mirror of https://github.com/doitsujin/dxvk
Compare commits
371 Commits
Author | SHA1 | Date |
---|---|---|
Blisto91 | 8d965359a5 | |
Philip Rebohle | fd978704fb | |
Tiagoquix | ee18aecb8a | |
Blisto91 | c2fd91f835 | |
Tiagoquix | 79eea564fb | |
Robin Kertels | 7df8017e46 | |
WinterSnowfall | c98152683f | |
Blisto91 | 890ad3f47f | |
Robin Kertels | 60cfafe027 | |
Robin Kertels | 889802887f | |
WinterSnowfall | a1ce690c5c | |
WinterSnowfall | 07d007c642 | |
Danylo Piliaiev | 58d8ea2d31 | |
Philip Rebohle | 61bd62c327 | |
Philip Rebohle | 7bc77b597e | |
Simon McVittie | 2ff2c826a5 | |
Simon McVittie | f9b4046223 | |
Simon McVittie | 83436a97f2 | |
Ethan Lee | e991bfa604 | |
Ethan Lee | f33453afbb | |
Robin Kertels | 65dd3c7df3 | |
Robin Kertels | dfc3776b24 | |
Philip Rebohle | 3420cd78ac | |
Philip Rebohle | 4225f35034 | |
Philip Rebohle | 2cb2f8694e | |
Blisto91 | c1f665f92b | |
WinterSnowfall | 20185a5309 | |
Blisto91 | 0c2efda804 | |
Blisto91 | c7d61b2fc0 | |
Ethan Lee | 6259e86392 | |
Ethan Lee | d5d236a1e2 | |
Ethan Lee | 10b83d184b | |
Ethan Lee | 0f7c1f753a | |
Ethan Lee | 529129c332 | |
Ethan Lee | 4055a92856 | |
Blisto91 | 7bad17c1d1 | |
Blisto91 | 6b76d70d9d | |
Philip Rebohle | 611dc60018 | |
WinterSnowfall | b2789ab894 | |
Philip Rebohle | ab715a8876 | |
talkingerbil | 1fb35b6d19 | |
Rémi Bernon | 4333ee872d | |
Rémi Bernon | b99d42c688 | |
Blisto91 | dacb8b434b | |
Philip Rebohle | ea4cb84d8a | |
Philip Rebohle | 65373792d2 | |
Lierrmm | 29253da356 | |
Robin Kertels | 79398b468d | |
Robin Kertels | e7d14e97de | |
Philip Rebohle | c613078ba8 | |
Philip Rebohle | 2970645f33 | |
Philip Rebohle | 462165da19 | |
Philip Rebohle | 3f27a0ee58 | |
Katharine Chui | aac3396671 | |
Katharine Chui | 92a43ebf65 | |
Blisto91 | 8ba5256dc7 | |
Philip Rebohle | 2b70ba8f77 | |
Philip Rebohle | 9c66c4bf1d | |
Philip Rebohle | 00872e9e4f | |
Philip Rebohle | 35157357dd | |
Philip Rebohle | 617ebf4e05 | |
Philip Rebohle | c2489d5a45 | |
Philip Rebohle | 6ef98c613f | |
Philip Rebohle | 7441137a33 | |
WinterSnowfall | 571948cfc0 | |
Martino Fontana | 133f0794bc | |
Philip Rebohle | 44695f9311 | |
Casey Bowman | 49e9ea5f5a | |
Blisto91 | 198bd3a4b8 | |
Philip Rebohle | f06c646315 | |
Philip Rebohle | 855b2746b6 | |
Blisto91 | 28c7c09bf5 | |
Philip Rebohle | 2742486540 | |
Philip Rebohle | 037d0fa1ad | |
Philip Rebohle | cbf51a7a25 | |
Philip Rebohle | 70e34dc31c | |
Philip Rebohle | c5aeb0f87a | |
Philip Rebohle | a163082770 | |
Blisto91 | 2e1a19c7fd | |
Joshua Ashton | 0beb18ef73 | |
Joshua Ashton | ef4428ab8c | |
Philip Rebohle | 1085ba713e | |
Philip Rebohle | e857b09432 | |
Kaitlyn | 538f1d13d4 | |
Kaitlyn | 783c9d4591 | |
Kaitlyn | 1a685b1c67 | |
Robin Kertels | 8b8be7c2bf | |
Billy Laws | 0776d764a4 | |
Robin Kertels | 15ddadc4de | |
Philip Rebohle | 69a52b3da0 | |
Philip Rebohle | 707ad6f328 | |
Philip Rebohle | 3a6992ea97 | |
Robin Kertels | 72c86b8229 | |
Robin Kertels | 85215b10d6 | |
Philip Rebohle | fd3fbf6607 | |
Minelelol | 0a699fddb6 | |
Blisto91 | afec5cce88 | |
Ethan Lee | 4b0e3111d1 | |
Philip Rebohle | 0414bbe2d5 | |
Robin Kertels | 20490b678f | |
Blisto91 | 428c98bc63 | |
Robin Kertels | a0e39e94fa | |
Robin Kertels | eaa732d0b3 | |
Robin Kertels | 49b18f03fe | |
Philip Rebohle | c9cea93b7b | |
Philip Rebohle | 69d74a46a0 | |
Philip Rebohle | 94098aa97d | |
Philip Rebohle | c677ba9b3e | |
Philip Rebohle | 77c7396ee1 | |
Philip Rebohle | f07e5f9eaa | |
Philip Rebohle | d5c3011f54 | |
Blisto91 | 6b3b934471 | |
Philip Rebohle | 9004c132ed | |
Philip Rebohle | 24d4c9c938 | |
Philip Rebohle | 5ded7d67f0 | |
Philip Rebohle | 234f3ea071 | |
Robin Kertels | c5a37d443a | |
Robin Kertels | f254afb4fb | |
Robin Kertels | 39c19e9299 | |
Robin Kertels | 738fd4f895 | |
Philip Rebohle | 9491b56beb | |
Robin Kertels | ab3593185f | |
Robin Kertels | e9a0fec5b3 | |
Echo J | fae78407a2 | |
Robin Kertels | 5312ef1cf9 | |
Robin Kertels | 62d64bd63a | |
Robin Kertels | f83ba898af | |
Ethan Lee | 30f2b2df31 | |
Philip Rebohle | 05cb963e22 | |
Philip Rebohle | eb339bc7e4 | |
Ethan Lee | c423819e90 | |
Tatsuyuki Ishi | e2a46a347d | |
Tatsuyuki Ishi | afc6aa70fb | |
Tatsuyuki Ishi | 799aeff560 | |
Robin Kertels | 2ca8fdf890 | |
Robin Kertels | 0841f5faf4 | |
Ethan Lee | 2334bbccb0 | |
Robin Kertels | 7d9864c077 | |
Dean Beeler | d4c5fc74e7 | |
Tatsuyuki Ishi | 6199776869 | |
Tatsuyuki Ishi | 6faf3c1acd | |
Tatsuyuki Ishi | ab6bd8b17f | |
Tatsuyuki Ishi | 89267b62ad | |
Blisto91 | 34d8e65fd7 | |
Joshua Ashton | 1568c263fb | |
Joshua Ashton | 0cd4165658 | |
Joshua Ashton | 4b8e8bed6e | |
r-a-sattarov | ac78048c23 | |
Richard Yao | 14560600a9 | |
Blisto91 | 854e06d3f0 | |
Blisto91 | eb806952d8 | |
Blisto91 | a44dfabe26 | |
spiffeeroo | 5e06cf9573 | |
Blisto91 | 2cf590f636 | |
Robin Kertels | a7a63b37c3 | |
Robin Kertels | 9cde0b5798 | |
Blisto91 | adb33d3af1 | |
Philip Rebohle | 1b31aa5dbc | |
Philip Rebohle | 03c09ce15f | |
Blisto91 | 91f7f43c35 | |
Robin Kertels | d998dee46e | |
Philip Rebohle | ea3149801f | |
xpander69 | 1cb58b0732 | |
Philip Rebohle | 2ed1778df9 | |
Philip Rebohle | a427d22cde | |
Joshua Ashton | 22c2abb9b7 | |
Blisto91 | f45911a28f | |
Blisto91 | e00db24557 | |
Paul Gofman | 552d2f0a6d | |
WinterSnowfall | 4d974685c9 | |
Blisto91 | f0ff0007dc | |
Robin Kertels | 494f7fd38d | |
WinterSnowfall | 0632da1935 | |
Philip Rebohle | 83dc4678df | |
Paul Gofman | f93cfbc26a | |
Philip Rebohle | c113b791a1 | |
Ellie Hermaszewska | 41191af3b1 | |
Philip Rebohle | 5828f0e2b9 | |
Philip Rebohle | 80e075406b | |
Margen67 | a53f0e8168 | |
Margen67 | 4705de5725 | |
Robin Kertels | 9e26964a96 | |
Blisto91 | ce2f9f35ce | |
Philip Rebohle | a3fa9c26dc | |
Joshua Ashton | ff5507769a | |
WinterSnowfall | 5c56fa0df4 | |
Tatsuyuki Ishi | 7e10021eac | |
Joshua Ashton | bbd1d84cd0 | |
Jens Peters | 02db89ac30 | |
Philip Rebohle | 92dc61f161 | |
Philip Rebohle | 6a5ed02db3 | |
Philip Rebohle | 64828e2c6c | |
Philip Rebohle | a4f2a49a02 | |
Philip Rebohle | aa41a7a351 | |
Philip Rebohle | fb71c08d8c | |
Philip Rebohle | 79f6239df3 | |
Philip Rebohle | 53a68635b2 | |
Philip Rebohle | 179c5ec998 | |
Philip Rebohle | d6e0107e23 | |
Joshua Ashton | 428ca9416d | |
Joshua Ashton | c26f40229a | |
Joshua Ashton | 8226690298 | |
Joshua Ashton | 138f727fbb | |
Philip Rebohle | c2cd129b89 | |
Philip Rebohle | 915244c00c | |
Blisto91 | 6fce094942 | |
Robin Kertels | 740ebec7ee | |
Robin Kertels | bcaaac4ad7 | |
Joshua Ashton | 1130512db5 | |
Blisto91 | 143eb8c710 | |
Philip Rebohle | 4ae542e875 | |
Philip Rebohle | 952c66fe2a | |
Philip Rebohle | b6a7714e67 | |
Etaash Mathamsetty | 037669f715 | |
Robin Kertels | 295a58afdf | |
Robin Kertels | 0746a3b91a | |
Etaash Mathamsetty | 429555a540 | |
Blisto91 | dfcd7aedd8 | |
gofman | cbda22a040 | |
Georg Lehmann | 549bd86f03 | |
WinterSnowfall | b0b46fd075 | |
Joshua Ashton | a62117cd13 | |
pchome | e598dcd77e | |
Philip Rebohle | 09857dcaa9 | |
Philip Rebohle | d66f8385c3 | |
Philip Rebohle | 007e9f4c89 | |
Philip Rebohle | 9b019d26ac | |
Philip Rebohle | 228615b639 | |
Ellie Hermaszewska | dfbebba6b5 | |
Blisto91 | 4ed04268fd | |
Blisto91 | 4ed1474030 | |
Blisto91 | 13440a5d89 | |
Blisto91 | 1daae75048 | |
Philip Rebohle | b4d87eaac0 | |
Philip Rebohle | 1e11db98d0 | |
Philip Rebohle | f689ddd838 | |
Philip Rebohle | eed43c8524 | |
Philip Rebohle | d066fbbaed | |
Philip Rebohle | a67c99943a | |
Philip Rebohle | 5ece97f769 | |
Philip Rebohle | 228cd4c331 | |
Blisto91 | 98f3887680 | |
Blisto91 | 3a9a70b5f0 | |
Philip Rebohle | 878da4984b | |
Philip Rebohle | c599f95e5d | |
Paul Gofman | 4893788d9b | |
Paul Gofman | fc952a3ca3 | |
Paul Gofman | 01ad79278b | |
Paul Gofman | 48557886de | |
Paul Gofman | 8319793a98 | |
Blisto91 | 886268fcf9 | |
Hans-Kristian Arntzen | 84e59fc9e5 | |
Blisto91 | 6be1f6d7bd | |
Joshua Ashton | 2f72115f91 | |
Alpyne | 026aa49ef8 | |
Trevonn | 3a368f4780 | |
Tatsuyuki Ishi | 2ef41bdbf6 | |
Philip Rebohle | 0f4458e173 | |
Philip Rebohle | ccb87d5ea9 | |
Alpyne | 022bf1d134 | |
Alpyne | d6e7e3e780 | |
Blisto91 | b77928b6fe | |
Philip Rebohle | 987df8a487 | |
Philip Rebohle | a7278cdab1 | |
Joshua Ashton | 3b3ebc9350 | |
Joshua Ashton | 00ae118655 | |
Joshua Ashton | 55be12daa5 | |
Joshua Ashton | 0e36a07a93 | |
Joshua Ashton | ff65599dba | |
Joshua Ashton | 6b60de2d31 | |
Joshua Ashton | 362743c1d6 | |
Joshua Ashton | 7f302fc350 | |
Philip Rebohle | 8704ed7af6 | |
Philip Rebohle | 0895858901 | |
Joshua Ashton | 80b27f95bc | |
Joshua Ashton | a791493d14 | |
Joshua Ashton | c768196251 | |
Joshua Ashton | 3625c5d481 | |
Philip Rebohle | b3cbe36c08 | |
Philip Rebohle | 166d90b04c | |
Robin Kertels | 60b6e98529 | |
Robin Kertels | a20869fb93 | |
Philip Rebohle | a287566c65 | |
Philip Rebohle | 28f48f9fdc | |
Philip Rebohle | e02a800c33 | |
Philip Rebohle | d7fa39c4eb | |
Philip Rebohle | d1e39be7e7 | |
Philip Rebohle | 438c535fe7 | |
Philip Rebohle | 7dbe4abb48 | |
Philip Rebohle | e99bc591df | |
Philip Rebohle | 08363edb05 | |
Philip Rebohle | 5d1196733b | |
Philip Rebohle | ca3492570c | |
Philip Rebohle | 215c4f8f6f | |
Robin Kertels | 5a1ebfa4ee | |
Joshua Ashton | 6f87ccdafc | |
Joshua Ashton | b30a4f0cc7 | |
Joshua Ashton | 4e9853f608 | |
Joshua Ashton | 5fbb0dd4ba | |
Joshua Ashton | 77f6f2a84b | |
Alpyne | 0b9acf3a25 | |
Timo Gurr | 211d095ee4 | |
Trevonn | 77e7e8bfba | |
Alpyne | 42a0264e69 | |
Alpyne | 5d29140f74 | |
Alpyne | 0236e780a7 | |
Alpyne | 24dbcf8fd8 | |
Alpyne | 404c984f9c | |
Alpyne | a79772322b | |
Trevonn | 36e6a7c2e5 | |
Trevonn | c5ab5be48d | |
Paul Gofman | af9bd16b8d | |
Winter Snowfall | 2c014fdb34 | |
Timo Gurr | 6478c10a18 | |
Philip Rebohle | 7388c243d2 | |
Lilium | bd575a4a46 | |
Lilium | 3fce9886f5 | |
Lilium | 5d134b877a | |
Robin Kertels | c75ed86909 | |
Robin Kertels | d1707026f9 | |
Robin Kertels | b8d36eeacc | |
Robin Kertels | 8f740c53b4 | |
Robin Kertels | 52ac271acb | |
Robin Kertels | a1a91dd766 | |
Robin Kertels | 22f6246fd6 | |
Robin Kertels | 9d6804e40a | |
Robin Kertels | 5fd025c513 | |
Robin Kertels | d9d6316609 | |
Robin Kertels | 9b877cf623 | |
Robin Kertels | 2c3f2b9ad1 | |
Robin Kertels | 1850819483 | |
Robin Kertels | 1db2e3a6ec | |
Robin Kertels | 2efd3f3698 | |
Robin Kertels | bbaf01d9e6 | |
Robin Kertels | 4a55047dde | |
Joshua Ashton | 3fddc364ee | |
Blisto91 | f3fb5ba320 | |
Philip Rebohle | 4d254b13be | |
Joshua Ashton | d241daa0b1 | |
Eric Sullivan | 2e70a2b07d | |
Robin Kertels | 52f04ca3d4 | |
Joshua Ashton | c585ea251e | |
Philip Rebohle | ab00591297 | |
Philip Rebohle | 85d52ccb88 | |
Philip Rebohle | e6be0cf996 | |
Philip Rebohle | 1728d9e89d | |
Philip Rebohle | b1b0abdbbf | |
Philip Rebohle | be875cd7e6 | |
Philip Rebohle | 0543956ea0 | |
Blisto91 | e9e0949717 | |
WinterSnowfall | 8b6cbda6de | |
Robin Kertels | 4b10846008 | |
Joshua Ashton | e0654977c9 | |
Joshua Ashton | b5c18a02ae | |
Joshua Ashton | cafd104783 | |
Joshua Ashton | 269bab2c34 | |
Joshua Ashton | 075c0bf203 | |
Joshua Ashton | 8560efa3c7 | |
Blisto91 | b9b2db510e | |
Lilium | d5c6ae2e4d | |
Lilium | 633f6663a4 | |
Robin Kertels | d2759c20ba | |
Robin Kertels | 1a2e724c16 | |
Blisto91 | 6449f583f8 | |
Joshua Ashton | f2bb1d4b69 | |
Joshua Ashton | 495dc75ab2 | |
Paul Gofman | 550e04c579 | |
WinterSnowfall | d4a7346198 | |
Blisto91 | 99b367cdd6 | |
Blisto91 | 65520fa18e | |
Joshua Ashton | f30376a1e4 |
|
@ -9,13 +9,13 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
id: checkout-code
|
id: checkout-code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup problem matcher
|
- name: Setup problem matcher
|
||||||
uses: Joshua-Ashton/gcc-problem-matcher@v2
|
uses: Joshua-Ashton/gcc-problem-matcher@v3
|
||||||
|
|
||||||
- name: Build release
|
- name: Build release
|
||||||
id: build-release
|
id: build-release
|
||||||
|
@ -28,9 +28,9 @@ jobs:
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
id: upload-artifacts
|
id: upload-artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: dxvk-${{ env.VERSION_NAME }}
|
name: dxvk-win-${{ env.VERSION_NAME }}
|
||||||
path: build/dxvk-${{ env.VERSION_NAME }}
|
path: build/dxvk-${{ env.VERSION_NAME }}
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
|
@ -41,26 +41,43 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
id: checkout-code
|
id: checkout-code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup problem matcher
|
- name: Setup problem matcher
|
||||||
uses: Joshua-Ashton/gcc-problem-matcher@v2
|
uses: Joshua-Ashton/gcc-problem-matcher@v3
|
||||||
|
|
||||||
- name: Build release
|
- name: Build release
|
||||||
id: build-release
|
id: build-release
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
export VERSION_NAME="${GITHUB_REF##*/}-${GITHUB_SHA##*/}"
|
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
|
echo "VERSION_NAME=${VERSION_NAME}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
id: upload-artifacts
|
id: upload-artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: dxvk-${{ env.VERSION_NAME }}
|
name: dxvk-native-${{ env.VERSION_NAME }}
|
||||||
path: build/dxvk-native-${{ env.VERSION_NAME }}
|
path: build/dxvk-native-${{ env.VERSION_NAME }}.tar.gz
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
|
merge-artifacts:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
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
|
||||||
|
|
|
@ -9,16 +9,15 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
id: checkout-code
|
id: checkout-code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Setup glslangValidator
|
- name: Setup glslangValidator
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
choco install vulkan-sdk -y
|
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/HansKristian-Work/vkd3d-proton-ci/main/glslangValidator.exe" -OutFile "glslangValidator.exe"
|
||||||
Write-Output "$([System.Environment]::GetEnvironmentVariable('VULKAN_SDK', 'Machine'))\Bin" `
|
Write-Output "$pwd" | Out-File -FilePath "${Env:GITHUB_PATH}" -Append
|
||||||
| Out-File -FilePath "${Env:GITHUB_PATH}" -Append
|
|
||||||
|
|
||||||
- name: Setup Meson
|
- name: Setup Meson
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
57
README.md
57
README.md
|
@ -9,20 +9,32 @@ The most recent development builds can be found [here](https://github.com/doitsu
|
||||||
Release builds can be found [here](https://github.com/doitsujin/dxvk/releases).
|
Release builds can be found [here](https://github.com/doitsujin/dxvk/releases).
|
||||||
|
|
||||||
## How to use
|
## 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 DLL overrides for `d3d11`, `d3d10core`, `dxgi`, and `d3d9`.
|
||||||
|
|
||||||
|
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 x64/*.dll $WINEPREFIX/drive_c/windows/system32
|
||||||
cp x32/*.dll $WINEPREFIX/drive_c/windows/syswow64
|
cp x32/*.dll $WINEPREFIX/drive_c/windows/syswow64
|
||||||
winecfg
|
winecfg
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that this is **not** an error, 64-bit DLLs are indeed supposed to go to the `system32` directory. Please refrain from opening issues or pull requests to change that, the instructions are correct as they are.
|
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 by enabling the HUD (see notes below).
|
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.
|
In order to remove DXVK from a prefix, remove the DLLs and DLL overrides, and run `wineboot -u` to restore the original DLL files.
|
||||||
|
|
||||||
|
Tools such as Steam Play, Lutris, Bottles, Heroic Launcher, etc will automatically handle setup of dxvk on their own when enabled.
|
||||||
|
|
||||||
|
### Notes on Vulkan drivers
|
||||||
|
Before reporting an issue, please check the [Wiki](https://github.com/doitsujin/dxvk/wiki/Driver-support) page on the current driver status and make sure you run a recent enough driver version for your hardware.
|
||||||
|
|
||||||
## Build instructions
|
## Build instructions
|
||||||
|
|
||||||
In order to pull in all submodules that are needed for building, clone the repository using the following command:
|
In order to pull in all submodules that are needed for building, clone the repository using the following command:
|
||||||
|
@ -66,9 +78,6 @@ 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 D3D9, D3D10, D3D11 and DXGI DLLs will be located in `/your/dxvk/directory/bin`. Setup has to be done manually in this case.
|
||||||
|
|
||||||
### Notes on Vulkan drivers
|
|
||||||
Before reporting an issue, please check the [Wiki](https://github.com/doitsujin/dxvk/wiki/Driver-support) page on the current driver status and make sure you run a recent enough driver version for your hardware.
|
|
||||||
|
|
||||||
### Online multi-player games
|
### 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.**
|
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.**
|
||||||
|
|
||||||
|
@ -94,6 +103,7 @@ The `DXVK_HUD` environment variable controls a HUD which can display the framera
|
||||||
- `compiler`: Shows shader compiler activity
|
- `compiler`: Shows shader compiler activity
|
||||||
- `samplers`: Shows the current number of sampler pairs used *[D3D9 Only]*
|
- `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`)
|
- `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.
|
Additionally, `DXVK_HUD=1` has the same effect as `DXVK_HUD=devinfo,fps`, and `DXVK_HUD=full` enables all available HUD elements.
|
||||||
|
|
||||||
|
@ -106,6 +116,15 @@ Some applications do not provide a method to select a different GPU. In that cas
|
||||||
|
|
||||||
**Note:** If the device filter is configured incorrectly, it may filter out all devices and applications will be unable to create a D3D device.
|
**Note:** If the device filter is configured incorrectly, it may filter out all devices and applications will be unable to create a D3D device.
|
||||||
|
|
||||||
|
### Graphics Pipeline Library
|
||||||
|
On drivers which support `VK_EXT_graphics_pipeline_library` Vulkan shaders will be compiled at the time the game loads its D3D shaders, rather than at draw time. This reduces or eliminates shader compile stutter in many games when compared to the previous system.
|
||||||
|
|
||||||
|
In games that load their shaders during loading screens or in the menu, this can lead to prolonged periods of very high CPU utilization, especially on weaker CPUs. For affected games it is recommended to wait for shader compilation to finish before starting the game to avoid stutter and low performance. Shader compiler activity can be monitored with `DXVK_HUD=compiler`.
|
||||||
|
|
||||||
|
This feature largely replaces the state cache.
|
||||||
|
|
||||||
|
**Note:** Games which only load their D3D shaders at draw time (e.g. most Unreal Engine games) will still exhibit some stutter, although it should still be less severe than without this feature.
|
||||||
|
|
||||||
### State cache
|
### 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.
|
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.
|
||||||
|
|
||||||
|
@ -115,13 +134,16 @@ The following environment variables can be used to control the cache:
|
||||||
- `reset`: Clears the cache file.
|
- `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.
|
- `DXVK_STATE_CACHE_PATH=/some/directory` Specifies a directory where to put the cache files. Defaults to the current working directory of the application.
|
||||||
|
|
||||||
|
This feature is mostly only relevant on systems without support for `VK_EXT_graphics_pipeline_library`
|
||||||
|
|
||||||
### Debugging
|
### Debugging
|
||||||
The following environment variables can be used for **debugging** purposes.
|
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.
|
- `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_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_LOG_PATH=/some/directory` Changes path where log files are stored. Set to `none` to disable log file creation entirely, without disabling logging.
|
||||||
- `DXVK_CONFIG_FILE=/xxx/dxvk.conf` Sets path to the configuration file.
|
|
||||||
- `DXVK_DEBUG=markers|validation` Enables use of the `VK_EXT_debug_utils` extension for translating performance event markers, or to enable Vulkan validation, respecticely.
|
- `DXVK_DEBUG=markers|validation` Enables use of the `VK_EXT_debug_utils` extension for translating performance event markers, or to enable Vulkan validation, respecticely.
|
||||||
|
- `DXVK_CONFIG_FILE=/xxx/dxvk.conf` Sets path to the configuration file.
|
||||||
|
- `DXVK_CONFIG="dxgi.hideAmdGpu = True; dxgi.syncInterval = 0"` Can be used to set config variables through the environment instead of a configuration file using the same syntax. `;` is used as a seperator.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
DXVK requires threading support from your mingw-w64 build environment. If you
|
DXVK requires threading support from your mingw-w64 build environment. If you
|
||||||
|
@ -141,3 +163,22 @@ For non debian based distros, make sure that your mingw-w64-gcc cross compiler
|
||||||
does have `--enable-threads=posix` enabled during configure. If your distro does
|
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
|
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.
|
recompile locally or open a bug at your distro's bugtracker to ask for it.
|
||||||
|
|
||||||
|
# DXVK Native
|
||||||
|
|
||||||
|
DXVK Native is a version of DXVK which allows it to be used natively without Wine.
|
||||||
|
|
||||||
|
This is primarily useful for game and application ports to either avoid having to write another rendering backend, or to help with port bringup during development.
|
||||||
|
|
||||||
|
[Release builds](https://github.com/doitsujin/dxvk/releases) are built using the Steam Runtime.
|
||||||
|
|
||||||
|
### How does it work?
|
||||||
|
|
||||||
|
DXVK Native replaces certain Windows-isms with a platform and framework-agnostic replacement, for example, `HWND`s can become `SDL_Window*`s, etc.
|
||||||
|
All it takes to do that is to add another WSI backend.
|
||||||
|
|
||||||
|
**Note:** DXVK Native requires a backend to be explicitly set via the `DXVK_WSI_DRIVER` environment variable. The current built-in options are `SDL2` and `GLFW`.
|
||||||
|
|
||||||
|
DXVK Native comes with a slim set of Windows header definitions required for D3D9/11 and the MinGW headers for D3D9/11.
|
||||||
|
In most cases, it will end up being plug and play with your renderer, but there may be certain teething issues such as:
|
||||||
|
- `__uuidof(type)` is supported, but `__uuidof(variable)` is not supported. Use `__uuidof_var(variable)` instead.
|
||||||
|
|
153
dxvk.conf
153
dxvk.conf
|
@ -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)
|
# Expose the HDR10 ColorSpace (DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
|
||||||
# to the application by default.
|
# to the application by default.
|
||||||
# This shows to the game that the global Windows 'HDR Mode' is enabled.
|
# This shows to the game that the global Windows 'HDR Mode' is enabled.
|
||||||
|
@ -10,6 +17,7 @@
|
||||||
|
|
||||||
# dxgi.enableHDR = True
|
# dxgi.enableHDR = True
|
||||||
|
|
||||||
|
|
||||||
# Create the VkSurface on the first call to IDXGISwapChain::Present,
|
# Create the VkSurface on the first call to IDXGISwapChain::Present,
|
||||||
# rather than when creating the swap chain. Some games that start
|
# rather than when creating the swap chain. Some games that start
|
||||||
# rendering with a different graphics API may require this option,
|
# rendering with a different graphics API may require this option,
|
||||||
|
@ -61,18 +69,43 @@
|
||||||
# d3d9.customDeviceDesc = ""
|
# d3d9.customDeviceDesc = ""
|
||||||
|
|
||||||
|
|
||||||
# Report Nvidia GPUs as AMD GPUs by default. This is enabled by default
|
# Report Nvidia GPUs as AMD GPUs. Unless NVAPI support is explicitly
|
||||||
# to work around issues with NVAPI, but may cause issues in some games.
|
# 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
|
# Override maximum amount of device memory and shared system memory
|
||||||
# reported to the application. This may fix texture streaming issues
|
# reported to the application. This may fix texture streaming issues
|
||||||
# in games that do not support cards with large amounts of VRAM.
|
# in games that do not support cards with large amounts of VRAM.
|
||||||
|
# This is not a hard cap and applications can choose to ignore it.
|
||||||
#
|
#
|
||||||
# Supported values: Any number in Megabytes.
|
# Supported values: Any number in Megabytes.
|
||||||
|
|
||||||
|
@ -122,8 +155,7 @@
|
||||||
#
|
#
|
||||||
# Supported values: Auto, True, False
|
# Supported values: Auto, True, False
|
||||||
|
|
||||||
# dxgi.tearFree = Auto
|
# dxvk.tearFree = Auto
|
||||||
# d3d9.tearFree = Auto
|
|
||||||
|
|
||||||
|
|
||||||
# Assume single-use mode for command lists created on deferred contexts.
|
# Assume single-use mode for command lists created on deferred contexts.
|
||||||
|
@ -190,6 +222,16 @@
|
||||||
# Supported values: Any number between -2.0 and 1.0
|
# Supported values: Any number between -2.0 and 1.0
|
||||||
|
|
||||||
# d3d11.samplerLodBias = 0.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
|
# Declares vertex positions as invariant in order to solve
|
||||||
|
@ -266,6 +308,32 @@
|
||||||
# d3d11.enableContextLock = False
|
# d3d11.enableContextLock = False
|
||||||
|
|
||||||
|
|
||||||
|
# Exposes or hides support for driver command lists
|
||||||
|
#
|
||||||
|
# Some games use the feature flag to decide whether to use deferred
|
||||||
|
# contexts or not. We enable this by default, but in some situations
|
||||||
|
# this can lead to issues if games detect an AMD GPU where command
|
||||||
|
# lists are not natively supported on Windows.
|
||||||
|
#
|
||||||
|
# Supported values: True, False
|
||||||
|
|
||||||
|
# d3d11.exposeDriverCommandLists = True
|
||||||
|
|
||||||
|
|
||||||
|
# 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.
|
# Sets number of pipeline compiler threads.
|
||||||
#
|
#
|
||||||
# If the graphics pipeline library feature is enabled, the given
|
# If the graphics pipeline library feature is enabled, the given
|
||||||
|
@ -453,6 +521,7 @@
|
||||||
# Supported values:
|
# Supported values:
|
||||||
# - True/False
|
# - True/False
|
||||||
|
|
||||||
|
# d3d11.longMad = False
|
||||||
# d3d9.longMad = False
|
# d3d9.longMad = False
|
||||||
|
|
||||||
# Device Local Constant Buffers
|
# Device Local Constant Buffers
|
||||||
|
@ -466,18 +535,11 @@
|
||||||
|
|
||||||
# d3d9.deviceLocalConstantBuffers = False
|
# d3d9.deviceLocalConstantBuffers = False
|
||||||
|
|
||||||
# No Explicit Front Buffer
|
|
||||||
#
|
|
||||||
# Disables the front buffer
|
|
||||||
#
|
|
||||||
# Supported values:
|
|
||||||
# - True/False
|
|
||||||
|
|
||||||
# d3d9.noExplicitFrontBuffer = False
|
|
||||||
|
|
||||||
# Support DF formats
|
# 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:
|
# Supported values:
|
||||||
# - True/False
|
# - True/False
|
||||||
|
@ -496,7 +558,7 @@
|
||||||
# Support X4R4G4B4
|
# Support X4R4G4B4
|
||||||
#
|
#
|
||||||
# Support the X4R4G4B4 format.
|
# 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:
|
# Supported values:
|
||||||
# - True/False
|
# - True/False
|
||||||
|
@ -515,7 +577,7 @@
|
||||||
# Disable A8 as a Render Target
|
# Disable A8 as a Render Target
|
||||||
#
|
#
|
||||||
# Disable support for A8 format render targets
|
# 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:
|
# Supported values:
|
||||||
# - True/False
|
# - True/False
|
||||||
|
@ -555,16 +617,6 @@
|
||||||
|
|
||||||
# d3d9.forceAspectRatio = ""
|
# 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
|
# Enumerate by Displays
|
||||||
#
|
#
|
||||||
# Whether we should enumerate D3D9 adapters by display (windows behaviour)
|
# Whether we should enumerate D3D9 adapters by display (windows behaviour)
|
||||||
|
@ -576,16 +628,17 @@
|
||||||
|
|
||||||
# d3d9.enumerateByDisplays = True
|
# d3d9.enumerateByDisplays = True
|
||||||
|
|
||||||
# APITrace Mode
|
# Cached Dynamic Buffers
|
||||||
#
|
#
|
||||||
# Makes all host visible buffers cached and coherent
|
# Allocates dynamic resources in D3DPOOL_DEFAULT in
|
||||||
# Improves performance when apitracing, but also can impact
|
# cached system memory rather than uncached memory or host-visible
|
||||||
# some dumb games.
|
# 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:
|
# Supported values:
|
||||||
# - True/False
|
# - True/False
|
||||||
|
|
||||||
# d3d9.apitraceMode = False
|
# d3d9.cachedDynamicBuffers = False
|
||||||
|
|
||||||
# Seamless Cubes
|
# Seamless Cubes
|
||||||
#
|
#
|
||||||
|
@ -615,3 +668,37 @@
|
||||||
# DO NOT CHANGE THIS UNLESS YOU HAVE A VERY GOOD REASON.
|
# DO NOT CHANGE THIS UNLESS YOU HAVE A VERY GOOD REASON.
|
||||||
|
|
||||||
# d3d9.textureMemory = 100
|
# 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
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
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_sdl2.h',
|
||||||
|
'wsi/native_glfw.h',
|
||||||
|
subdir: 'dxvk/wsi',
|
||||||
|
)
|
|
@ -31,6 +31,9 @@ typedef wchar_t WCHAR;
|
||||||
typedef WCHAR *NWPSTR, *LPWSTR, *PWSTR;
|
typedef WCHAR *NWPSTR, *LPWSTR, *PWSTR;
|
||||||
typedef unsigned char UCHAR, *PUCHAR;
|
typedef unsigned char UCHAR, *PUCHAR;
|
||||||
|
|
||||||
|
typedef char CHAR;
|
||||||
|
typedef const CHAR *LPCSTR, *PCSTR;
|
||||||
|
|
||||||
typedef INT BOOL;
|
typedef INT BOOL;
|
||||||
typedef BOOL WINBOOL;
|
typedef BOOL WINBOOL;
|
||||||
|
|
||||||
|
@ -45,7 +48,6 @@ typedef const void* LPCVOID;
|
||||||
typedef size_t SIZE_T;
|
typedef size_t SIZE_T;
|
||||||
|
|
||||||
typedef int8_t INT8;
|
typedef int8_t INT8;
|
||||||
|
|
||||||
typedef uint8_t UINT8;
|
typedef uint8_t UINT8;
|
||||||
typedef uint8_t BYTE;
|
typedef uint8_t BYTE;
|
||||||
|
|
||||||
|
@ -53,9 +55,13 @@ typedef int16_t SHORT;
|
||||||
typedef uint16_t USHORT;
|
typedef uint16_t USHORT;
|
||||||
|
|
||||||
typedef int64_t LONGLONG;
|
typedef int64_t LONGLONG;
|
||||||
|
typedef int64_t INT64;
|
||||||
|
|
||||||
typedef uint64_t ULONGLONG;
|
typedef uint64_t ULONGLONG;
|
||||||
|
typedef uint64_t UINT64;
|
||||||
|
|
||||||
typedef intptr_t LONG_PTR;
|
typedef intptr_t LONG_PTR;
|
||||||
|
typedef uintptr_t ULONG_PTR;
|
||||||
|
|
||||||
typedef float FLOAT;
|
typedef float FLOAT;
|
||||||
|
|
||||||
|
@ -208,6 +214,11 @@ typedef struct RGNDATA {
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
|
|
||||||
|
#define WAIT_TIMEOUT 0x00000102
|
||||||
|
#define WAIT_FAILED 0xffffffff
|
||||||
|
#define WAIT_OBJECT_0 0
|
||||||
|
#define WAIT_ABANDONED 0x00000080
|
||||||
|
|
||||||
#define interface struct
|
#define interface struct
|
||||||
#define MIDL_INTERFACE(x) struct
|
#define MIDL_INTERFACE(x) struct
|
||||||
|
|
||||||
|
@ -322,12 +333,21 @@ typedef struct RGNDATA {
|
||||||
#define DECLARE_INTERFACE(x) struct x
|
#define DECLARE_INTERFACE(x) struct x
|
||||||
#define DECLARE_INTERFACE_(x, y) struct x : public y
|
#define DECLARE_INTERFACE_(x, y) struct x : public y
|
||||||
#else
|
#else
|
||||||
|
#ifdef CONST_VTABLE
|
||||||
#define DECLARE_INTERFACE(x) \
|
#define DECLARE_INTERFACE(x) \
|
||||||
typedef interface x { \
|
typedef interface x { \
|
||||||
const struct x##Vtbl *lpVtbl; \
|
const struct x##Vtbl *lpVtbl; \
|
||||||
} x; \
|
} x; \
|
||||||
typedef const struct x##Vtbl x##Vtbl; \
|
typedef const struct x##Vtbl x##Vtbl; \
|
||||||
const struct 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)
|
#define DECLARE_INTERFACE_(x, y) DECLARE_INTERFACE(x)
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
namespace dxvk::wsi {
|
namespace dxvk::wsi {
|
||||||
|
|
||||||
|
@ -22,4 +22,4 @@ namespace dxvk::wsi {
|
||||||
return reinterpret_cast<HMONITOR>(static_cast<intptr_t>(displayId + 1));
|
return reinterpret_cast<HMONITOR>(static_cast<intptr_t>(displayId + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0bcc624926a25a2a273d07877fd25a6ff5ba1cfb
|
Subproject commit 8b246ff75c6615ba4532fe4fde20f1be090c3764
|
|
@ -1 +1 @@
|
||||||
Subproject commit 98f440ce6868c94f5ec6e198cc1adda4760e8849
|
Subproject commit 46dc0f6e514f5730784bb2cac2a7c731636839e8
|
112
meson.build
112
meson.build
|
@ -1,11 +1,13 @@
|
||||||
project('dxvk', ['c', 'cpp'], version : 'v2.2', meson_version : '>= 0.49', default_options : [ 'cpp_std=c++17', 'warning_level=2' ])
|
project('dxvk', ['c', 'cpp'], version : 'v2.3.1', meson_version : '>= 0.58', default_options : [ 'cpp_std=c++17', 'warning_level=2' ])
|
||||||
|
|
||||||
|
pkg = import('pkgconfig')
|
||||||
cpu_family = target_machine.cpu_family()
|
cpu_family = target_machine.cpu_family()
|
||||||
platform = target_machine.system()
|
platform = target_machine.system()
|
||||||
|
fs = import('fs')
|
||||||
|
|
||||||
cpp = meson.get_compiler('cpp')
|
cpp = meson.get_compiler('cpp')
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
dxvk_is_msvc = cpp.get_id() == 'msvc'
|
dxvk_is_msvc = cpp.get_argument_syntax() == 'msvc'
|
||||||
|
|
||||||
compiler_args = [
|
compiler_args = [
|
||||||
'-msse',
|
'-msse',
|
||||||
|
@ -33,44 +35,61 @@ if get_option('build_id')
|
||||||
]
|
]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dxvk_include_dirs = [
|
dxvk_include_dirs = ['./include']
|
||||||
'./include',
|
if fs.is_dir('./include/vulkan/include')
|
||||||
'./include/vulkan/include',
|
dxvk_include_dirs += ['./include/vulkan/include']
|
||||||
'./include/spirv/include'
|
elif not cpp.check_header('vulkan/vulkan.h')
|
||||||
]
|
error('Missing Vulkan-Headers')
|
||||||
|
endif
|
||||||
|
if fs.is_dir('./include/spirv/include')
|
||||||
|
dxvk_include_dirs += ['./include/spirv/include']
|
||||||
|
elif not cpp.check_header('spirv/unified1/spirv.hpp')
|
||||||
|
error('Missing SPIRV-Headers')
|
||||||
|
endif
|
||||||
|
|
||||||
proj_displayinfo = subproject('libdisplay-info')
|
dep_displayinfo = dependency(
|
||||||
dep_displayinfo = proj_displayinfo.get_variable('di_dep')
|
'libdisplay-info',
|
||||||
|
version: ['>= 0.0.0', '< 0.2.0'],
|
||||||
|
fallback: ['libdisplay-info', 'di_dep'],
|
||||||
|
default_options: ['default_library=static'],
|
||||||
|
)
|
||||||
|
|
||||||
if platform == 'windows'
|
if platform == 'windows'
|
||||||
|
dxvk_so_version = {'name_prefix': ''}
|
||||||
|
|
||||||
compiler_args += [
|
compiler_args += [
|
||||||
'-DNOMINMAX',
|
'-DNOMINMAX',
|
||||||
'-D_WIN32_WINNT=0xa00',
|
'-D_WIN32_WINNT=0xa00',
|
||||||
]
|
]
|
||||||
|
|
||||||
link_args += [
|
if not dxvk_is_msvc
|
||||||
'-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'
|
|
||||||
link_args += [
|
link_args += [
|
||||||
'-Wl,--enable-stdcall-fixup',
|
'-static',
|
||||||
'-Wl,--add-stdcall-alias',
|
'-static-libgcc',
|
||||||
]
|
'-static-libstdc++',
|
||||||
|
# We need to set the section alignment for debug symbols to
|
||||||
|
# work properly as well as avoiding a memcpy from the Wine loader.
|
||||||
|
'-Wl,--file-alignment=4096',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Wine's built-in back traces only work with dwarf4 symbols
|
||||||
|
if get_option('debug')
|
||||||
|
compiler_args += [
|
||||||
|
'-gdwarf-4',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Enable stdcall fixup on 32-bit
|
||||||
|
if cpu_family == 'x86'
|
||||||
|
link_args += [
|
||||||
|
'-Wl,--enable-stdcall-fixup',
|
||||||
|
'-Wl,--kill-at',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
link_args += [
|
||||||
|
'/FILEALIGN:4096',
|
||||||
|
]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lib_d3d9 = cpp.find_library('d3d9')
|
lib_d3d9 = cpp.find_library('d3d9')
|
||||||
|
@ -99,10 +118,13 @@ if platform == 'windows'
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dxvk_wsi = 'win32'
|
|
||||||
dxvk_name_prefix = ''
|
dxvk_name_prefix = ''
|
||||||
compiler_args += ['-DDXVK_WSI_WIN32']
|
compiler_args += ['-DDXVK_WSI_WIN32']
|
||||||
else
|
else
|
||||||
|
dxvk_abi_version = '0'
|
||||||
|
dxvk_version = meson.project_version().strip('v').split('.')
|
||||||
|
dxvk_so_version = {'version': dxvk_abi_version + '.' + dxvk_version[0] + dxvk_version[1] + dxvk_version[2]}
|
||||||
|
|
||||||
wrc = find_program('touch')
|
wrc = find_program('touch')
|
||||||
wrc_generator = generator(wrc, output : [ '@BASENAME@_ignored.h' ], arguments : [ '@OUTPUT@' ] )
|
wrc_generator = generator(wrc, output : [ '@BASENAME@_ignored.h' ], arguments : [ '@OUTPUT@' ] )
|
||||||
|
|
||||||
|
@ -112,17 +134,20 @@ else
|
||||||
'./include/native/directx'
|
'./include/native/directx'
|
||||||
]
|
]
|
||||||
|
|
||||||
dxvk_wsi = get_option('dxvk_native_wsi')
|
lib_sdl2 = dependency('SDL2', required: false)
|
||||||
|
lib_glfw = dependency('glfw', required: false)
|
||||||
if dxvk_wsi == 'sdl2'
|
if lib_sdl2.found()
|
||||||
lib_sdl2 = cpp.find_library('SDL2')
|
|
||||||
compiler_args += ['-DDXVK_WSI_SDL2']
|
compiler_args += ['-DDXVK_WSI_SDL2']
|
||||||
elif dxvk_wsi == 'glfw'
|
endif
|
||||||
lib_glfw = cpp.find_library('glfw')
|
if lib_glfw.found()
|
||||||
compiler_args += ['-DDXVK_WSI_GLFW']
|
compiler_args += ['-DDXVK_WSI_GLFW']
|
||||||
endif
|
endif
|
||||||
|
if (not lib_sdl2.found() and not lib_glfw.found())
|
||||||
|
error('SDL2 or GLFW are required to build dxvk-native')
|
||||||
|
endif
|
||||||
|
|
||||||
dxvk_name_prefix = 'libdxvk_'
|
dxvk_name_prefix = 'dxvk_'
|
||||||
|
dxvk_pkg_prefix = 'dxvk-'
|
||||||
|
|
||||||
link_args += [
|
link_args += [
|
||||||
'-static-libgcc',
|
'-static-libgcc',
|
||||||
|
@ -138,13 +163,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')
|
add_project_link_arguments(cc.get_supported_link_arguments(link_args), language: 'c')
|
||||||
|
|
||||||
exe_ext = ''
|
exe_ext = ''
|
||||||
dll_ext = ''
|
|
||||||
def_spec_ext = '.def'
|
def_spec_ext = '.def'
|
||||||
|
|
||||||
glsl_compiler = find_program('glslangValidator')
|
glsl_compiler = find_program('glslang', 'glslangValidator')
|
||||||
glsl_args = [
|
glsl_args = [
|
||||||
'--quiet',
|
'--quiet',
|
||||||
'--target-env', 'vulkan1.2',
|
'--target-env', 'vulkan1.3',
|
||||||
'--vn', '@BASENAME@',
|
'--vn', '@BASENAME@',
|
||||||
'--depfile', '@DEPFILE@',
|
'--depfile', '@DEPFILE@',
|
||||||
'@INPUT@',
|
'@INPUT@',
|
||||||
|
@ -163,4 +187,8 @@ dxvk_version = vcs_tag(
|
||||||
output: 'version.h',
|
output: 'version.h',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if platform != 'windows'
|
||||||
|
subdir('include/native')
|
||||||
|
endif
|
||||||
|
|
||||||
subdir('src')
|
subdir('src')
|
||||||
|
|
|
@ -56,13 +56,14 @@ function build_arch {
|
||||||
opt_strip=--strip
|
opt_strip=--strip
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CC="$CC -m$1" CXX="$CXX -m$1" meson setup \
|
CC="$CC -m$1" CXX="$CXX -m$1" meson setup \
|
||||||
--buildtype "release" \
|
--buildtype "release" \
|
||||||
--prefix "$DXVK_BUILD_DIR/usr" \
|
--prefix "$DXVK_BUILD_DIR/usr" \
|
||||||
$opt_strip \
|
$opt_strip \
|
||||||
--bindir "$2" \
|
--bindir "$2" \
|
||||||
--libdir "$2" \
|
--libdir "$2" \
|
||||||
-Dbuild_id=$opt_buildid \
|
-Dbuild_id=$opt_buildid \
|
||||||
|
--force-fallback-for=libdisplay-info \
|
||||||
"$DXVK_BUILD_DIR/build.$1"
|
"$DXVK_BUILD_DIR/build.$1"
|
||||||
|
|
||||||
cd "$DXVK_BUILD_DIR/build.$1"
|
cd "$DXVK_BUILD_DIR/build.$1"
|
||||||
|
|
|
@ -9,10 +9,14 @@ extern "C" {
|
||||||
HRESULT __stdcall D3D11CoreCreateDevice(
|
HRESULT __stdcall D3D11CoreCreateDevice(
|
||||||
IDXGIFactory* pFactory,
|
IDXGIFactory* pFactory,
|
||||||
IDXGIAdapter* pAdapter,
|
IDXGIAdapter* pAdapter,
|
||||||
|
D3D_DRIVER_TYPE DriverType,
|
||||||
|
HMODULE Software,
|
||||||
UINT Flags,
|
UINT Flags,
|
||||||
const D3D_FEATURE_LEVEL* pFeatureLevels,
|
const D3D_FEATURE_LEVEL* pFeatureLevels,
|
||||||
UINT FeatureLevels,
|
UINT FeatureLevels,
|
||||||
ID3D11Device** ppDevice);
|
UINT SDKVersion,
|
||||||
|
ID3D11Device** ppDevice,
|
||||||
|
D3D_FEATURE_LEVEL* pFeatureLevel);
|
||||||
|
|
||||||
|
|
||||||
DLLEXPORT HRESULT __stdcall D3D10CoreCreateDevice(
|
DLLEXPORT HRESULT __stdcall D3D10CoreCreateDevice(
|
||||||
|
@ -31,8 +35,8 @@ extern "C" {
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
hr = D3D11CoreCreateDevice(pFactory, pAdapter,
|
hr = D3D11CoreCreateDevice(pFactory, pAdapter, D3D_DRIVER_TYPE_UNKNOWN,
|
||||||
Flags, &FeatureLevel, 1, &d3d11Device);
|
nullptr, Flags, &FeatureLevel, 1, D3D11_SDK_VERSION, &d3d11Device, nullptr);
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
|
@ -7,21 +7,31 @@ d3d10_core_src = [
|
||||||
d3d10_core_ld_args = []
|
d3d10_core_ld_args = []
|
||||||
d3d10_core_link_depends = []
|
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_ld_args += [ '-Wl,--version-script', join_paths(meson.current_source_dir(), 'd3d10core.sym') ]
|
||||||
d3d10_core_link_depends += files('d3d10core.sym')
|
d3d10_core_link_depends += files('d3d10core.sym')
|
||||||
|
d3d10_d3d11_dep = d3d11_dep
|
||||||
endif
|
endif
|
||||||
|
|
||||||
d3d10_core_dll = shared_library('d3d10core'+dll_ext, d3d10_core_src, d3d10_core_res,
|
d3d10_core_dll = shared_library(dxvk_name_prefix+'d3d10core', d3d10_core_src, d3d10_core_res,
|
||||||
name_prefix : dxvk_name_prefix,
|
dependencies : [ d3d10_d3d11_dep ],
|
||||||
dependencies : [ d3d11_dep ],
|
|
||||||
include_directories : dxvk_include_path,
|
include_directories : dxvk_include_path,
|
||||||
install : true,
|
install : true,
|
||||||
vs_module_defs : 'd3d10core'+def_spec_ext,
|
vs_module_defs : 'd3d10core'+def_spec_ext,
|
||||||
link_args : d3d10_core_ld_args,
|
link_args : d3d10_core_ld_args,
|
||||||
link_depends : [ d3d10_core_link_depends ],
|
link_depends : [ d3d10_core_link_depends ],
|
||||||
|
kwargs : dxvk_so_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
d3d10_core_dep = declare_dependency(
|
d3d10_core_dep = declare_dependency(
|
||||||
link_with : [ d3d10_core_dll ],
|
link_with : [ d3d10_core_dll ],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if platform != 'windows'
|
||||||
|
pkg.generate(d3d10_core_dll,
|
||||||
|
filebase: dxvk_pkg_prefix + 'd3d10core',
|
||||||
|
subdirs: 'dxvk',
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace dxvk {
|
||||||
const D3D11_ON_12_RESOURCE_INFO* p11on12Info)
|
const D3D11_ON_12_RESOURCE_INFO* p11on12Info)
|
||||||
: D3D11DeviceChild<ID3D11Buffer>(pDevice),
|
: D3D11DeviceChild<ID3D11Buffer>(pDevice),
|
||||||
m_desc (*pDesc),
|
m_desc (*pDesc),
|
||||||
m_resource (this),
|
m_resource (this, pDevice),
|
||||||
m_d3d10 (this) {
|
m_d3d10 (this) {
|
||||||
DxvkBufferCreateInfo info;
|
DxvkBufferCreateInfo info;
|
||||||
info.flags = 0;
|
info.flags = 0;
|
||||||
|
@ -339,6 +339,7 @@ namespace dxvk {
|
||||||
|| (m_parent->GetOptions()->cachedDynamicResources & m_desc.BindFlags);
|
|| (m_parent->GetOptions()->cachedDynamicResources & m_desc.BindFlags);
|
||||||
|
|
||||||
if ((memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && useCached) {
|
if ((memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && useCached) {
|
||||||
|
memoryFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||||
memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||||
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
|
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -386,11 +386,16 @@ namespace dxvk {
|
||||||
const UINT Values[4]) {
|
const UINT Values[4]) {
|
||||||
D3D10DeviceLock lock = LockContext();
|
D3D10DeviceLock lock = LockContext();
|
||||||
|
|
||||||
auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
|
if (!pUnorderedAccessView)
|
||||||
|
|
||||||
if (!uav)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Com<ID3D11UnorderedAccessView> qiUav;
|
||||||
|
|
||||||
|
if (FAILED(pUnorderedAccessView->QueryInterface(IID_PPV_ARGS(&qiUav))))
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto uav = static_cast<D3D11UnorderedAccessView*>(qiUav.ptr());
|
||||||
|
|
||||||
// Gather UAV format info. We'll use this to determine
|
// Gather UAV format info. We'll use this to determine
|
||||||
// whether we need to create a temporary view or not.
|
// whether we need to create a temporary view or not.
|
||||||
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
|
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
|
||||||
|
@ -406,15 +411,22 @@ namespace dxvk {
|
||||||
|
|
||||||
VkClearValue clearValue;
|
VkClearValue clearValue;
|
||||||
|
|
||||||
// R11G11B10 is a special case since there's no corresponding
|
if (uavDesc.Format == DXGI_FORMAT_R11G11B10_FLOAT) {
|
||||||
// integer format with the same bit layout. Use R32 instead.
|
// R11G11B10 is a special case since there's no corresponding
|
||||||
if (uavFormat == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
|
// integer format with the same bit layout. Use R32 instead.
|
||||||
clearValue.color.uint32[0] = ((Values[0] & 0x7FF) << 0)
|
clearValue.color.uint32[0] = ((Values[0] & 0x7FF) << 0)
|
||||||
| ((Values[1] & 0x7FF) << 11)
|
| ((Values[1] & 0x7FF) << 11)
|
||||||
| ((Values[2] & 0x3FF) << 22);
|
| ((Values[2] & 0x3FF) << 22);
|
||||||
clearValue.color.uint32[1] = 0;
|
clearValue.color.uint32[1] = 0;
|
||||||
clearValue.color.uint32[2] = 0;
|
clearValue.color.uint32[2] = 0;
|
||||||
clearValue.color.uint32[3] = 0;
|
clearValue.color.uint32[3] = 0;
|
||||||
|
} else if (uavDesc.Format == DXGI_FORMAT_A8_UNORM) {
|
||||||
|
// We need to use R8_UINT to clear A8_UNORM images,
|
||||||
|
// so remap the alpha component to the red channel.
|
||||||
|
clearValue.color.uint32[0] = Values[3];
|
||||||
|
clearValue.color.uint32[1] = 0;
|
||||||
|
clearValue.color.uint32[2] = 0;
|
||||||
|
clearValue.color.uint32[3] = 0;
|
||||||
} else {
|
} else {
|
||||||
clearValue.color.uint32[0] = Values[0];
|
clearValue.color.uint32[0] = Values[0];
|
||||||
clearValue.color.uint32[1] = Values[1];
|
clearValue.color.uint32[1] = Values[1];
|
||||||
|
@ -916,6 +928,34 @@ namespace dxvk {
|
||||||
const void* pSrcData,
|
const void* pSrcData,
|
||||||
UINT SrcRowPitch,
|
UINT SrcRowPitch,
|
||||||
UINT SrcDepthPitch) {
|
UINT SrcDepthPitch) {
|
||||||
|
if (IsDeferred && unlikely(pDstBox != nullptr) && unlikely(!m_parent->GetOptions()->exposeDriverCommandLists)) {
|
||||||
|
// If called from a deferred context and native command list support is not
|
||||||
|
// exposed, we need to apply the destination box to the source pointer. This
|
||||||
|
// only applies to UpdateSubresource, not to UpdateSubresource1. See MSDN:
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476486(v=vs.85).aspx)
|
||||||
|
size_t srcOffset = pDstBox->left;
|
||||||
|
|
||||||
|
// For textures, the offset logic needs to take the format into account.
|
||||||
|
// Ignore that multi-planar images exist, this is hairy enough already.
|
||||||
|
D3D11CommonTexture* dstTexture = GetCommonTexture(pDstResource);
|
||||||
|
|
||||||
|
if (dstTexture) {
|
||||||
|
auto dstFormat = dstTexture->GetPackedFormat();
|
||||||
|
auto dstFormatInfo = lookupFormatInfo(dstFormat);
|
||||||
|
|
||||||
|
size_t blockSize = dstFormatInfo->elementSize;
|
||||||
|
|
||||||
|
VkOffset3D offset;
|
||||||
|
offset.x = pDstBox->left / dstFormatInfo->blockSize.width;
|
||||||
|
offset.y = pDstBox->top / dstFormatInfo->blockSize.height;
|
||||||
|
offset.z = pDstBox->front / dstFormatInfo->blockSize.depth;
|
||||||
|
|
||||||
|
srcOffset = offset.x * blockSize + offset.y * SrcRowPitch + offset.z * SrcDepthPitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSrcData = reinterpret_cast<const char*>(pSrcData) + srcOffset;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateResource(pDstResource, DstSubresource, pDstBox,
|
UpdateResource(pDstResource, DstSubresource, pDstBox,
|
||||||
pSrcData, SrcRowPitch, SrcDepthPitch, 0);
|
pSrcData, SrcRowPitch, SrcDepthPitch, 0);
|
||||||
}
|
}
|
||||||
|
@ -3389,8 +3429,24 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static VkDepthBiasRepresentationEXT FormatToDepthBiasRepresentation(DXGI_FORMAT format) {
|
||||||
|
switch (format) {
|
||||||
|
default:
|
||||||
|
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
||||||
|
case DXGI_FORMAT_D32_FLOAT:
|
||||||
|
return VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_D24_UNORM_S8_UINT:
|
||||||
|
case DXGI_FORMAT_D16_UNORM:
|
||||||
|
return VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ContextType>
|
template<typename ContextType>
|
||||||
void D3D11CommonContext<ContextType>::BindFramebuffer() {
|
void D3D11CommonContext<ContextType>::BindFramebuffer() {
|
||||||
|
DxvkDepthBiasRepresentation depthBiasRepresentation =
|
||||||
|
{ VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT,
|
||||||
|
m_device->features().extDepthBiasControl.depthBiasExact };
|
||||||
DxvkRenderTargets attachments;
|
DxvkRenderTargets attachments;
|
||||||
uint32_t sampleCount = 0;
|
uint32_t sampleCount = 0;
|
||||||
|
|
||||||
|
@ -3411,12 +3467,17 @@ namespace dxvk {
|
||||||
m_state.om.dsv->GetImageView(),
|
m_state.om.dsv->GetImageView(),
|
||||||
m_state.om.dsv->GetRenderLayout() };
|
m_state.om.dsv->GetRenderLayout() };
|
||||||
sampleCount = m_state.om.dsv->GetSampleCount();
|
sampleCount = m_state.om.dsv->GetSampleCount();
|
||||||
|
|
||||||
|
if (m_device->features().extDepthBiasControl.leastRepresentableValueForceUnormRepresentation)
|
||||||
|
depthBiasRepresentation.depthBiasRepresentation = FormatToDepthBiasRepresentation(m_state.om.dsv->GetViewFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and bind the framebuffer object to the context
|
// Create and bind the framebuffer object to the context
|
||||||
EmitCs([
|
EmitCs([
|
||||||
cAttachments = std::move(attachments)
|
cAttachments = std::move(attachments),
|
||||||
|
cRepresentation = depthBiasRepresentation
|
||||||
] (DxvkContext* ctx) mutable {
|
] (DxvkContext* ctx) mutable {
|
||||||
|
ctx->setDepthBiasRepresentation(cRepresentation);
|
||||||
ctx->bindRenderTargets(Forwarder::move(cAttachments), 0u);
|
ctx->bindRenderTargets(Forwarder::move(cAttachments), 0u);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5380,6 +5441,7 @@ namespace dxvk {
|
||||||
pRsState->conservativeMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
|
pRsState->conservativeMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
|
||||||
pRsState->sampleCount = 0;
|
pRsState->sampleCount = 0;
|
||||||
pRsState->flatShading = VK_FALSE;
|
pRsState->flatShading = VK_FALSE;
|
||||||
|
pRsState->lineMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1130,7 +1130,7 @@ namespace dxvk {
|
||||||
if (likely(pBuffer != nullptr))
|
if (likely(pBuffer != nullptr))
|
||||||
bufferSize = static_cast<D3D11Buffer*>(pBuffer)->Desc()->ByteWidth;
|
bufferSize = static_cast<D3D11Buffer*>(pBuffer)->Desc()->ByteWidth;
|
||||||
|
|
||||||
return bufferSize >= Offset + Size;
|
return uint64_t(bufferSize) >= uint64_t(Offset) + uint64_t(Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace dxvk {
|
||||||
m_csThread(Device, Device->createContext(DxvkContextType::Primary)),
|
m_csThread(Device, Device->createContext(DxvkContextType::Primary)),
|
||||||
m_maxImplicitDiscardSize(pParent->GetOptions()->maxImplicitDiscardSize),
|
m_maxImplicitDiscardSize(pParent->GetOptions()->maxImplicitDiscardSize),
|
||||||
m_submissionFence(new sync::CallbackFence()),
|
m_submissionFence(new sync::CallbackFence()),
|
||||||
|
m_flushTracker(pParent->GetOptions()->reproducibleCommandStream),
|
||||||
m_multithread(this, false, pParent->GetOptions()->enableContextLock),
|
m_multithread(this, false, pParent->GetOptions()->enableContextLock),
|
||||||
m_videoContext(this, Device) {
|
m_videoContext(this, Device) {
|
||||||
EmitCs([
|
EmitCs([
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace dxvk {
|
||||||
friend class D3D11CommonContext<D3D11ImmediateContext>;
|
friend class D3D11CommonContext<D3D11ImmediateContext>;
|
||||||
friend class D3D11SwapChain;
|
friend class D3D11SwapChain;
|
||||||
friend class D3D11VideoContext;
|
friend class D3D11VideoContext;
|
||||||
|
friend class D3D11DXGIKeyedMutex;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
D3D11ImmediateContext(
|
D3D11ImmediateContext(
|
||||||
|
@ -88,6 +89,10 @@ namespace dxvk {
|
||||||
void SynchronizeCsThread(
|
void SynchronizeCsThread(
|
||||||
uint64_t SequenceNumber);
|
uint64_t SequenceNumber);
|
||||||
|
|
||||||
|
D3D10Multithread& GetMultithread() {
|
||||||
|
return m_multithread;
|
||||||
|
}
|
||||||
|
|
||||||
D3D10DeviceLock LockContext() {
|
D3D10DeviceLock LockContext() {
|
||||||
return m_multithread.AcquireLock();
|
return m_multithread.AcquireLock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace dxvk {
|
||||||
|
|
||||||
if (riid == __uuidof(ID3D10DeviceChild)
|
if (riid == __uuidof(ID3D10DeviceChild)
|
||||||
|| riid == __uuidof(ID3D10DepthStencilState)) {
|
|| riid == __uuidof(ID3D10DepthStencilState)) {
|
||||||
*ppvObject = ref(this);
|
*ppvObject = ref(&m_d3d10);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,10 +45,10 @@ namespace dxvk {
|
||||||
m_dxvkDevice (pContainer->GetDXVKDevice()),
|
m_dxvkDevice (pContainer->GetDXVKDevice()),
|
||||||
m_dxvkAdapter (m_dxvkDevice->adapter()),
|
m_dxvkAdapter (m_dxvkDevice->adapter()),
|
||||||
m_d3d11Formats (m_dxvkDevice),
|
m_d3d11Formats (m_dxvkDevice),
|
||||||
m_d3d11Options (m_dxvkDevice->instance()->config(), m_dxvkDevice),
|
m_d3d11Options (m_dxvkDevice->instance()->config()),
|
||||||
m_dxbcOptions (m_dxvkDevice, m_d3d11Options),
|
m_dxbcOptions (m_dxvkDevice, m_d3d11Options),
|
||||||
m_maxFeatureLevel (GetMaxFeatureLevel(m_dxvkDevice->instance(), m_dxvkDevice->adapter())),
|
m_maxFeatureLevel (GetMaxFeatureLevel(m_dxvkDevice->instance(), m_dxvkDevice->adapter())),
|
||||||
m_deviceFeatures (m_dxvkDevice->instance(), m_dxvkDevice->adapter(), m_featureLevel) {
|
m_deviceFeatures (m_dxvkDevice->instance(), m_dxvkDevice->adapter(), m_d3d11Options, m_featureLevel) {
|
||||||
m_initializer = new D3D11Initializer(this);
|
m_initializer = new D3D11Initializer(this);
|
||||||
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
|
m_context = new D3D11ImmediateContext(this, m_dxvkDevice);
|
||||||
m_d3d10Device = new D3D10Device(this, m_context.ptr());
|
m_d3d10Device = new D3D10Device(this, m_context.ptr());
|
||||||
|
@ -1348,7 +1348,7 @@ namespace dxvk {
|
||||||
m_deviceFeatures = D3D11DeviceFeatures(
|
m_deviceFeatures = D3D11DeviceFeatures(
|
||||||
m_dxvkDevice->instance(),
|
m_dxvkDevice->instance(),
|
||||||
m_dxvkDevice->adapter(),
|
m_dxvkDevice->adapter(),
|
||||||
m_featureLevel);
|
m_d3d11Options, m_featureLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pChosenFeatureLevel)
|
if (pChosenFeatureLevel)
|
||||||
|
@ -1953,6 +1953,11 @@ namespace dxvk {
|
||||||
enabled.core.features.shaderFloat64 = supported.core.features.shaderFloat64;
|
enabled.core.features.shaderFloat64 = supported.core.features.shaderFloat64;
|
||||||
enabled.core.features.shaderInt64 = supported.core.features.shaderInt64;
|
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;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2304,6 +2309,10 @@ namespace dxvk {
|
||||||
d3d11Desc.CPUAccessFlags = metadata.CPUAccessFlags;
|
d3d11Desc.CPUAccessFlags = metadata.CPUAccessFlags;
|
||||||
d3d11Desc.MiscFlags = metadata.MiscFlags;
|
d3d11Desc.MiscFlags = metadata.MiscFlags;
|
||||||
d3d11Desc.TextureLayout = metadata.TextureLayout;
|
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
|
// Only 2D textures may be shared
|
||||||
try {
|
try {
|
||||||
|
@ -3402,8 +3411,9 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::EnqueueSetEvent(HANDLE hEvent) {
|
HRESULT STDMETHODCALLTYPE D3D11DXGIDevice::EnqueueSetEvent(HANDLE hEvent) {
|
||||||
Logger::err("D3D11DXGIDevice::EnqueueSetEvent: Not implemented");
|
auto immediateContext = m_d3d11Device.GetContext();
|
||||||
return DXGI_ERROR_UNSUPPORTED;
|
immediateContext->Flush1(D3D11_CONTEXT_TYPE_ALL, hEvent);
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace dxvk {
|
||||||
D3D11DeviceFeatures::D3D11DeviceFeatures(
|
D3D11DeviceFeatures::D3D11DeviceFeatures(
|
||||||
const Rc<DxvkInstance>& Instance,
|
const Rc<DxvkInstance>& Instance,
|
||||||
const Rc<DxvkAdapter>& Adapter,
|
const Rc<DxvkAdapter>& Adapter,
|
||||||
|
const D3D11Options& Options,
|
||||||
D3D_FEATURE_LEVEL FeatureLevel)
|
D3D_FEATURE_LEVEL FeatureLevel)
|
||||||
: m_features (Adapter->features()),
|
: m_features (Adapter->features()),
|
||||||
m_properties (Adapter->devicePropertiesExt()) {
|
m_properties (Adapter->devicePropertiesExt()) {
|
||||||
|
@ -107,7 +108,7 @@ namespace dxvk {
|
||||||
m_gpuVirtualAddress.MaxGPUVirtualAddressBitsPerProcess = 40;
|
m_gpuVirtualAddress.MaxGPUVirtualAddressBitsPerProcess = 40;
|
||||||
|
|
||||||
// Marker support only depends on the debug utils extension
|
// 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
|
// 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.
|
// 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.PixelShaderMinPrecision = 0;
|
||||||
m_shaderMinPrecision.AllOtherShaderStagesMinPrecision = 0;
|
m_shaderMinPrecision.AllOtherShaderStagesMinPrecision = 0;
|
||||||
|
|
||||||
// Report native support for command lists here so that we do not actually have
|
// Report native support for command lists by default. Deferred context
|
||||||
// to re-implement the UpdateSubresource bug from the D3D11 runtime, see MSDN:
|
// usage can be beneficial for us as ExecuteCommandList has low overhead,
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476486(v=vs.85).aspx)
|
// and we avoid having to deal with known UpdateSubresource bugs this way.
|
||||||
m_threading.DriverConcurrentCreates = TRUE;
|
m_threading.DriverConcurrentCreates = TRUE;
|
||||||
m_threading.DriverCommandLists = TRUE;
|
m_threading.DriverCommandLists = Options.exposeDriverCommandLists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,7 +183,8 @@ namespace dxvk {
|
||||||
D3D_FEATURE_LEVEL D3D11DeviceFeatures::GetMaxFeatureLevel(
|
D3D_FEATURE_LEVEL D3D11DeviceFeatures::GetMaxFeatureLevel(
|
||||||
const Rc<DxvkInstance>& Instance,
|
const Rc<DxvkInstance>& Instance,
|
||||||
const Rc<DxvkAdapter>& Adapter) {
|
const Rc<DxvkAdapter>& Adapter) {
|
||||||
D3D11DeviceFeatures features(Instance, Adapter, D3D_FEATURE_LEVEL_12_1);
|
D3D11Options options(Instance->config());
|
||||||
|
D3D11DeviceFeatures features(Instance, Adapter, options, D3D_FEATURE_LEVEL_12_1);
|
||||||
return features.GetMaxFeatureLevel();
|
return features.GetMaxFeatureLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "d3d11_include.h"
|
#include "d3d11_include.h"
|
||||||
|
#include "d3d11_options.h"
|
||||||
|
|
||||||
#include "../dxvk/dxvk_adapter.h"
|
#include "../dxvk/dxvk_adapter.h"
|
||||||
#include "../dxvk/dxvk_instance.h"
|
#include "../dxvk/dxvk_instance.h"
|
||||||
|
@ -21,6 +22,7 @@ namespace dxvk {
|
||||||
D3D11DeviceFeatures(
|
D3D11DeviceFeatures(
|
||||||
const Rc<DxvkInstance>& Instance,
|
const Rc<DxvkInstance>& Instance,
|
||||||
const Rc<DxvkAdapter>& Adapter,
|
const Rc<DxvkAdapter>& Adapter,
|
||||||
|
const D3D11Options& Options,
|
||||||
D3D_FEATURE_LEVEL FeatureLevel);
|
D3D_FEATURE_LEVEL FeatureLevel);
|
||||||
|
|
||||||
~D3D11DeviceFeatures();
|
~D3D11DeviceFeatures();
|
||||||
|
|
|
@ -49,6 +49,8 @@ namespace dxvk {
|
||||||
InitHostVisibleTexture(pTexture, pInitialData);
|
InitHostVisibleTexture(pTexture, pInitialData);
|
||||||
else
|
else
|
||||||
InitDeviceLocalTexture(pTexture, pInitialData);
|
InitDeviceLocalTexture(pTexture, pInitialData);
|
||||||
|
|
||||||
|
SyncKeyedMutex(pTexture->GetInterface());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -284,4 +286,14 @@ namespace dxvk {
|
||||||
m_transferMemory = 0;
|
m_transferMemory = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11Initializer::SyncKeyedMutex(ID3D11Resource *pResource) {
|
||||||
|
Com<IDXGIKeyedMutex> keyedMutex;
|
||||||
|
if (pResource->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&keyedMutex)) != S_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
keyedMutex->AcquireSync(0, 0);
|
||||||
|
keyedMutex->ReleaseSync(0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -71,6 +71,8 @@ namespace dxvk {
|
||||||
void FlushImplicit();
|
void FlushImplicit();
|
||||||
void FlushInternal();
|
void FlushInternal();
|
||||||
|
|
||||||
|
void SyncKeyedMutex(ID3D11Resource *pResource);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -183,13 +183,7 @@ ID3D11VkExtContext1 : public ID3D11VkExtContext {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifndef _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
|
|
||||||
__CRT_UUID_DECL(ID3D11VkExtShader, 0xbb8a4fb9,0x3935,0x4762,0xb4,0x4b,0x35,0x18,0x9a,0x26,0x41,0x4a);
|
__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(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(ID3D11VkExtDevice1, 0xcfcf64ef,0x9586,0x46d0,0xbc,0xa4,0x97,0xcf,0x2c,0xa6,0x1b,0x06);
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace dxvk {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
using namespace dxvk;
|
using namespace dxvk;
|
||||||
|
|
||||||
DLLEXPORT HRESULT __stdcall D3D11CoreCreateDevice(
|
HRESULT D3D11InternalCreateDevice(
|
||||||
IDXGIFactory* pFactory,
|
IDXGIFactory* pFactory,
|
||||||
IDXGIAdapter* pAdapter,
|
IDXGIAdapter* pAdapter,
|
||||||
UINT Flags,
|
UINT Flags,
|
||||||
|
@ -34,11 +34,11 @@ extern "C" {
|
||||||
dxvkAdapter = dxgiVkAdapter->GetDXVKAdapter();
|
dxvkAdapter = dxgiVkAdapter->GetDXVKAdapter();
|
||||||
dxvkInstance = dxgiVkAdapter->GetDXVKInstance();
|
dxvkInstance = dxgiVkAdapter->GetDXVKInstance();
|
||||||
} else {
|
} else {
|
||||||
Logger::warn("D3D11CoreCreateDevice: Adapter is not a DXVK adapter");
|
Logger::warn("D3D11InternalCreateDevice: Adapter is not a DXVK adapter");
|
||||||
DXGI_ADAPTER_DESC desc;
|
DXGI_ADAPTER_DESC desc;
|
||||||
pAdapter->GetDesc(&desc);
|
pAdapter->GetDesc(&desc);
|
||||||
|
|
||||||
dxvkInstance = new DxvkInstance();
|
dxvkInstance = new DxvkInstance(0);
|
||||||
dxvkAdapter = dxvkInstance->findAdapterByLuid(&desc.AdapterLuid);
|
dxvkAdapter = dxvkInstance->findAdapterByLuid(&desc.AdapterLuid);
|
||||||
|
|
||||||
if (dxvkAdapter == nullptr)
|
if (dxvkAdapter == nullptr)
|
||||||
|
@ -70,7 +70,7 @@ extern "C" {
|
||||||
D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL();
|
D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL();
|
||||||
D3D_FEATURE_LEVEL devFeatureLevel = 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++) {
|
for (uint32_t flId = 0 ; flId < FeatureLevels; flId++) {
|
||||||
minFeatureLevel = pFeatureLevels[flId];
|
minFeatureLevel = pFeatureLevels[flId];
|
||||||
|
@ -82,12 +82,12 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!devFeatureLevel) {
|
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;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Logger::info(str::format("D3D11CoreCreateDevice: Using feature level ", devFeatureLevel));
|
Logger::info(str::format("D3D11InternalCreateDevice: Using feature level ", devFeatureLevel));
|
||||||
|
|
||||||
DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(dxvkAdapter);
|
DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(dxvkAdapter);
|
||||||
Rc<DxvkDevice> dxvkDevice = dxvkAdapter->createDevice(dxvkInstance, deviceFeatures);
|
Rc<DxvkDevice> dxvkDevice = dxvkAdapter->createDevice(dxvkInstance, deviceFeatures);
|
||||||
|
@ -101,7 +101,7 @@ extern "C" {
|
||||||
__uuidof(ID3D11Device),
|
__uuidof(ID3D11Device),
|
||||||
reinterpret_cast<void**>(ppDevice));
|
reinterpret_cast<void**>(ppDevice));
|
||||||
} catch (const DxvkError& e) {
|
} catch (const DxvkError& e) {
|
||||||
Logger::err("D3D11CoreCreateDevice: Failed to create D3D11 device");
|
Logger::err("D3D11InternalCreateDevice: Failed to create D3D11 device");
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the actual device
|
// Create the actual device
|
||||||
hr = D3D11CoreCreateDevice(
|
hr = D3D11InternalCreateDevice(
|
||||||
dxgiFactory.ptr(), dxgiAdapter.ptr(),
|
dxgiFactory.ptr(), dxgiAdapter.ptr(),
|
||||||
Flags, pFeatureLevels, FeatureLevels,
|
Flags, pFeatureLevels, FeatureLevels,
|
||||||
&device);
|
&device);
|
||||||
|
@ -212,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(
|
DLLEXPORT HRESULT __stdcall D3D11CreateDevice(
|
||||||
IDXGIAdapter* pAdapter,
|
IDXGIAdapter* pAdapter,
|
||||||
D3D_DRIVER_TYPE DriverType,
|
D3D_DRIVER_TYPE DriverType,
|
||||||
|
@ -357,7 +376,7 @@ extern "C" {
|
||||||
instanceInfo.extensionCount = instanceExtensions.size();
|
instanceInfo.extensionCount = instanceExtensions.size();
|
||||||
instanceInfo.extensionNames = instanceExtensions.data();
|
instanceInfo.extensionNames = instanceExtensions.data();
|
||||||
|
|
||||||
Rc<DxvkInstance> dxvkInstance = new DxvkInstance(instanceInfo);
|
Rc<DxvkInstance> dxvkInstance = new DxvkInstance(instanceInfo, 0);
|
||||||
|
|
||||||
// Find adapter by physical device handle
|
// Find adapter by physical device handle
|
||||||
Rc<DxvkAdapter> dxvkAdapter;
|
Rc<DxvkAdapter> dxvkAdapter;
|
||||||
|
|
|
@ -49,8 +49,6 @@ ID3D12DXVKInteropDevice : public IUnknown {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
struct __declspec(uuid("39da4e09-bd1c-4198-9fae-86bbe3be41fd")) ID3D12DXVKInteropDevice;
|
|
||||||
#else
|
|
||||||
__CRT_UUID_DECL(ID3D12DXVKInteropDevice, 0x39da4e09, 0xbd1c, 0x4198, 0x9f,0xae, 0x86,0xbb,0xe3,0xbe,0x41,0xfd)
|
__CRT_UUID_DECL(ID3D12DXVKInteropDevice, 0x39da4e09, 0xbd1c, 0x4198, 0x9f,0xae, 0x86,0xbb,0xe3,0xbe,0x41,0xfd)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace dxvk {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D11Options::D3D11Options(const Config& config, const Rc<DxvkDevice>& device) {
|
D3D11Options::D3D11Options(const Config& config) {
|
||||||
this->dcSingleUseMode = config.getOption<bool>("d3d11.dcSingleUseMode", true);
|
this->dcSingleUseMode = config.getOption<bool>("d3d11.dcSingleUseMode", true);
|
||||||
this->zeroInitWorkgroupMemory = config.getOption<bool>("d3d11.zeroInitWorkgroupMemory", false);
|
this->zeroInitWorkgroupMemory = config.getOption<bool>("d3d11.zeroInitWorkgroupMemory", false);
|
||||||
this->forceVolatileTgsmAccess = config.getOption<bool>("d3d11.forceVolatileTgsmAccess", false);
|
this->forceVolatileTgsmAccess = config.getOption<bool>("d3d11.forceVolatileTgsmAccess", false);
|
||||||
|
@ -21,6 +21,7 @@ namespace dxvk {
|
||||||
this->maxTessFactor = config.getOption<int32_t>("d3d11.maxTessFactor", 0);
|
this->maxTessFactor = config.getOption<int32_t>("d3d11.maxTessFactor", 0);
|
||||||
this->samplerAnisotropy = config.getOption<int32_t>("d3d11.samplerAnisotropy", -1);
|
this->samplerAnisotropy = config.getOption<int32_t>("d3d11.samplerAnisotropy", -1);
|
||||||
this->samplerLodBias = config.getOption<float>("d3d11.samplerLodBias", 0.0f);
|
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->invariantPosition = config.getOption<bool>("d3d11.invariantPosition", true);
|
||||||
this->floatControls = config.getOption<bool>("d3d11.floatControls", true);
|
this->floatControls = config.getOption<bool>("d3d11.floatControls", true);
|
||||||
this->forceSampleRateShading = config.getOption<bool>("d3d11.forceSampleRateShading", false);
|
this->forceSampleRateShading = config.getOption<bool>("d3d11.forceSampleRateShading", false);
|
||||||
|
@ -30,8 +31,9 @@ namespace dxvk {
|
||||||
this->numBackBuffers = config.getOption<int32_t>("dxgi.numBackBuffers", 0);
|
this->numBackBuffers = config.getOption<int32_t>("dxgi.numBackBuffers", 0);
|
||||||
this->maxFrameLatency = config.getOption<int32_t>("dxgi.maxFrameLatency", 0);
|
this->maxFrameLatency = config.getOption<int32_t>("dxgi.maxFrameLatency", 0);
|
||||||
this->maxFrameRate = config.getOption<int32_t>("dxgi.maxFrameRate", 0);
|
this->maxFrameRate = config.getOption<int32_t>("dxgi.maxFrameRate", 0);
|
||||||
this->syncInterval = config.getOption<int32_t>("dxgi.syncInterval", -1);
|
this->exposeDriverCommandLists = config.getOption<bool>("d3d11.exposeDriverCommandLists", true);
|
||||||
this->tearFree = config.getOption<Tristate>("dxgi.tearFree", Tristate::Auto);
|
this->longMad = config.getOption<bool>("d3d11.longMad", false);
|
||||||
|
this->reproducibleCommandStream = config.getOption<bool>("d3d11.reproducibleCommandStream", false);
|
||||||
|
|
||||||
// Clamp LOD bias so that people don't abuse this in unintended ways
|
// Clamp LOD bias so that people don't abuse this in unintended ways
|
||||||
this->samplerLodBias = dxvk::fclamp(this->samplerLodBias, -2.0f, 1.0f);
|
this->samplerLodBias = dxvk::fclamp(this->samplerLodBias, -2.0f, 1.0f);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
struct D3D11Options {
|
struct D3D11Options {
|
||||||
D3D11Options(const Config& config, const Rc<DxvkDevice>& device);
|
D3D11Options(const Config& config);
|
||||||
|
|
||||||
/// Enables speed hack for mapping on deferred contexts
|
/// Enables speed hack for mapping on deferred contexts
|
||||||
///
|
///
|
||||||
|
@ -63,6 +63,9 @@ namespace dxvk {
|
||||||
/// Enforces the given LOD bias for all samplers.
|
/// Enforces the given LOD bias for all samplers.
|
||||||
float samplerLodBias;
|
float samplerLodBias;
|
||||||
|
|
||||||
|
/// Clamps negative LOD bias
|
||||||
|
bool clampNegativeLodBias;
|
||||||
|
|
||||||
/// Declare vertex positions in shaders as invariant
|
/// Declare vertex positions in shaders as invariant
|
||||||
bool invariantPosition;
|
bool invariantPosition;
|
||||||
|
|
||||||
|
@ -73,14 +76,6 @@ namespace dxvk {
|
||||||
/// Overrides DXGI_SWAP_CHAIN_DESC::BufferCount.
|
/// Overrides DXGI_SWAP_CHAIN_DESC::BufferCount.
|
||||||
int32_t numBackBuffers;
|
int32_t numBackBuffers;
|
||||||
|
|
||||||
/// Sync interval. Overrides the value
|
|
||||||
/// passed to IDXGISwapChain::Present.
|
|
||||||
int32_t syncInterval;
|
|
||||||
|
|
||||||
/// Tear-free mode if vsync is disabled
|
|
||||||
/// Tearing mode if vsync is enabled
|
|
||||||
Tristate tearFree;
|
|
||||||
|
|
||||||
/// Override maximum frame latency if the app specifies
|
/// Override maximum frame latency if the app specifies
|
||||||
/// a higher value. May help with frame timing issues.
|
/// a higher value. May help with frame timing issues.
|
||||||
int32_t maxFrameLatency;
|
int32_t maxFrameLatency;
|
||||||
|
@ -118,8 +113,21 @@ namespace dxvk {
|
||||||
/// race conditions.
|
/// race conditions.
|
||||||
bool enableContextLock;
|
bool enableContextLock;
|
||||||
|
|
||||||
|
/// Whether to expose the driver command list feature. Enabled by
|
||||||
|
/// default and generally beneficial, but some games may assume that
|
||||||
|
/// this is not supported when running on an AMD GPU.
|
||||||
|
bool exposeDriverCommandLists;
|
||||||
|
|
||||||
/// Shader dump path
|
/// Shader dump path
|
||||||
std::string shaderDumpPath;
|
std::string shaderDumpPath;
|
||||||
|
|
||||||
|
/// Should we make our Mads a FFma or do it the long way with an FMul and an FAdd?
|
||||||
|
bool longMad;
|
||||||
|
|
||||||
|
/// 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -38,13 +38,22 @@ namespace dxvk {
|
||||||
m_state.conservativeMode = DecodeConservativeRasterizationMode(desc.ConservativeRaster);
|
m_state.conservativeMode = DecodeConservativeRasterizationMode(desc.ConservativeRaster);
|
||||||
m_state.sampleCount = VkSampleCountFlags(desc.ForcedSampleCount);
|
m_state.sampleCount = VkSampleCountFlags(desc.ForcedSampleCount);
|
||||||
m_state.flatShading = VK_FALSE;
|
m_state.flatShading = VK_FALSE;
|
||||||
|
m_state.lineMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
|
||||||
|
|
||||||
m_depthBias.depthBiasConstant = float(desc.DepthBias);
|
m_depthBias.depthBiasConstant = float(desc.DepthBias);
|
||||||
m_depthBias.depthBiasSlope = desc.SlopeScaledDepthBias;
|
m_depthBias.depthBiasSlope = desc.SlopeScaledDepthBias;
|
||||||
m_depthBias.depthBiasClamp = desc.DepthBiasClamp;
|
m_depthBias.depthBiasClamp = desc.DepthBiasClamp;
|
||||||
|
|
||||||
if (desc.AntialiasedLineEnable)
|
// Set up line rasterization mode
|
||||||
Logger::err("D3D11RasterizerState: Antialiased lines not supported");
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,138 @@
|
||||||
#include "d3d11_buffer.h"
|
#include "d3d11_buffer.h"
|
||||||
#include "d3d11_texture.h"
|
#include "d3d11_texture.h"
|
||||||
#include "d3d11_resource.h"
|
#include "d3d11_resource.h"
|
||||||
|
#include "d3d11_context_imm.h"
|
||||||
|
#include "d3d11_device.h"
|
||||||
|
|
||||||
#include "../util/util_shared_res.h"
|
#include "../util/util_shared_res.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
|
D3D11DXGIKeyedMutex::D3D11DXGIKeyedMutex(
|
||||||
|
ID3D11Resource* pResource,
|
||||||
|
D3D11Device* pDevice)
|
||||||
|
: m_resource(pResource),
|
||||||
|
m_device(pDevice) {
|
||||||
|
|
||||||
|
m_supported = m_device->GetDXVKDevice()->features().khrWin32KeyedMutex
|
||||||
|
&& m_device->GetDXVKDevice()->vkd()->wine_vkAcquireKeyedMutex != nullptr
|
||||||
|
&& m_device->GetDXVKDevice()->vkd()->wine_vkReleaseKeyedMutex != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
D3D11DXGIKeyedMutex::~D3D11DXGIKeyedMutex() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE D3D11DXGIKeyedMutex::AddRef() {
|
||||||
|
return m_resource->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE D3D11DXGIKeyedMutex::Release() {
|
||||||
|
return m_resource->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::QueryInterface(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject) {
|
||||||
|
return m_resource->QueryInterface(riid, ppvObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::GetPrivateData(
|
||||||
|
REFGUID Name,
|
||||||
|
UINT* pDataSize,
|
||||||
|
void* pData) {
|
||||||
|
return m_resource->GetPrivateData(Name, pDataSize, pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::SetPrivateData(
|
||||||
|
REFGUID Name,
|
||||||
|
UINT DataSize,
|
||||||
|
const void* pData) {
|
||||||
|
return m_resource->SetPrivateData(Name, DataSize, pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::SetPrivateDataInterface(
|
||||||
|
REFGUID Name,
|
||||||
|
const IUnknown* pUnknown) {
|
||||||
|
return m_resource->SetPrivateDataInterface(Name, pUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::GetParent(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppParent) {
|
||||||
|
return GetDevice(riid, ppParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::GetDevice(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppDevice) {
|
||||||
|
Com<ID3D11Device> device;
|
||||||
|
m_resource->GetDevice(&device);
|
||||||
|
return device->QueryInterface(riid, ppDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::AcquireSync(
|
||||||
|
UINT64 Key,
|
||||||
|
DWORD dwMilliseconds) {
|
||||||
|
if (!m_supported) {
|
||||||
|
if (!m_warned) {
|
||||||
|
m_warned = true;
|
||||||
|
Logger::err("D3D11DXGIKeyedMutex::AcquireSync: Not supported");
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D11CommonTexture* texture = GetCommonTexture(m_resource);
|
||||||
|
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
|
||||||
|
|
||||||
|
VkResult vr = dxvkDevice->vkd()->wine_vkAcquireKeyedMutex(dxvkDevice->handle(), texture->GetImage()->memory().memory(), Key, dwMilliseconds);
|
||||||
|
switch (vr) {
|
||||||
|
case VK_SUCCESS: return S_OK;
|
||||||
|
case VK_TIMEOUT: return WAIT_TIMEOUT;
|
||||||
|
default: return DXGI_ERROR_INVALID_CALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D11DXGIKeyedMutex::ReleaseSync(
|
||||||
|
UINT64 Key) {
|
||||||
|
if (!m_supported)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
D3D11CommonTexture* texture = GetCommonTexture(m_resource);
|
||||||
|
Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
|
||||||
|
|
||||||
|
{
|
||||||
|
D3D11ImmediateContext* context = m_device->GetContext();
|
||||||
|
D3D10Multithread& multithread = context->GetMultithread();
|
||||||
|
static bool s_errorShown = false;
|
||||||
|
|
||||||
|
if (!multithread.GetMultithreadProtected() && !std::exchange(s_errorShown, true))
|
||||||
|
Logger::warn("D3D11DXGIKeyedMutex::ReleaseSync: Called without context locking enabled.");
|
||||||
|
|
||||||
|
D3D10DeviceLock lock = context->LockContext();
|
||||||
|
context->WaitForResource(texture->GetImage(), DxvkCsThread::SynchronizeAll, D3D11_MAP_READ_WRITE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dxvkDevice->vkd()->wine_vkReleaseKeyedMutex(dxvkDevice->handle(), texture->GetImage()->memory().memory(), Key) == VK_SUCCESS
|
||||||
|
? S_OK
|
||||||
|
: DXGI_ERROR_INVALID_CALL;
|
||||||
|
}
|
||||||
|
|
||||||
D3D11DXGIResource::D3D11DXGIResource(
|
D3D11DXGIResource::D3D11DXGIResource(
|
||||||
ID3D11Resource* pResource)
|
ID3D11Resource* pResource,
|
||||||
: m_resource(pResource) {
|
D3D11Device* pDevice)
|
||||||
|
: m_resource(pResource),
|
||||||
|
m_keyedMutex(pResource, pDevice) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,9 +208,15 @@ namespace dxvk {
|
||||||
HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetSharedHandle(
|
HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetSharedHandle(
|
||||||
HANDLE* pSharedHandle) {
|
HANDLE* pSharedHandle) {
|
||||||
auto texture = GetCommonTexture(m_resource);
|
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;
|
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();
|
HANDLE kmtHandle = texture->GetImage()->sharedHandle();
|
||||||
|
|
||||||
if (kmtHandle == INVALID_HANDLE_VALUE)
|
if (kmtHandle == INVALID_HANDLE_VALUE)
|
||||||
|
@ -143,8 +273,9 @@ namespace dxvk {
|
||||||
LPCWSTR lpName,
|
LPCWSTR lpName,
|
||||||
HANDLE* pHandle) {
|
HANDLE* pHandle) {
|
||||||
auto texture = GetCommonTexture(m_resource);
|
auto texture = GetCommonTexture(m_resource);
|
||||||
|
if (pHandle) *pHandle = nullptr;
|
||||||
if (texture == nullptr || 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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if (lpName)
|
if (lpName)
|
||||||
|
@ -155,9 +286,6 @@ namespace dxvk {
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
if (texture->Desc()->MiscFlags & D3D11_RESOURCE_MISC_SHARED)
|
|
||||||
handle = openKmtHandle( handle );
|
|
||||||
|
|
||||||
*pHandle = handle;
|
*pHandle = handle;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +300,16 @@ 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(
|
HRESULT GetResource11on12Info(
|
||||||
ID3D11Resource* pResource,
|
ID3D11Resource* pResource,
|
||||||
D3D11_ON_12_RESOURCE_INFO* p11on12Info) {
|
D3D11_ON_12_RESOURCE_INFO* p11on12Info) {
|
||||||
|
|
|
@ -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
|
* \brief IDXGIResource implementation for D3D11 resources
|
||||||
*/
|
*/
|
||||||
|
@ -30,7 +89,8 @@ namespace dxvk {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
D3D11DXGIResource(
|
D3D11DXGIResource(
|
||||||
ID3D11Resource* pResource);
|
ID3D11Resource* pResource,
|
||||||
|
D3D11Device* pDevice);
|
||||||
|
|
||||||
~D3D11DXGIResource();
|
~D3D11DXGIResource();
|
||||||
|
|
||||||
|
@ -86,9 +146,12 @@ namespace dxvk {
|
||||||
UINT index,
|
UINT index,
|
||||||
IDXGISurface2** ppSurface);
|
IDXGISurface2** ppSurface);
|
||||||
|
|
||||||
|
HRESULT GetKeyedMutex(void **ppvObject);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ID3D11Resource* m_resource;
|
ID3D11Resource* m_resource;
|
||||||
|
D3D11DXGIKeyedMutex m_keyedMutex;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -272,4 +335,4 @@ namespace dxvk {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,9 +47,13 @@ namespace dxvk {
|
||||||
if (desc.MaxAnisotropy > 16) info.maxAnisotropy = 16.0f;
|
if (desc.MaxAnisotropy > 16) info.maxAnisotropy = 16.0f;
|
||||||
|
|
||||||
// Enforce LOD bias specified in the device options
|
// Enforce LOD bias specified in the device options
|
||||||
if (info.minFilter == VK_FILTER_LINEAR && info.magFilter == VK_FILTER_LINEAR)
|
if (info.minFilter == VK_FILTER_LINEAR && info.magFilter == VK_FILTER_LINEAR) {
|
||||||
info.mipmapLodBias += device->GetOptions()->samplerLodBias;
|
info.mipmapLodBias += device->GetOptions()->samplerLodBias;
|
||||||
|
|
||||||
|
if (device->GetOptions()->clampNegativeLodBias)
|
||||||
|
info.mipmapLodBias = std::max(info.mipmapLodBias, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
// Enforce anisotropy specified in the device options
|
// Enforce anisotropy specified in the device options
|
||||||
int32_t samplerAnisotropyOption = device->GetOptions()->samplerAnisotropy;
|
int32_t samplerAnisotropyOption = device->GetOptions()->samplerAnisotropy;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
static float ConvertMinLuminance(UINT dxgiLuminance) {
|
static float ConvertMinLuminance(UINT dxgiLuminance) {
|
||||||
return float(dxgiLuminance) / 0.0001f;
|
return float(dxgiLuminance) * 0.0001f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float ConvertLevel(UINT16 dxgiLevel) {
|
static float ConvertLevel(UINT16 dxgiLevel) {
|
||||||
|
@ -72,7 +72,7 @@ namespace dxvk {
|
||||||
CreateHud();
|
CreateHud();
|
||||||
|
|
||||||
if (!pDevice->GetOptions()->deferSurfaceCreation)
|
if (!pDevice->GetOptions()->deferSurfaceCreation)
|
||||||
RecreateSwapChain(false);
|
RecreateSwapChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,7 +98,8 @@ namespace dxvk {
|
||||||
InitReturnPtr(ppvObject);
|
InitReturnPtr(ppvObject);
|
||||||
|
|
||||||
if (riid == __uuidof(IUnknown)
|
if (riid == __uuidof(IUnknown)
|
||||||
|| riid == __uuidof(IDXGIVkSwapChain)) {
|
|| riid == __uuidof(IDXGIVkSwapChain)
|
||||||
|
|| riid == __uuidof(IDXGIVkSwapChain1)) {
|
||||||
*ppvObject = ref(this);
|
*ppvObject = ref(this);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -160,12 +161,10 @@ namespace dxvk {
|
||||||
|
|
||||||
HANDLE STDMETHODCALLTYPE D3D11SwapChain::GetFrameLatencyEvent() {
|
HANDLE STDMETHODCALLTYPE D3D11SwapChain::GetFrameLatencyEvent() {
|
||||||
HANDLE result = nullptr;
|
HANDLE result = nullptr;
|
||||||
|
HANDLE processHandle = GetCurrentProcess();
|
||||||
|
|
||||||
if (!m_processHandle)
|
if (!DuplicateHandle(processHandle, m_frameLatencyEvent,
|
||||||
m_processHandle = GetCurrentProcess();
|
processHandle, &result, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
||||||
|
|
||||||
if (!DuplicateHandle(m_processHandle, m_frameLatencyEvent,
|
|
||||||
m_processHandle, &result, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
|
|
||||||
Logger::err("DxgiSwapChain::GetFrameLatencyWaitableObject: DuplicateHandle failed");
|
Logger::err("DxgiSwapChain::GetFrameLatencyWaitableObject: DuplicateHandle failed");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -255,22 +254,13 @@ namespace dxvk {
|
||||||
UINT SyncInterval,
|
UINT SyncInterval,
|
||||||
UINT PresentFlags,
|
UINT PresentFlags,
|
||||||
const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
|
const DXGI_PRESENT_PARAMETERS* pPresentParameters) {
|
||||||
auto options = m_parent->GetOptions();
|
if (!(PresentFlags & DXGI_PRESENT_TEST))
|
||||||
|
m_dirty |= m_presenter->setSyncInterval(SyncInterval) != VK_SUCCESS;
|
||||||
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;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
if (!m_presenter->hasSwapChain()) {
|
if (!m_presenter->hasSwapChain()) {
|
||||||
RecreateSwapChain(m_vsync);
|
RecreateSwapChain();
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,19 +270,29 @@ namespace dxvk {
|
||||||
if (m_device->getDeviceStatus() != VK_SUCCESS)
|
if (m_device->getDeviceStatus() != VK_SUCCESS)
|
||||||
hr = DXGI_ERROR_DEVICE_RESET;
|
hr = DXGI_ERROR_DEVICE_RESET;
|
||||||
|
|
||||||
if ((PresentFlags & DXGI_PRESENT_TEST) || hr != S_OK)
|
if (PresentFlags & DXGI_PRESENT_TEST)
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
if (hr != S_OK) {
|
||||||
|
SyncFrameLatency();
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
if (std::exchange(m_dirty, false))
|
if (std::exchange(m_dirty, false))
|
||||||
RecreateSwapChain(m_vsync);
|
RecreateSwapChain();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PresentImage(SyncInterval);
|
hr = PresentImage(SyncInterval);
|
||||||
} catch (const DxvkError& e) {
|
} catch (const DxvkError& e) {
|
||||||
Logger::err(e.message());
|
Logger::err(e.message());
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure to synchronize and release the frame latency semaphore
|
||||||
|
// even if presentation failed with STATUS_OCCLUDED, or otherwise
|
||||||
|
// applications using the semaphore may deadlock. This works because
|
||||||
|
// we do not increment the frame ID in those situations.
|
||||||
|
SyncFrameLatency();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,34 +334,44 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE D3D11SwapChain::GetLastPresentCount(
|
||||||
|
UINT64* pLastPresentCount) {
|
||||||
|
*pLastPresentCount = UINT64(m_frameId - DXGI_MAX_SWAP_CHAIN_BUFFERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE D3D11SwapChain::GetFrameStatistics(
|
||||||
|
DXGI_VK_FRAME_STATISTICS* pFrameStatistics) {
|
||||||
|
std::lock_guard<dxvk::mutex> lock(m_frameStatisticsLock);
|
||||||
|
*pFrameStatistics = m_frameStatistics;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT D3D11SwapChain::PresentImage(UINT SyncInterval) {
|
HRESULT D3D11SwapChain::PresentImage(UINT SyncInterval) {
|
||||||
// Flush pending rendering commands before
|
// Flush pending rendering commands before
|
||||||
auto immediateContext = m_parent->GetContext();
|
auto immediateContext = m_parent->GetContext();
|
||||||
immediateContext->EndFrame();
|
immediateContext->EndFrame();
|
||||||
immediateContext->Flush();
|
immediateContext->Flush();
|
||||||
|
|
||||||
// Bump our frame id.
|
|
||||||
++m_frameId;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < SyncInterval || i < 1; i++) {
|
for (uint32_t i = 0; i < SyncInterval || i < 1; i++) {
|
||||||
SynchronizePresent();
|
SynchronizePresent();
|
||||||
|
|
||||||
if (!m_presenter->hasSwapChain())
|
if (!m_presenter->hasSwapChain())
|
||||||
return DXGI_STATUS_OCCLUDED;
|
return i ? S_OK : DXGI_STATUS_OCCLUDED;
|
||||||
|
|
||||||
// Presentation semaphores and WSI swap chain image
|
// Presentation semaphores and WSI swap chain image
|
||||||
vk::PresenterInfo info = m_presenter->info();
|
PresenterInfo info = m_presenter->info();
|
||||||
vk::PresenterSync sync;
|
PresenterSync sync;
|
||||||
|
|
||||||
uint32_t imageIndex = 0;
|
uint32_t imageIndex = 0;
|
||||||
|
|
||||||
VkResult status = m_presenter->acquireNextImage(sync, imageIndex);
|
VkResult status = m_presenter->acquireNextImage(sync, imageIndex);
|
||||||
|
|
||||||
while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) {
|
while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) {
|
||||||
RecreateSwapChain(m_vsync);
|
RecreateSwapChain();
|
||||||
|
|
||||||
if (!m_presenter->hasSwapChain())
|
if (!m_presenter->hasSwapChain())
|
||||||
return DXGI_STATUS_OCCLUDED;
|
return i ? S_OK : DXGI_STATUS_OCCLUDED;
|
||||||
|
|
||||||
info = m_presenter->info();
|
info = m_presenter->info();
|
||||||
status = m_presenter->acquireNextImage(sync, imageIndex);
|
status = m_presenter->acquireNextImage(sync, imageIndex);
|
||||||
|
@ -372,8 +382,6 @@ namespace dxvk {
|
||||||
m_dirtyHdrMetadata = false;
|
m_dirtyHdrMetadata = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve back buffer if it is multisampled. We
|
|
||||||
// only have to do it only for the first frame.
|
|
||||||
m_context->beginRecording(
|
m_context->beginRecording(
|
||||||
m_device->createCommandList());
|
m_device->createCommandList());
|
||||||
|
|
||||||
|
@ -384,40 +392,45 @@ namespace dxvk {
|
||||||
if (m_hud != nullptr)
|
if (m_hud != nullptr)
|
||||||
m_hud->render(m_context, info.format, info.imageExtent);
|
m_hud->render(m_context, info.format, info.imageExtent);
|
||||||
|
|
||||||
if (i + 1 >= SyncInterval)
|
|
||||||
m_context->signal(m_frameLatencySignal, m_frameId);
|
|
||||||
|
|
||||||
SubmitPresent(immediateContext, sync, i);
|
SubmitPresent(immediateContext, sync, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncFrameLatency();
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D11SwapChain::SubmitPresent(
|
void D3D11SwapChain::SubmitPresent(
|
||||||
D3D11ImmediateContext* pContext,
|
D3D11ImmediateContext* pContext,
|
||||||
const vk::PresenterSync& Sync,
|
const PresenterSync& Sync,
|
||||||
uint32_t FrameId) {
|
uint32_t Repeat) {
|
||||||
auto lock = pContext->LockContext();
|
auto lock = pContext->LockContext();
|
||||||
|
|
||||||
|
// Bump frame ID as necessary
|
||||||
|
if (!Repeat)
|
||||||
|
m_frameId += 1;
|
||||||
|
|
||||||
// Present from CS thread so that we don't
|
// Present from CS thread so that we don't
|
||||||
// have to synchronize with it first.
|
// have to synchronize with it first.
|
||||||
m_presentStatus.result = VK_NOT_READY;
|
m_presentStatus.result = VK_NOT_READY;
|
||||||
|
|
||||||
pContext->EmitCs([this,
|
pContext->EmitCs([this,
|
||||||
cFrameId = FrameId,
|
cRepeat = Repeat,
|
||||||
cSync = Sync,
|
cSync = Sync,
|
||||||
cHud = m_hud,
|
cHud = m_hud,
|
||||||
|
cPresentMode = m_presenter->info().presentMode,
|
||||||
|
cFrameId = m_frameId,
|
||||||
cCommandList = m_context->endRecording()
|
cCommandList = m_context->endRecording()
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
cCommandList->setWsiSemaphores(cSync);
|
cCommandList->setWsiSemaphores(cSync);
|
||||||
m_device->submitCommandList(cCommandList, nullptr);
|
m_device->submitCommandList(cCommandList, nullptr);
|
||||||
|
|
||||||
if (cHud != nullptr && !cFrameId)
|
if (cHud != nullptr && !cRepeat)
|
||||||
cHud->update();
|
cHud->update();
|
||||||
|
|
||||||
m_device->presentImage(m_presenter, &m_presentStatus);
|
uint64_t frameId = cRepeat ? 0 : cFrameId;
|
||||||
|
|
||||||
|
m_device->presentImage(m_presenter,
|
||||||
|
cPresentMode, frameId, &m_presentStatus);
|
||||||
});
|
});
|
||||||
|
|
||||||
pContext->FlushCsChunk();
|
pContext->FlushCsChunk();
|
||||||
|
@ -429,11 +442,11 @@ namespace dxvk {
|
||||||
VkResult status = m_device->waitForSubmission(&m_presentStatus);
|
VkResult status = m_device->waitForSubmission(&m_presentStatus);
|
||||||
|
|
||||||
if (status != VK_SUCCESS)
|
if (status != VK_SUCCESS)
|
||||||
RecreateSwapChain(m_vsync);
|
RecreateSwapChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D11SwapChain::RecreateSwapChain(BOOL Vsync) {
|
void D3D11SwapChain::RecreateSwapChain() {
|
||||||
// Ensure that we can safely destroy the swap chain
|
// Ensure that we can safely destroy the swap chain
|
||||||
m_device->waitForSubmission(&m_presentStatus);
|
m_device->waitForSubmission(&m_presentStatus);
|
||||||
m_device->waitForIdle();
|
m_device->waitForIdle();
|
||||||
|
@ -441,11 +454,10 @@ namespace dxvk {
|
||||||
m_presentStatus.result = VK_SUCCESS;
|
m_presentStatus.result = VK_SUCCESS;
|
||||||
m_dirtyHdrMetadata = true;
|
m_dirtyHdrMetadata = true;
|
||||||
|
|
||||||
vk::PresenterDesc presenterDesc;
|
PresenterDesc presenterDesc;
|
||||||
presenterDesc.imageExtent = { m_desc.Width, m_desc.Height };
|
presenterDesc.imageExtent = { m_desc.Width, m_desc.Height };
|
||||||
presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1);
|
presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1);
|
||||||
presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats);
|
presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats);
|
||||||
presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes);
|
|
||||||
presenterDesc.fullScreenExclusive = PickFullscreenMode();
|
presenterDesc.fullScreenExclusive = PickFullscreenMode();
|
||||||
|
|
||||||
VkResult vr = m_presenter->recreateSwapChain(presenterDesc);
|
VkResult vr = m_presenter->recreateSwapChain(presenterDesc);
|
||||||
|
@ -477,28 +489,13 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
void D3D11SwapChain::CreatePresenter() {
|
void D3D11SwapChain::CreatePresenter() {
|
||||||
DxvkDeviceQueue graphicsQueue = m_device->queues().graphics;
|
PresenterDesc presenterDesc;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
vk::PresenterDesc presenterDesc;
|
|
||||||
presenterDesc.imageExtent = { m_desc.Width, m_desc.Height };
|
presenterDesc.imageExtent = { m_desc.Width, m_desc.Height };
|
||||||
presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1);
|
presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1);
|
||||||
presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats);
|
presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats);
|
||||||
presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes);
|
|
||||||
presenterDesc.fullScreenExclusive = PickFullscreenMode();
|
presenterDesc.fullScreenExclusive = PickFullscreenMode();
|
||||||
|
|
||||||
m_presenter = new vk::Presenter(
|
m_presenter = new Presenter(m_device, m_frameLatencySignal, presenterDesc);
|
||||||
m_device->adapter()->vki(),
|
|
||||||
m_device->vkd(),
|
|
||||||
presenterDevice,
|
|
||||||
presenterDesc);
|
|
||||||
|
|
||||||
m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate);
|
m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +510,7 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
void D3D11SwapChain::CreateRenderTargetViews() {
|
void D3D11SwapChain::CreateRenderTargetViews() {
|
||||||
vk::PresenterInfo info = m_presenter->info();
|
PresenterInfo info = m_presenter->info();
|
||||||
|
|
||||||
m_imageViews.clear();
|
m_imageViews.clear();
|
||||||
m_imageViews.resize(info.imageCount);
|
m_imageViews.resize(info.imageCount);
|
||||||
|
@ -655,11 +652,17 @@ namespace dxvk {
|
||||||
// Wait for the sync event so that we respect the maximum frame latency
|
// Wait for the sync event so that we respect the maximum frame latency
|
||||||
m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency());
|
m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency());
|
||||||
|
|
||||||
if (m_frameLatencyEvent) {
|
m_frameLatencySignal->setCallback(m_frameId, [this,
|
||||||
m_frameLatencySignal->setCallback(m_frameId, [cFrameLatencyEvent = m_frameLatencyEvent] () {
|
cFrameId = m_frameId,
|
||||||
|
cFrameLatencyEvent = m_frameLatencyEvent
|
||||||
|
] () {
|
||||||
|
if (cFrameLatencyEvent)
|
||||||
ReleaseSemaphore(cFrameLatencyEvent, 1, nullptr);
|
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();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -675,7 +678,7 @@ namespace dxvk {
|
||||||
if (m_frameLatencyCap)
|
if (m_frameLatencyCap)
|
||||||
maxFrameLatency = std::min(maxFrameLatency, 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;
|
return maxFrameLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,25 +719,6 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t D3D11SwapChain::PickPresentModes(
|
|
||||||
BOOL Vsync,
|
|
||||||
VkPresentModeKHR* pDstModes) {
|
|
||||||
uint32_t n = 0;
|
|
||||||
|
|
||||||
if (Vsync) {
|
|
||||||
if (m_parent->GetOptions()->tearFree == Tristate::False)
|
|
||||||
pDstModes[n++] = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
|
|
||||||
pDstModes[n++] = VK_PRESENT_MODE_FIFO_KHR;
|
|
||||||
} else {
|
|
||||||
if (m_parent->GetOptions()->tearFree != Tristate::True)
|
|
||||||
pDstModes[n++] = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
|
||||||
pDstModes[n++] = VK_PRESENT_MODE_MAILBOX_KHR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t D3D11SwapChain::PickImageCount(
|
uint32_t D3D11SwapChain::PickImageCount(
|
||||||
UINT Preferred) {
|
UINT Preferred) {
|
||||||
int32_t option = m_parent->GetOptions()->numBackBuffers;
|
int32_t option = m_parent->GetOptions()->numBackBuffers;
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace dxvk {
|
||||||
class D3D11Device;
|
class D3D11Device;
|
||||||
class D3D11DXGIDevice;
|
class D3D11DXGIDevice;
|
||||||
|
|
||||||
class D3D11SwapChain : public ComObject<IDXGIVkSwapChain> {
|
class D3D11SwapChain : public ComObject<IDXGIVkSwapChain1> {
|
||||||
constexpr static uint32_t DefaultFrameLatency = 1;
|
constexpr static uint32_t DefaultFrameLatency = 1;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -80,6 +80,12 @@ namespace dxvk {
|
||||||
HRESULT STDMETHODCALLTYPE SetHDRMetaData(
|
HRESULT STDMETHODCALLTYPE SetHDRMetaData(
|
||||||
const DXGI_VK_HDR_METADATA* pMetaData);
|
const DXGI_VK_HDR_METADATA* pMetaData);
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE GetLastPresentCount(
|
||||||
|
UINT64* pLastPresentCount);
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE GetFrameStatistics(
|
||||||
|
DXGI_VK_FRAME_STATISTICS* pFrameStatistics);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum BindingIds : uint32_t {
|
enum BindingIds : uint32_t {
|
||||||
|
@ -97,7 +103,7 @@ namespace dxvk {
|
||||||
Rc<DxvkDevice> m_device;
|
Rc<DxvkDevice> m_device;
|
||||||
Rc<DxvkContext> m_context;
|
Rc<DxvkContext> m_context;
|
||||||
|
|
||||||
Rc<vk::Presenter> m_presenter;
|
Rc<Presenter> m_presenter;
|
||||||
|
|
||||||
Rc<DxvkImage> m_swapImage;
|
Rc<DxvkImage> m_swapImage;
|
||||||
Rc<DxvkImageView> m_swapImageView;
|
Rc<DxvkImageView> m_swapImageView;
|
||||||
|
@ -116,27 +122,26 @@ namespace dxvk {
|
||||||
HANDLE m_frameLatencyEvent = nullptr;
|
HANDLE m_frameLatencyEvent = nullptr;
|
||||||
Rc<sync::CallbackFence> m_frameLatencySignal;
|
Rc<sync::CallbackFence> m_frameLatencySignal;
|
||||||
|
|
||||||
HANDLE m_processHandle = nullptr;
|
|
||||||
|
|
||||||
bool m_dirty = true;
|
bool m_dirty = true;
|
||||||
bool m_vsync = true;
|
|
||||||
|
|
||||||
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||||
|
|
||||||
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
|
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
|
||||||
bool m_dirtyHdrMetadata = true;
|
bool m_dirtyHdrMetadata = true;
|
||||||
|
|
||||||
|
dxvk::mutex m_frameStatisticsLock;
|
||||||
|
DXGI_VK_FRAME_STATISTICS m_frameStatistics = { };
|
||||||
|
|
||||||
HRESULT PresentImage(UINT SyncInterval);
|
HRESULT PresentImage(UINT SyncInterval);
|
||||||
|
|
||||||
void SubmitPresent(
|
void SubmitPresent(
|
||||||
D3D11ImmediateContext* pContext,
|
D3D11ImmediateContext* pContext,
|
||||||
const vk::PresenterSync& Sync,
|
const PresenterSync& Sync,
|
||||||
uint32_t FrameId);
|
uint32_t Repeat);
|
||||||
|
|
||||||
void SynchronizePresent();
|
void SynchronizePresent();
|
||||||
|
|
||||||
void RecreateSwapChain(
|
void RecreateSwapChain();
|
||||||
BOOL Vsync);
|
|
||||||
|
|
||||||
void CreateFrameLatencyEvent();
|
void CreateFrameLatencyEvent();
|
||||||
|
|
||||||
|
@ -162,10 +167,6 @@ namespace dxvk {
|
||||||
DXGI_FORMAT Format,
|
DXGI_FORMAT Format,
|
||||||
VkSurfaceFormatKHR* pDstFormats);
|
VkSurfaceFormatKHR* pDstFormats);
|
||||||
|
|
||||||
uint32_t PickPresentModes(
|
|
||||||
BOOL Vsync,
|
|
||||||
VkPresentModeKHR* pDstModes);
|
|
||||||
|
|
||||||
uint32_t PickImageCount(
|
uint32_t PickImageCount(
|
||||||
UINT Preferred);
|
UINT Preferred);
|
||||||
|
|
||||||
|
|
|
@ -48,15 +48,21 @@ namespace dxvk {
|
||||||
if (hSharedHandle == nullptr)
|
if (hSharedHandle == nullptr)
|
||||||
hSharedHandle = INVALID_HANDLE_VALUE;
|
hSharedHandle = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
if (m_desc.MiscFlags & (D3D11_RESOURCE_MISC_SHARED|D3D11_RESOURCE_MISC_SHARED_NTHANDLE)) {
|
const auto sharingFlags = D3D11_RESOURCE_MISC_SHARED|D3D11_RESOURCE_MISC_SHARED_NTHANDLE|D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||||
if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX)
|
|
||||||
Logger::warn("D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX: not supported.");
|
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.shared = true;
|
||||||
imageInfo.sharing.mode = hSharedHandle == INVALID_HANDLE_VALUE ? DxvkSharedHandleMode::Export : DxvkSharedHandleMode::Import;
|
imageInfo.sharing.mode = hSharedHandle == INVALID_HANDLE_VALUE ? DxvkSharedHandleMode::Export : DxvkSharedHandleMode::Import;
|
||||||
imageInfo.sharing.type = (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED)
|
imageInfo.sharing.type = (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE)
|
||||||
? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
|
? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
|
||||||
: VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
|
: VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
|
||||||
imageInfo.sharing.handle = hSharedHandle;
|
imageInfo.sharing.handle = hSharedHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,9 +211,12 @@ namespace dxvk {
|
||||||
// For some formats, we need to enable sampled and/or
|
// For some formats, we need to enable sampled and/or
|
||||||
// render target capabilities if available, but these
|
// render target capabilities if available, but these
|
||||||
// should in no way affect the default image layout
|
// should in no way affect the default image layout
|
||||||
imageInfo.usage |= EnableMetaCopyUsage(imageInfo.format, imageInfo.tiling);
|
|
||||||
imageInfo.usage |= EnableMetaPackUsage(imageInfo.format, m_desc.CPUAccessFlags);
|
imageInfo.usage |= EnableMetaPackUsage(imageInfo.format, m_desc.CPUAccessFlags);
|
||||||
|
imageInfo.usage |= EnableMetaCopyUsage(imageInfo.format, imageInfo.tiling);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < imageInfo.viewFormatCount; i++)
|
||||||
|
imageInfo.usage |= EnableMetaCopyUsage(imageInfo.viewFormats[i], imageInfo.tiling);
|
||||||
|
|
||||||
// Check if we can actually create the image
|
// Check if we can actually create the image
|
||||||
if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
|
if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
|
||||||
throw DxvkError(str::format(
|
throw DxvkError(str::format(
|
||||||
|
@ -696,10 +705,10 @@ namespace dxvk {
|
||||||
void D3D11CommonTexture::ExportImageInfo() {
|
void D3D11CommonTexture::ExportImageInfo() {
|
||||||
HANDLE hSharedHandle;
|
HANDLE hSharedHandle;
|
||||||
|
|
||||||
if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED)
|
if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE)
|
||||||
hSharedHandle = openKmtHandle( m_image->sharedHandle() );
|
|
||||||
else
|
|
||||||
hSharedHandle = m_image->sharedHandle();
|
hSharedHandle = m_image->sharedHandle();
|
||||||
|
else
|
||||||
|
hSharedHandle = openKmtHandle( m_image->sharedHandle() );
|
||||||
|
|
||||||
DxvkSharedTextureMetadata metadata;
|
DxvkSharedTextureMetadata metadata;
|
||||||
|
|
||||||
|
@ -719,7 +728,7 @@ namespace dxvk {
|
||||||
Logger::warn("D3D11: Failed to write shared resource info for a texture");
|
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);
|
CloseHandle(hSharedHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,7 +1099,7 @@ namespace dxvk {
|
||||||
m_texture (this, pDevice, pDesc, p11on12Info, 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_interop (this, &m_texture),
|
||||||
m_surface (this, &m_texture),
|
m_surface (this, &m_texture),
|
||||||
m_resource(this),
|
m_resource(this, pDevice),
|
||||||
m_d3d10 (this) {
|
m_d3d10 (this) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1137,7 +1146,10 @@ namespace dxvk {
|
||||||
*ppvObject = ref(&m_resource);
|
*ppvObject = ref(&m_resource);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (riid == __uuidof(IDXGIKeyedMutex))
|
||||||
|
return m_resource.GetKeyedMutex(ppvObject);
|
||||||
|
|
||||||
if (riid == __uuidof(IDXGIVkInteropSurface)) {
|
if (riid == __uuidof(IDXGIVkInteropSurface)) {
|
||||||
*ppvObject = ref(&m_interop);
|
*ppvObject = ref(&m_interop);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -1193,7 +1205,7 @@ namespace dxvk {
|
||||||
m_texture (this, pDevice, pDesc, p11on12Info, 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_interop (this, &m_texture),
|
||||||
m_surface (this, &m_texture),
|
m_surface (this, &m_texture),
|
||||||
m_resource (this),
|
m_resource (this, pDevice),
|
||||||
m_d3d10 (this),
|
m_d3d10 (this),
|
||||||
m_swapChain (nullptr) {
|
m_swapChain (nullptr) {
|
||||||
}
|
}
|
||||||
|
@ -1208,7 +1220,7 @@ namespace dxvk {
|
||||||
m_texture (this, pDevice, pDesc, nullptr, 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_interop (this, &m_texture),
|
||||||
m_surface (this, &m_texture),
|
m_surface (this, &m_texture),
|
||||||
m_resource (this),
|
m_resource (this, pDevice),
|
||||||
m_d3d10 (this),
|
m_d3d10 (this),
|
||||||
m_swapChain (nullptr) {
|
m_swapChain (nullptr) {
|
||||||
|
|
||||||
|
@ -1224,7 +1236,7 @@ namespace dxvk {
|
||||||
m_texture (this, pDevice, pDesc, nullptr, 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_interop (this, &m_texture),
|
||||||
m_surface (this, &m_texture),
|
m_surface (this, &m_texture),
|
||||||
m_resource (this),
|
m_resource (this, pDevice),
|
||||||
m_d3d10 (this),
|
m_d3d10 (this),
|
||||||
m_swapChain (pSwapChain) {
|
m_swapChain (pSwapChain) {
|
||||||
|
|
||||||
|
@ -1298,6 +1310,9 @@ namespace dxvk {
|
||||||
*ppvObject = ref(&m_resource);
|
*ppvObject = ref(&m_resource);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (riid == __uuidof(IDXGIKeyedMutex))
|
||||||
|
return m_resource.GetKeyedMutex(ppvObject);
|
||||||
|
|
||||||
if (riid == __uuidof(IDXGIVkInteropSurface)) {
|
if (riid == __uuidof(IDXGIVkInteropSurface)) {
|
||||||
*ppvObject = ref(&m_interop);
|
*ppvObject = ref(&m_interop);
|
||||||
|
@ -1369,7 +1384,7 @@ namespace dxvk {
|
||||||
: D3D11DeviceChild<ID3D11Texture3D1>(pDevice),
|
: D3D11DeviceChild<ID3D11Texture3D1>(pDevice),
|
||||||
m_texture (this, pDevice, pDesc, p11on12Info, 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_interop (this, &m_texture),
|
||||||
m_resource(this),
|
m_resource(this, pDevice),
|
||||||
m_d3d10 (this) {
|
m_d3d10 (this) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1409,7 +1424,10 @@ namespace dxvk {
|
||||||
*ppvObject = ref(&m_resource);
|
*ppvObject = ref(&m_resource);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (riid == __uuidof(IDXGIKeyedMutex))
|
||||||
|
return m_resource.GetKeyedMutex(ppvObject);
|
||||||
|
|
||||||
if (riid == __uuidof(IDXGIVkInteropSurface)) {
|
if (riid == __uuidof(IDXGIVkInteropSurface)) {
|
||||||
*ppvObject = ref(&m_interop);
|
*ppvObject = ref(&m_interop);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -1262,12 +1262,28 @@ namespace dxvk {
|
||||||
viewport.height = float(cStreamState.dstRect.bottom) - viewport.y;
|
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 uboData = { };
|
||||||
uboData.colorMatrix[0][0] = 1.0f;
|
uboData.colorMatrix[0][0] = 1.0f;
|
||||||
uboData.colorMatrix[1][1] = 1.0f;
|
uboData.colorMatrix[1][1] = 1.0f;
|
||||||
uboData.colorMatrix[2][2] = 1.0f;
|
uboData.colorMatrix[2][2] = 1.0f;
|
||||||
uboData.coordMatrix[0][0] = 1.0f;
|
uboData.coordMatrix[0][0] = float(srcRect.extent.width) / float(viewExtent.width);
|
||||||
uboData.coordMatrix[1][1] = 1.0f;
|
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.yMin = 0.0f;
|
||||||
uboData.yMax = 1.0f;
|
uboData.yMax = 1.0f;
|
||||||
uboData.isPlanar = cViews[1] != nullptr;
|
uboData.isPlanar = cViews[1] != nullptr;
|
||||||
|
@ -1290,17 +1306,14 @@ namespace dxvk {
|
||||||
ctx->bindShader<VK_SHADER_STAGE_FRAGMENT_BIT>(Rc<DxvkShader>(m_fs));
|
ctx->bindShader<VK_SHADER_STAGE_FRAGMENT_BIT>(Rc<DxvkShader>(m_fs));
|
||||||
|
|
||||||
ctx->bindUniformBuffer(VK_SHADER_STAGE_FRAGMENT_BIT, 0, DxvkBufferSlice(m_ubo));
|
ctx->bindUniformBuffer(VK_SHADER_STAGE_FRAGMENT_BIT, 0, DxvkBufferSlice(m_ubo));
|
||||||
ctx->bindResourceSampler(VK_SHADER_STAGE_FRAGMENT_BIT, 1, Rc<DxvkSampler>(m_sampler));
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < cViews.size(); i++)
|
for (uint32_t i = 0; i < cViews.size(); i++)
|
||||||
ctx->bindResourceImageView(VK_SHADER_STAGE_FRAGMENT_BIT, 2 + i, Rc<DxvkImageView>(cViews[i]));
|
ctx->bindResourceImageView(VK_SHADER_STAGE_FRAGMENT_BIT, 1 + i, Rc<DxvkImageView>(cViews[i]));
|
||||||
|
|
||||||
ctx->draw(3, 1, 0, 0);
|
ctx->draw(3, 1, 0, 0);
|
||||||
|
|
||||||
ctx->bindResourceSampler(VK_SHADER_STAGE_FRAGMENT_BIT, 1, nullptr);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < cViews.size(); i++)
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1315,38 +1328,14 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D11VideoContext::CreateSampler() {
|
|
||||||
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 = m_device->createSampler(samplerInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void D3D11VideoContext::CreateShaders() {
|
void D3D11VideoContext::CreateShaders() {
|
||||||
SpirvCodeBuffer vsCode(d3d11_video_blit_vert);
|
SpirvCodeBuffer vsCode(d3d11_video_blit_vert);
|
||||||
SpirvCodeBuffer fsCode(d3d11_video_blit_frag);
|
SpirvCodeBuffer fsCode(d3d11_video_blit_frag);
|
||||||
|
|
||||||
const std::array<DxvkBindingInfo, 4> fsBindings = {{
|
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_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, 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 },
|
{ 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;
|
DxvkShaderCreateInfo vsInfo;
|
||||||
|
@ -1368,7 +1357,6 @@ namespace dxvk {
|
||||||
if (std::exchange(m_resourcesCreated, true))
|
if (std::exchange(m_resourcesCreated, true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CreateSampler();
|
|
||||||
CreateUniformBuffer();
|
CreateUniformBuffer();
|
||||||
CreateShaders();
|
CreateShaders();
|
||||||
}
|
}
|
||||||
|
|
|
@ -584,6 +584,7 @@ namespace dxvk {
|
||||||
struct alignas(16) UboData {
|
struct alignas(16) UboData {
|
||||||
float colorMatrix[3][4];
|
float colorMatrix[3][4];
|
||||||
float coordMatrix[3][2];
|
float coordMatrix[3][2];
|
||||||
|
VkRect2D srcRect;
|
||||||
float yMin, yMax;
|
float yMin, yMax;
|
||||||
VkBool32 isPlanar;
|
VkBool32 isPlanar;
|
||||||
};
|
};
|
||||||
|
@ -593,7 +594,6 @@ namespace dxvk {
|
||||||
Rc<DxvkDevice> m_device;
|
Rc<DxvkDevice> m_device;
|
||||||
Rc<DxvkShader> m_vs;
|
Rc<DxvkShader> m_vs;
|
||||||
Rc<DxvkShader> m_fs;
|
Rc<DxvkShader> m_fs;
|
||||||
Rc<DxvkSampler> m_sampler;
|
|
||||||
Rc<DxvkBuffer> m_ubo;
|
Rc<DxvkBuffer> m_ubo;
|
||||||
|
|
||||||
VkExtent2D m_dstExtent = { 0u, 0u };
|
VkExtent2D m_dstExtent = { 0u, 0u };
|
||||||
|
@ -613,8 +613,6 @@ namespace dxvk {
|
||||||
|
|
||||||
void CreateUniformBuffer();
|
void CreateUniformBuffer();
|
||||||
|
|
||||||
void CreateSampler();
|
|
||||||
|
|
||||||
void CreateShaders();
|
void CreateShaders();
|
||||||
|
|
||||||
void CreateResources();
|
void CreateResources();
|
||||||
|
|
|
@ -126,7 +126,7 @@ namespace dxvk {
|
||||||
if (riid == __uuidof(ID3D10DeviceChild)
|
if (riid == __uuidof(ID3D10DeviceChild)
|
||||||
|| riid == __uuidof(ID3D10View)
|
|| riid == __uuidof(ID3D10View)
|
||||||
|| riid == __uuidof(ID3D10DepthStencilView)) {
|
|| riid == __uuidof(ID3D10DepthStencilView)) {
|
||||||
*ppvObject = ref(this);
|
*ppvObject = ref(&m_d3d10);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,10 @@ namespace dxvk {
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DXGI_FORMAT GetViewFormat() const {
|
||||||
|
return m_desc.Format;
|
||||||
|
}
|
||||||
|
|
||||||
D3D10DepthStencilView* GetD3D10Iface() {
|
D3D10DepthStencilView* GetD3D10Iface() {
|
||||||
return &m_d3d10;
|
return &m_d3d10;
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ namespace dxvk {
|
||||||
if (riid == __uuidof(ID3D10DeviceChild)
|
if (riid == __uuidof(ID3D10DeviceChild)
|
||||||
|| riid == __uuidof(ID3D10View)
|
|| riid == __uuidof(ID3D10View)
|
||||||
|| riid == __uuidof(ID3D10RenderTargetView)) {
|
|| riid == __uuidof(ID3D10RenderTargetView)) {
|
||||||
*ppvObject = ref(this);
|
*ppvObject = ref(&m_d3d10);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,7 @@ namespace dxvk {
|
||||||
|| riid == __uuidof(ID3D10View)
|
|| riid == __uuidof(ID3D10View)
|
||||||
|| riid == __uuidof(ID3D10ShaderResourceView)
|
|| riid == __uuidof(ID3D10ShaderResourceView)
|
||||||
|| riid == __uuidof(ID3D10ShaderResourceView1)) {
|
|| riid == __uuidof(ID3D10ShaderResourceView1)) {
|
||||||
*ppvObject = ref(this);
|
*ppvObject = ref(&m_d3d10);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ namespace dxvk {
|
||||||
D3D11_BUFFER_DESC bufferDesc;
|
D3D11_BUFFER_DESC bufferDesc;
|
||||||
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
||||||
|
|
||||||
if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
if (bufferDesc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
||||||
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
||||||
pDesc->ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
pDesc->ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
|
||||||
pDesc->Buffer.FirstElement = 0;
|
pDesc->Buffer.FirstElement = 0;
|
||||||
|
|
|
@ -214,7 +214,7 @@ namespace dxvk {
|
||||||
D3D11_BUFFER_DESC bufferDesc;
|
D3D11_BUFFER_DESC bufferDesc;
|
||||||
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
static_cast<D3D11Buffer*>(pResource)->GetDesc(&bufferDesc);
|
||||||
|
|
||||||
if (bufferDesc.MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
if (bufferDesc.MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) {
|
||||||
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
pDesc->Format = DXGI_FORMAT_UNKNOWN;
|
||||||
pDesc->ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
pDesc->ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
|
||||||
pDesc->Buffer.FirstElement = 0;
|
pDesc->Buffer.FirstElement = 0;
|
||||||
|
|
|
@ -69,23 +69,33 @@ d3d11_shaders = files([
|
||||||
d3d11_ld_args = []
|
d3d11_ld_args = []
|
||||||
d3d11_link_depends = []
|
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_ld_args += [ '-Wl,--version-script', join_paths(meson.current_source_dir(), 'd3d11.sym') ]
|
||||||
d3d11_link_depends += files('d3d11.sym')
|
d3d11_link_depends += files('d3d11.sym')
|
||||||
|
d3d11_dxgi_dep = dxgi_dep
|
||||||
endif
|
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,
|
glsl_generator.process(d3d11_shaders), d3d11_res,
|
||||||
name_prefix : dxvk_name_prefix,
|
dependencies : [ d3d11_dxgi_dep, dxbc_dep, dxvk_dep ],
|
||||||
dependencies : [ dxgi_dep, dxbc_dep, dxvk_dep ],
|
|
||||||
include_directories : dxvk_include_path,
|
include_directories : dxvk_include_path,
|
||||||
install : true,
|
install : true,
|
||||||
vs_module_defs : 'd3d11'+def_spec_ext,
|
vs_module_defs : 'd3d11'+def_spec_ext,
|
||||||
link_args : d3d11_ld_args,
|
link_args : d3d11_ld_args,
|
||||||
link_depends : [ d3d11_link_depends ],
|
link_depends : [ d3d11_link_depends ],
|
||||||
|
kwargs : dxvk_so_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
d3d11_dep = declare_dependency(
|
d3d11_dep = declare_dependency(
|
||||||
link_with : [ d3d11_dll ],
|
link_with : [ d3d11_dll ],
|
||||||
include_directories : [ dxvk_include_path ],
|
include_directories : [ dxvk_include_path ],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if platform != 'windows'
|
||||||
|
pkg.generate(d3d11_dll,
|
||||||
|
filebase: dxvk_pkg_prefix + 'd3d11',
|
||||||
|
subdirs: 'dxvk',
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
|
#extension GL_EXT_samplerless_texture_functions : require
|
||||||
|
|
||||||
// Can't use matrix types here since even a two-row
|
// Can't use matrix types here since even a two-row
|
||||||
// matrix will be padded to 16 bytes per column for
|
// matrix will be padded to 16 bytes per column for
|
||||||
// absolutely no reason
|
// absolutely no reason
|
||||||
|
@ -11,6 +13,8 @@ uniform ubo_t {
|
||||||
vec2 coord_matrix_c1;
|
vec2 coord_matrix_c1;
|
||||||
vec2 coord_matrix_c2;
|
vec2 coord_matrix_c2;
|
||||||
vec2 coord_matrix_c3;
|
vec2 coord_matrix_c3;
|
||||||
|
uvec2 src_offset;
|
||||||
|
uvec2 src_extent;
|
||||||
float y_min;
|
float y_min;
|
||||||
float y_max;
|
float y_max;
|
||||||
bool is_planar;
|
bool is_planar;
|
||||||
|
@ -19,9 +23,8 @@ uniform ubo_t {
|
||||||
layout(location = 0) in vec2 i_texcoord;
|
layout(location = 0) in vec2 i_texcoord;
|
||||||
layout(location = 0) out vec4 o_color;
|
layout(location = 0) out vec4 o_color;
|
||||||
|
|
||||||
layout(set = 0, binding = 1) uniform sampler s_sampler;
|
layout(set = 0, binding = 1) uniform texture2D s_inputY;
|
||||||
layout(set = 0, binding = 2) uniform texture2D s_inputY;
|
layout(set = 0, binding = 2) uniform texture2D s_inputCbCr;
|
||||||
layout(set = 0, binding = 3) uniform texture2D s_inputCbCr;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Transform input texture coordinates to
|
// Transform input texture coordinates to
|
||||||
|
@ -31,25 +34,61 @@ void main() {
|
||||||
coord_matrix_c2,
|
coord_matrix_c2,
|
||||||
coord_matrix_c3);
|
coord_matrix_c3);
|
||||||
|
|
||||||
vec2 coord = coord_matrix * vec3(i_texcoord, 1.0f);
|
// Load color space transform
|
||||||
|
|
||||||
// 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
|
|
||||||
mat3x4 color_matrix = mat3x4(
|
mat3x4 color_matrix = mat3x4(
|
||||||
color_matrix_r1,
|
color_matrix_r1,
|
||||||
color_matrix_r2,
|
color_matrix_r2,
|
||||||
color_matrix_r3);
|
color_matrix_r3);
|
||||||
|
|
||||||
o_color.rgb = vec4(color.rgb, 1.0f) * color_matrix;
|
// Compute actual pixel coordinates to sample. We filter
|
||||||
o_color.a = color.a;
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,3 +25,6 @@ EXPORTS
|
||||||
DXVK_UnRegisterAnnotation @28258 NONAME
|
DXVK_UnRegisterAnnotation @28258 NONAME
|
||||||
|
|
||||||
Direct3D9ForceHybridEnumeration @16 NONAME PRIVATE
|
Direct3D9ForceHybridEnumeration @16 NONAME PRIVATE
|
||||||
|
|
||||||
|
Direct3DCreate9On12 @20
|
||||||
|
Direct3DCreate9On12Ex @21
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
DXVK_RegisterAnnotation;
|
DXVK_RegisterAnnotation;
|
||||||
DXVK_UnRegisterAnnotation;
|
DXVK_UnRegisterAnnotation;
|
||||||
Direct3D9ForceHybridEnumeration;
|
Direct3D9ForceHybridEnumeration;
|
||||||
|
Direct3DCreate9On12;
|
||||||
|
Direct3DCreate9On12Ex;
|
||||||
|
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
|
|
|
@ -162,6 +162,9 @@ namespace dxvk {
|
||||||
if (mapping.FormatSrgb == VK_FORMAT_UNDEFINED && srgb)
|
if (mapping.FormatSrgb == VK_FORMAT_UNDEFINED && srgb)
|
||||||
return D3DERR_NOTAVAILABLE;
|
return D3DERR_NOTAVAILABLE;
|
||||||
|
|
||||||
|
if (RType == D3DRTYPE_CUBETEXTURE && mapping.Aspect != VK_IMAGE_ASPECT_COLOR_BIT)
|
||||||
|
return D3DERR_NOTAVAILABLE;
|
||||||
|
|
||||||
if (RType == D3DRTYPE_VERTEXBUFFER || RType == D3DRTYPE_INDEXBUFFER)
|
if (RType == D3DRTYPE_VERTEXBUFFER || RType == D3DRTYPE_INDEXBUFFER)
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
|
||||||
|
@ -224,11 +227,15 @@ namespace dxvk {
|
||||||
if (!IsDepthFormat(DepthStencilFormat))
|
if (!IsDepthFormat(DepthStencilFormat))
|
||||||
return D3DERR_NOTAVAILABLE;
|
return D3DERR_NOTAVAILABLE;
|
||||||
|
|
||||||
|
auto dsfMapping = ConvertFormatUnfixed(DepthStencilFormat);
|
||||||
|
if (dsfMapping.FormatColor == VK_FORMAT_UNDEFINED)
|
||||||
|
return D3DERR_NOTAVAILABLE;
|
||||||
|
|
||||||
if (RenderTargetFormat == dxvk::D3D9Format::NULL_FORMAT)
|
if (RenderTargetFormat == dxvk::D3D9Format::NULL_FORMAT)
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
|
||||||
auto mapping = ConvertFormatUnfixed(RenderTargetFormat);
|
auto rtfMapping = ConvertFormatUnfixed(RenderTargetFormat);
|
||||||
if (mapping.FormatColor == VK_FORMAT_UNDEFINED)
|
if (rtfMapping.FormatColor == VK_FORMAT_UNDEFINED)
|
||||||
return D3DERR_NOTAVAILABLE;
|
return D3DERR_NOTAVAILABLE;
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
@ -529,7 +536,7 @@ namespace dxvk {
|
||||||
// Max Vertex Blend Matrices
|
// Max Vertex Blend Matrices
|
||||||
pCaps->MaxVertexBlendMatrices = 4;
|
pCaps->MaxVertexBlendMatrices = 4;
|
||||||
// Max Vertex Blend Matrix Index
|
// Max Vertex Blend Matrix Index
|
||||||
pCaps->MaxVertexBlendMatrixIndex = 8;
|
pCaps->MaxVertexBlendMatrixIndex = 0;
|
||||||
// Max Point Size
|
// Max Point Size
|
||||||
pCaps->MaxPointSize = 256.0f;
|
pCaps->MaxPointSize = 256.0f;
|
||||||
// Max Primitive Count
|
// Max Primitive Count
|
||||||
|
@ -788,7 +795,8 @@ namespace dxvk {
|
||||||
// Fix up the D3DFORMAT to match what we are enumerating
|
// Fix up the D3DFORMAT to match what we are enumerating
|
||||||
mode.Format = static_cast<D3DFORMAT>(Format);
|
mode.Format = static_cast<D3DFORMAT>(Format);
|
||||||
|
|
||||||
m_modes.push_back(mode);
|
if (std::count(m_modes.begin(), m_modes.end(), mode) == 0)
|
||||||
|
m_modes.push_back(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort display modes by width, height and refresh rate,
|
// Sort display modes by width, height and refresh rate,
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
|
||||||
|
#include "d3d9_device.h"
|
||||||
|
#include "d3d9_interface.h"
|
||||||
|
#include "d3d9_bridge.h"
|
||||||
|
#include "d3d9_swapchain.h"
|
||||||
|
#include "d3d9_surface.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
DxvkD3D8Bridge::DxvkD3D8Bridge(D3D9DeviceEx* pDevice)
|
||||||
|
: m_device(pDevice) {
|
||||||
|
}
|
||||||
|
|
||||||
|
DxvkD3D8Bridge::~DxvkD3D8Bridge() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE DxvkD3D8Bridge::AddRef() {
|
||||||
|
return m_device->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE DxvkD3D8Bridge::Release() {
|
||||||
|
return m_device->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DxvkD3D8Bridge::QueryInterface(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject) {
|
||||||
|
return m_device->QueryInterface(riid, ppvObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DxvkD3D8Bridge::SetAPIName(const char* name) {
|
||||||
|
m_device->m_implicitSwapchain->SetApiName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DxvkD3D8Bridge::SetD3D8CompatibilityMode(const bool compatMode) {
|
||||||
|
m_device->SetD3D8CompatibilityMode(compatMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT DxvkD3D8Bridge::UpdateTextureFromBuffer(
|
||||||
|
IDirect3DSurface9* pDestSurface,
|
||||||
|
IDirect3DSurface9* pSrcSurface,
|
||||||
|
const RECT* pSrcRect,
|
||||||
|
const POINT* pDestPoint) {
|
||||||
|
auto lock = m_device->LockDevice();
|
||||||
|
|
||||||
|
D3D9Surface* dst = static_cast<D3D9Surface*>(pDestSurface);
|
||||||
|
D3D9Surface* src = static_cast<D3D9Surface*>(pSrcSurface);
|
||||||
|
|
||||||
|
if (unlikely(dst == nullptr || src == nullptr))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
D3D9CommonTexture* srcTextureInfo = src->GetCommonTexture();
|
||||||
|
D3D9CommonTexture* dstTextureInfo = dst->GetCommonTexture();
|
||||||
|
|
||||||
|
VkOffset3D srcOffset = { 0u, 0u, 0u };
|
||||||
|
VkOffset3D dstOffset = { 0u, 0u, 0u };
|
||||||
|
VkExtent3D texLevelExtent = srcTextureInfo->GetExtentMip(src->GetSubresource());
|
||||||
|
VkExtent3D extent = texLevelExtent;
|
||||||
|
|
||||||
|
srcOffset = { pSrcRect->left,
|
||||||
|
pSrcRect->top,
|
||||||
|
0u };
|
||||||
|
|
||||||
|
extent = { uint32_t(pSrcRect->right - pSrcRect->left), uint32_t(pSrcRect->bottom - pSrcRect->top), 1 };
|
||||||
|
|
||||||
|
// TODO: Validate extents like in D3D9DeviceEx::UpdateSurface
|
||||||
|
|
||||||
|
dstOffset = { pDestPoint->x,
|
||||||
|
pDestPoint->y,
|
||||||
|
0u };
|
||||||
|
|
||||||
|
|
||||||
|
m_device->UpdateTextureFromBuffer(
|
||||||
|
srcTextureInfo, dstTextureInfo,
|
||||||
|
src->GetSubresource(), dst->GetSubresource(),
|
||||||
|
srcOffset, extent, dstOffset
|
||||||
|
);
|
||||||
|
|
||||||
|
dstTextureInfo->SetNeedsReadback(dst->GetSubresource(), true);
|
||||||
|
|
||||||
|
if (dstTextureInfo->IsAutomaticMip())
|
||||||
|
m_device->MarkTextureMipsDirty(dstTextureInfo);
|
||||||
|
|
||||||
|
return D3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DxvkD3D8InterfaceBridge::DxvkD3D8InterfaceBridge(D3D9InterfaceEx* pObject)
|
||||||
|
: m_interface(pObject) {
|
||||||
|
}
|
||||||
|
|
||||||
|
DxvkD3D8InterfaceBridge::~DxvkD3D8InterfaceBridge() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE DxvkD3D8InterfaceBridge::AddRef() {
|
||||||
|
return m_interface->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE DxvkD3D8InterfaceBridge::Release() {
|
||||||
|
return m_interface->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DxvkD3D8InterfaceBridge::QueryInterface(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject) {
|
||||||
|
return m_interface->QueryInterface(riid, ppvObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Config* DxvkD3D8InterfaceBridge::GetConfig() const {
|
||||||
|
return &m_interface->GetInstance()->config();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include "../util/config/config.h"
|
||||||
|
|
||||||
|
#include "../vulkan/vulkan_loader.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The D3D9 bridge allows D3D8 to access DXVK internals.
|
||||||
|
* For Vulkan interop without needing DXVK internals, see d3d9_interop.h.
|
||||||
|
*
|
||||||
|
* NOTE: You must include "d3d9_include.h" or "d3d8_include.h" before this header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief D3D9 device interface for D3D8 interop
|
||||||
|
*/
|
||||||
|
MIDL_INTERFACE("D3D9D3D8-42A9-4C1E-AA97-BEEFCAFE2000")
|
||||||
|
IDxvkD3D8Bridge : public IUnknown {
|
||||||
|
|
||||||
|
// D3D8 keeps D3D9 objects contained in a namespace.
|
||||||
|
#ifdef DXVK_D3D9_NAMESPACE
|
||||||
|
using IDirect3DSurface9 = d3d9::IDirect3DSurface9;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Changes the API name displayed on the HUD
|
||||||
|
*
|
||||||
|
* \param [in] name The new API name
|
||||||
|
*/
|
||||||
|
virtual void SetAPIName(const char* name) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Enables or disables D3D9-specific device features and validations
|
||||||
|
*
|
||||||
|
* \param [in] compatibility state
|
||||||
|
*/
|
||||||
|
virtual void SetD3D8CompatibilityMode(const bool compatMode) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Updates a D3D9 surface from a D3D9 buffer
|
||||||
|
*
|
||||||
|
* \param [in] pDestSurface Destination surface (typically in VRAM)
|
||||||
|
* \param [in] pSrcSurface Source surface (typically in system memory)
|
||||||
|
* \param [in] pSrcRect Source rectangle
|
||||||
|
* \param [in] pDestPoint Destination (top-left) point
|
||||||
|
*/
|
||||||
|
virtual HRESULT UpdateTextureFromBuffer(
|
||||||
|
IDirect3DSurface9* pDestSurface,
|
||||||
|
IDirect3DSurface9* pSrcSurface,
|
||||||
|
const RECT* pSrcRect,
|
||||||
|
const POINT* pDestPoint) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief D3D9 instance interface for D3D8 interop
|
||||||
|
*/
|
||||||
|
MIDL_INTERFACE("D3D9D3D8-A407-773E-18E9-CAFEBEEF3000")
|
||||||
|
IDxvkD3D8InterfaceBridge : public IUnknown {
|
||||||
|
/**
|
||||||
|
* \brief Retrieves the DXVK configuration
|
||||||
|
*
|
||||||
|
* \returns The DXVK Config object
|
||||||
|
*/
|
||||||
|
virtual const dxvk::Config* GetConfig() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
__CRT_UUID_DECL(IDxvkD3D8Bridge, 0xD3D9D3D8, 0x42A9, 0x4C1E, 0xAA, 0x97, 0xBE, 0xEF, 0xCA, 0xFE, 0x20, 0x00);
|
||||||
|
__CRT_UUID_DECL(IDxvkD3D8InterfaceBridge, 0xD3D9D3D8, 0xA407, 0x773E, 0x18, 0xE9, 0xCA, 0xFE, 0xBE, 0xEF, 0x30, 0x00);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
class D3D9DeviceEx;
|
||||||
|
class D3D9InterfaceEx;
|
||||||
|
|
||||||
|
class DxvkD3D8Bridge : public IDxvkD3D8Bridge {
|
||||||
|
public:
|
||||||
|
DxvkD3D8Bridge(D3D9DeviceEx* pDevice);
|
||||||
|
~DxvkD3D8Bridge();
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
ULONG STDMETHODCALLTYPE Release();
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject);
|
||||||
|
|
||||||
|
void SetAPIName(const char* name);
|
||||||
|
void SetD3D8CompatibilityMode(const bool compatMode);
|
||||||
|
|
||||||
|
HRESULT UpdateTextureFromBuffer(
|
||||||
|
IDirect3DSurface9* pDestSurface,
|
||||||
|
IDirect3DSurface9* pSrcSurface,
|
||||||
|
const RECT* pSrcRect,
|
||||||
|
const POINT* pDestPoint);
|
||||||
|
|
||||||
|
private:
|
||||||
|
D3D9DeviceEx* m_device;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DxvkD3D8InterfaceBridge : public IDxvkD3D8InterfaceBridge {
|
||||||
|
public:
|
||||||
|
DxvkD3D8InterfaceBridge(D3D9InterfaceEx* pObject);
|
||||||
|
~DxvkD3D8InterfaceBridge();
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
ULONG STDMETHODCALLTYPE Release();
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject);
|
||||||
|
|
||||||
|
const Config* GetConfig() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
D3D9InterfaceEx* m_interface;
|
||||||
|
};
|
||||||
|
}
|
|
@ -20,6 +20,11 @@ namespace dxvk {
|
||||||
m_dirtyRange = D3D9Range(0, m_desc.Size);
|
m_dirtyRange = D3D9Range(0, m_desc.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D3D9CommonBuffer::~D3D9CommonBuffer() {
|
||||||
|
if (m_desc.Pool == D3DPOOL_DEFAULT)
|
||||||
|
m_parent->DecrementLosableCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT D3D9CommonBuffer::Lock(
|
HRESULT D3D9CommonBuffer::Lock(
|
||||||
UINT OffsetToLock,
|
UINT OffsetToLock,
|
||||||
|
@ -57,6 +62,32 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
D3D9_COMMON_BUFFER_MAP_MODE D3D9CommonBuffer::DetermineMapMode(const D3D9Options* options) const {
|
||||||
|
if (m_desc.Pool != D3DPOOL_DEFAULT)
|
||||||
|
return D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
|
||||||
|
|
||||||
|
// CSGO keeps vertex buffers locked across multiple frames and writes to it. It uses them for drawing without unlocking first.
|
||||||
|
// Tests show that D3D9 DEFAULT + USAGE_DYNAMIC behaves like a directly mapped buffer even when unlocked.
|
||||||
|
// DEFAULT + WRITEONLY does not behave like a directly mapped buffer EXCEPT if its locked at the moment.
|
||||||
|
// That's annoying to implement so we just always directly map DEFAULT + WRITEONLY.
|
||||||
|
if (!(m_desc.Usage & (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)))
|
||||||
|
return D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
|
||||||
|
|
||||||
|
// Tests show that DISCARD does not work for pure SWVP devices.
|
||||||
|
// So force staging buffer path to avoid stalls.
|
||||||
|
// Dark Romance: Vampire in Love also expects draws to be synchronous
|
||||||
|
// and breaks if we respect NOOVERWRITE.
|
||||||
|
// D&D Temple of Elemental Evil breaks if we respect DISCARD.
|
||||||
|
if (m_parent->CanOnlySWVP())
|
||||||
|
return D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
|
||||||
|
|
||||||
|
if (!options->allowDirectBufferMapping)
|
||||||
|
return D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
|
||||||
|
|
||||||
|
return D3D9_COMMON_BUFFER_MAP_MODE_DIRECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkBuffer> D3D9CommonBuffer::CreateBuffer() const {
|
Rc<DxvkBuffer> D3D9CommonBuffer::CreateBuffer() const {
|
||||||
DxvkBufferCreateInfo info;
|
DxvkBufferCreateInfo info;
|
||||||
|
@ -103,7 +134,8 @@ namespace dxvk {
|
||||||
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT && m_parent->GetOptions()->apitraceMode) {
|
if ((memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && m_parent->GetOptions()->cachedDynamicBuffers) {
|
||||||
|
memoryFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||||
memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||||
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
|
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,8 @@ namespace dxvk {
|
||||||
D3D9DeviceEx* pDevice,
|
D3D9DeviceEx* pDevice,
|
||||||
const D3D9_BUFFER_DESC* pDesc);
|
const D3D9_BUFFER_DESC* pDesc);
|
||||||
|
|
||||||
|
~D3D9CommonBuffer();
|
||||||
|
|
||||||
HRESULT Lock(
|
HRESULT Lock(
|
||||||
UINT OffsetToLock,
|
UINT OffsetToLock,
|
||||||
UINT SizeToLock,
|
UINT SizeToLock,
|
||||||
|
@ -89,11 +91,7 @@ namespace dxvk {
|
||||||
/**
|
/**
|
||||||
* \brief Determine the mapping mode of the buffer, (ie. direct mapping or backed)
|
* \brief Determine the mapping mode of the buffer, (ie. direct mapping or backed)
|
||||||
*/
|
*/
|
||||||
inline D3D9_COMMON_BUFFER_MAP_MODE DetermineMapMode(const D3D9Options* options) const {
|
D3D9_COMMON_BUFFER_MAP_MODE DetermineMapMode(const D3D9Options* options) const;
|
||||||
return (m_desc.Pool == D3DPOOL_DEFAULT && (m_desc.Usage & (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)) && options->allowDirectBufferMapping)
|
|
||||||
? D3D9_COMMON_BUFFER_MAP_MODE_DIRECT
|
|
||||||
: D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the mapping mode of the buffer, (ie. direct mapping or backed)
|
* \brief Get the mapping mode of the buffer, (ie. direct mapping or backed)
|
||||||
|
@ -127,7 +125,12 @@ namespace dxvk {
|
||||||
|
|
||||||
template <D3D9_COMMON_BUFFER_TYPE Type>
|
template <D3D9_COMMON_BUFFER_TYPE Type>
|
||||||
inline DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const {
|
inline DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const {
|
||||||
return DxvkBufferSlice(GetBuffer<Type>(), offset, length);
|
if (likely(length && offset < m_desc.Size)) {
|
||||||
|
return DxvkBufferSlice(GetBuffer<Type>(), offset,
|
||||||
|
std::min<VkDeviceSize>(m_desc.Size - offset, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
return DxvkBufferSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DxvkBufferSliceHandle AllocMapSlice() {
|
inline DxvkBufferSliceHandle AllocMapSlice() {
|
||||||
|
@ -208,6 +211,10 @@ namespace dxvk {
|
||||||
: DxvkCsThread::SynchronizeAll;
|
: DxvkCsThread::SynchronizeAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsSysmemDynamic() const {
|
||||||
|
return m_desc.Pool == D3DPOOL_SYSTEMMEM && (m_desc.Usage & D3DUSAGE_DYNAMIC) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Rc<DxvkBuffer> CreateBuffer() const;
|
Rc<DxvkBuffer> CreateBuffer() const;
|
||||||
|
@ -227,7 +234,7 @@ namespace dxvk {
|
||||||
|
|
||||||
D3D9DeviceEx* m_parent;
|
D3D9DeviceEx* m_parent;
|
||||||
const D3D9_BUFFER_DESC m_desc;
|
const D3D9_BUFFER_DESC m_desc;
|
||||||
DWORD m_mapFlags;
|
DWORD m_mapFlags = 0;
|
||||||
bool m_needsReadback = false;
|
bool m_needsReadback = false;
|
||||||
D3D9_COMMON_BUFFER_MAP_MODE m_mapMode;
|
D3D9_COMMON_BUFFER_MAP_MODE m_mapMode;
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,12 @@ namespace dxvk {
|
||||||
AddDirtyBox(nullptr, i);
|
AddDirtyBox(nullptr, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_desc.Pool != D3DPOOL_DEFAULT) {
|
if (m_desc.Pool != D3DPOOL_DEFAULT && pSharedHandle) {
|
||||||
|
throw DxvkError("D3D9: Incompatible pool type for texture sharing.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsPoolManaged(m_desc.Pool)) {
|
||||||
SetAllNeedUpload();
|
SetAllNeedUpload();
|
||||||
if (pSharedHandle) {
|
|
||||||
throw DxvkError("D3D9: Incompatible pool type for texture sharing.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_mapping = pDevice->LookupFormat(m_desc.Format);
|
m_mapping = pDevice->LookupFormat(m_desc.Format);
|
||||||
|
@ -98,6 +99,9 @@ namespace dxvk {
|
||||||
m_device->ChangeReportedMemory(m_size);
|
m_device->ChangeReportedMemory(m_size);
|
||||||
|
|
||||||
m_device->RemoveMappedTexture(this);
|
m_device->RemoveMappedTexture(this);
|
||||||
|
|
||||||
|
if (m_desc.Pool == D3DPOOL_DEFAULT)
|
||||||
|
m_device->DecrementLosableCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,6 +118,7 @@ namespace dxvk {
|
||||||
|
|
||||||
HRESULT D3D9CommonTexture::NormalizeTextureProperties(
|
HRESULT D3D9CommonTexture::NormalizeTextureProperties(
|
||||||
D3D9DeviceEx* pDevice,
|
D3D9DeviceEx* pDevice,
|
||||||
|
D3DRESOURCETYPE ResourceType,
|
||||||
D3D9_COMMON_TEXTURE_DESC* pDesc) {
|
D3D9_COMMON_TEXTURE_DESC* pDesc) {
|
||||||
auto* options = pDevice->GetOptions();
|
auto* options = pDevice->GetOptions();
|
||||||
|
|
||||||
|
@ -127,6 +132,11 @@ namespace dxvk {
|
||||||
options->disableA8RT)
|
options->disableA8RT)
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
// Cube textures with depth formats are not supported on any native
|
||||||
|
// driver, and allowing them triggers a broken code path in Gothic 3.
|
||||||
|
if (ResourceType == D3DRTYPE_CUBETEXTURE && mapping.Aspect != VK_IMAGE_ASPECT_COLOR_BIT)
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
// If the mapping is invalid then lets return invalid
|
// If the mapping is invalid then lets return invalid
|
||||||
// Some edge cases:
|
// Some edge cases:
|
||||||
// NULL format does not map to anything, but should succeed
|
// NULL format does not map to anything, but should succeed
|
||||||
|
@ -364,7 +374,7 @@ namespace dxvk {
|
||||||
if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
|
if (!CheckImageSupport(&imageInfo, imageInfo.tiling)) {
|
||||||
throw DxvkError(str::format(
|
throw DxvkError(str::format(
|
||||||
"D3D9: Cannot create texture:",
|
"D3D9: Cannot create texture:",
|
||||||
"\n Type: ", std::hex, ResourceType,
|
"\n Type: 0x", std::hex, ResourceType, std::dec,
|
||||||
"\n Format: ", m_desc.Format,
|
"\n Format: ", m_desc.Format,
|
||||||
"\n Extent: ", m_desc.Width,
|
"\n Extent: ", m_desc.Width,
|
||||||
"x", m_desc.Height,
|
"x", m_desc.Height,
|
||||||
|
@ -372,8 +382,8 @@ namespace dxvk {
|
||||||
"\n Samples: ", m_desc.MultiSample,
|
"\n Samples: ", m_desc.MultiSample,
|
||||||
"\n Layers: ", m_desc.ArraySize,
|
"\n Layers: ", m_desc.ArraySize,
|
||||||
"\n Levels: ", m_desc.MipLevels,
|
"\n Levels: ", m_desc.MipLevels,
|
||||||
"\n Usage: ", std::hex, m_desc.Usage,
|
"\n Usage: 0x", std::hex, m_desc.Usage, std::dec,
|
||||||
"\n Pool: ", std::hex, m_desc.Pool));
|
"\n Pool: 0x", std::hex, m_desc.Pool, std::dec));
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_device->GetDXVKDevice()->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
return m_device->GetDXVKDevice()->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
|
@ -179,11 +179,14 @@ namespace dxvk {
|
||||||
* Fills in undefined values and validates the texture
|
* Fills in undefined values and validates the texture
|
||||||
* parameters. Any error returned by this method should
|
* parameters. Any error returned by this method should
|
||||||
* be forwarded to the application.
|
* be forwarded to the application.
|
||||||
|
* \param [in] pDevice D3D9 device
|
||||||
|
* \param [in] ResourceType Resource type
|
||||||
* \param [in,out] pDesc Texture description
|
* \param [in,out] pDesc Texture description
|
||||||
* \returns \c S_OK if the parameters are valid
|
* \returns \c S_OK if the parameters are valid
|
||||||
*/
|
*/
|
||||||
static HRESULT NormalizeTextureProperties(
|
static HRESULT NormalizeTextureProperties(
|
||||||
D3D9DeviceEx* pDevice,
|
D3D9DeviceEx* pDevice,
|
||||||
|
D3DRESOURCETYPE ResourceType,
|
||||||
D3D9_COMMON_TEXTURE_DESC* pDesc);
|
D3D9_COMMON_TEXTURE_DESC* pDesc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -307,8 +310,8 @@ namespace dxvk {
|
||||||
return util::computeMipLevelExtent(GetExtent(), MipLevel);
|
return util::computeMipLevelExtent(GetExtent(), MipLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MarkHazardous() {
|
bool MarkTransitionedToHazardLayout() {
|
||||||
return std::exchange(m_hazardous, true);
|
return std::exchange(m_transitionedToHazardLayout, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
D3DRESOURCETYPE GetType() {
|
D3DRESOURCETYPE GetType() {
|
||||||
|
@ -340,7 +343,7 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageLayout DetermineRenderTargetLayout(VkImageLayout hazardLayout) const {
|
VkImageLayout DetermineRenderTargetLayout(VkImageLayout hazardLayout) const {
|
||||||
if (unlikely(m_hazardous))
|
if (unlikely(m_transitionedToHazardLayout))
|
||||||
return hazardLayout;
|
return hazardLayout;
|
||||||
|
|
||||||
return m_image != nullptr &&
|
return m_image != nullptr &&
|
||||||
|
@ -350,18 +353,16 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageLayout DetermineDepthStencilLayout(bool write, bool hazardous, VkImageLayout hazardLayout) const {
|
VkImageLayout DetermineDepthStencilLayout(bool write, bool hazardous, VkImageLayout hazardLayout) const {
|
||||||
VkImageLayout layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
if (unlikely(m_transitionedToHazardLayout))
|
||||||
|
return hazardLayout;
|
||||||
if (unlikely(hazardous)) {
|
|
||||||
layout = write
|
|
||||||
? hazardLayout
|
|
||||||
: VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely(m_image->info().tiling != VK_IMAGE_TILING_OPTIMAL))
|
if (unlikely(m_image->info().tiling != VK_IMAGE_TILING_OPTIMAL))
|
||||||
layout = VK_IMAGE_LAYOUT_GENERAL;
|
return VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
|
||||||
return layout;
|
if (unlikely(hazardous && !write))
|
||||||
|
return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rc<DxvkImageView> CreateView(
|
Rc<DxvkImageView> CreateView(
|
||||||
|
@ -512,7 +513,7 @@ namespace dxvk {
|
||||||
|
|
||||||
int64_t m_size = 0;
|
int64_t m_size = 0;
|
||||||
|
|
||||||
bool m_hazardous = false;
|
bool m_transitionedToHazardLayout = false;
|
||||||
|
|
||||||
D3D9ColorView m_sampleView;
|
D3D9ColorView m_sampleView;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace dxvk {
|
||||||
DxsoProgramType ShaderStage,
|
DxsoProgramType ShaderStage,
|
||||||
DxsoConstantBuffers BufferType,
|
DxsoConstantBuffers BufferType,
|
||||||
VkDeviceSize Size)
|
VkDeviceSize Size)
|
||||||
: D3D9ConstantBuffer(pDevice, getBufferUsage(pDevice, ShaderStage, BufferType), GetShaderStage(ShaderStage),
|
: D3D9ConstantBuffer(pDevice, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, GetShaderStage(ShaderStage),
|
||||||
computeResourceSlotId(ShaderStage, DxsoBindingType::ConstantBuffer, BufferType),
|
computeResourceSlotId(ShaderStage, DxsoBindingType::ConstantBuffer, BufferType),
|
||||||
Size) {
|
Size) {
|
||||||
|
|
||||||
|
@ -135,21 +135,4 @@ namespace dxvk {
|
||||||
device->properties().extRobustness2.robustUniformBufferAccessSizeAlignment);
|
device->properties().extRobustness2.robustUniformBufferAccessSizeAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkBufferUsageFlags D3D9ConstantBuffer::getBufferUsage(
|
|
||||||
D3D9DeviceEx* pDevice,
|
|
||||||
DxsoProgramType ShaderStage,
|
|
||||||
DxsoConstantBuffers BufferType) {
|
|
||||||
VkBufferUsageFlags result = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
|
||||||
|
|
||||||
// We won't always need this, but the only buffer that
|
|
||||||
// this applies to is so large that it will not matter.
|
|
||||||
if (pDevice->CanSWVP()
|
|
||||||
&& ShaderStage == DxsoProgramType::VertexShader
|
|
||||||
&& BufferType == DxsoConstantBuffers::VSConstantBuffer)
|
|
||||||
result |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,11 +80,6 @@ namespace dxvk {
|
||||||
|
|
||||||
VkDeviceSize getAlignment(const Rc<DxvkDevice>& device) const;
|
VkDeviceSize getAlignment(const Rc<DxvkDevice>& device) const;
|
||||||
|
|
||||||
static VkBufferUsageFlags getBufferUsage(
|
|
||||||
D3D9DeviceEx* pDevice,
|
|
||||||
DxsoProgramType ShaderStage,
|
|
||||||
DxsoConstantBuffers BufferType);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -16,7 +16,11 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
BOOL D3D9Cursor::ShowCursor(BOOL bShow) {
|
BOOL D3D9Cursor::ShowCursor(BOOL bShow) {
|
||||||
::SetCursor(bShow ? m_hCursor : nullptr);
|
if (likely(m_hCursor != nullptr))
|
||||||
|
::SetCursor(bShow ? m_hCursor : nullptr);
|
||||||
|
else
|
||||||
|
Logger::debug("D3D9Cursor::ShowCursor: Software cursor not implemented.");
|
||||||
|
|
||||||
return std::exchange(m_visible, bShow);
|
return std::exchange(m_visible, bShow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,4 +67,4 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,12 +28,17 @@
|
||||||
|
|
||||||
#include "d3d9_spec_constants.h"
|
#include "d3d9_spec_constants.h"
|
||||||
#include "d3d9_interop.h"
|
#include "d3d9_interop.h"
|
||||||
|
#include "d3d9_on_12.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include "d3d9_bridge.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "../util/util_flush.h"
|
||||||
#include "../util/util_lru.h"
|
#include "../util/util_lru.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
@ -61,6 +66,8 @@ namespace dxvk {
|
||||||
DirtyInputLayout,
|
DirtyInputLayout,
|
||||||
DirtyViewportScissor,
|
DirtyViewportScissor,
|
||||||
DirtyMultiSampleState,
|
DirtyMultiSampleState,
|
||||||
|
DirtyVertexBuffers,
|
||||||
|
DirtyIndexBuffer,
|
||||||
|
|
||||||
DirtyFogState,
|
DirtyFogState,
|
||||||
DirtyFogColor,
|
DirtyFogColor,
|
||||||
|
@ -123,8 +130,10 @@ namespace dxvk {
|
||||||
constexpr static VkDeviceSize StagingBufferSize = 4ull << 20;
|
constexpr static VkDeviceSize StagingBufferSize = 4ull << 20;
|
||||||
|
|
||||||
friend class D3D9SwapChainEx;
|
friend class D3D9SwapChainEx;
|
||||||
|
friend struct D3D9WindowContext;
|
||||||
friend class D3D9ConstantBuffer;
|
friend class D3D9ConstantBuffer;
|
||||||
friend class D3D9UserDefinedAnnotation;
|
friend class D3D9UserDefinedAnnotation;
|
||||||
|
friend class DxvkD3D8Bridge;
|
||||||
friend D3D9VkInteropDevice;
|
friend D3D9VkInteropDevice;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -757,6 +766,24 @@ namespace dxvk {
|
||||||
HRESULT UnlockBuffer(
|
HRESULT UnlockBuffer(
|
||||||
D3D9CommonBuffer* pResource);
|
D3D9CommonBuffer* pResource);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Uploads data from D3DPOOL_SYSMEM + D3DUSAGE_DYNAMIC buffers and binds the temporary buffers.
|
||||||
|
*
|
||||||
|
* @param FirstVertexIndex The first vertex
|
||||||
|
* @param NumVertices The number of vertices that are accessed. If this is 0, the vertex buffer binding will not be modified.
|
||||||
|
* @param FirstIndex The first index
|
||||||
|
* @param NumIndices The number of indices that will be drawn. If this is 0, the index buffer binding will not be modified.
|
||||||
|
*/
|
||||||
|
void UploadDynamicSysmemBuffers(
|
||||||
|
UINT& FirstVertexIndex,
|
||||||
|
UINT NumVertices,
|
||||||
|
UINT& FirstIndex,
|
||||||
|
UINT NumIndices,
|
||||||
|
INT& BaseVertexIndex,
|
||||||
|
bool* pDynamicVBOs,
|
||||||
|
bool* pDynamicIBO);
|
||||||
|
|
||||||
|
|
||||||
void SetupFPU();
|
void SetupFPU();
|
||||||
|
|
||||||
int64_t DetermineInitialTextureMemory();
|
int64_t DetermineInitialTextureMemory();
|
||||||
|
@ -766,6 +793,7 @@ namespace dxvk {
|
||||||
void SynchronizeCsThread(uint64_t SequenceNumber);
|
void SynchronizeCsThread(uint64_t SequenceNumber);
|
||||||
|
|
||||||
void Flush();
|
void Flush();
|
||||||
|
void FlushAndSync9On12();
|
||||||
|
|
||||||
void EndFrame();
|
void EndFrame();
|
||||||
|
|
||||||
|
@ -773,6 +801,9 @@ namespace dxvk {
|
||||||
|
|
||||||
void UpdateActiveRTs(uint32_t index);
|
void UpdateActiveRTs(uint32_t index);
|
||||||
|
|
||||||
|
template <uint32_t Index>
|
||||||
|
void UpdateAnyColorWrites(bool has);
|
||||||
|
|
||||||
void UpdateActiveTextures(uint32_t index, DWORD combinedUsage);
|
void UpdateActiveTextures(uint32_t index, DWORD combinedUsage);
|
||||||
|
|
||||||
void UpdateActiveHazardsRT(uint32_t rtMask);
|
void UpdateActiveHazardsRT(uint32_t rtMask);
|
||||||
|
@ -806,7 +837,7 @@ namespace dxvk {
|
||||||
inline bool IsAlphaToCoverageEnabled() {
|
inline bool IsAlphaToCoverageEnabled() {
|
||||||
const bool alphaTest = m_state.renderStates[D3DRS_ALPHATESTENABLE] != 0;
|
const bool alphaTest = m_state.renderStates[D3DRS_ALPHATESTENABLE] != 0;
|
||||||
|
|
||||||
return m_amdATOC || (m_nvATOC && alphaTest);
|
return (m_amdATOC || (m_nvATOC && alphaTest)) && m_flags.test(D3D9DeviceFlag::ValidSampleMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsDepthBiasEnabled() {
|
inline bool IsDepthBiasEnabled() {
|
||||||
|
@ -874,6 +905,10 @@ namespace dxvk {
|
||||||
|
|
||||||
void MarkTextureBindingDirty(IDirect3DBaseTexture9* texture);
|
void MarkTextureBindingDirty(IDirect3DBaseTexture9* texture);
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE SetRenderTargetInternal(
|
||||||
|
DWORD RenderTargetIndex,
|
||||||
|
IDirect3DSurface9* pRenderTarget);
|
||||||
|
|
||||||
D3D9DrawInfo GenerateDrawInfo(
|
D3D9DrawInfo GenerateDrawInfo(
|
||||||
D3DPRIMITIVETYPE PrimitiveType,
|
D3DPRIMITIVETYPE PrimitiveType,
|
||||||
UINT PrimitiveCount,
|
UINT PrimitiveCount,
|
||||||
|
@ -881,7 +916,7 @@ namespace dxvk {
|
||||||
|
|
||||||
uint32_t GetInstanceCount() const;
|
uint32_t GetInstanceCount() const;
|
||||||
|
|
||||||
void PrepareDraw(D3DPRIMITIVETYPE PrimitiveType);
|
void PrepareDraw(D3DPRIMITIVETYPE PrimitiveType, bool UploadVBOs, bool UploadIBOs);
|
||||||
|
|
||||||
template <DxsoProgramType ShaderStage>
|
template <DxsoProgramType ShaderStage>
|
||||||
void BindShader(
|
void BindShader(
|
||||||
|
@ -915,7 +950,7 @@ namespace dxvk {
|
||||||
void SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits);
|
void SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits);
|
||||||
void SetPixelBoolBitfield (uint32_t idx, uint32_t mask, uint32_t bits);
|
void SetPixelBoolBitfield (uint32_t idx, uint32_t mask, uint32_t bits);
|
||||||
|
|
||||||
void FlushImplicit(BOOL StrongHint);
|
void ConsiderFlush(GpuFlushType FlushType);
|
||||||
|
|
||||||
bool ChangeReportedMemory(int64_t delta) {
|
bool ChangeReportedMemory(int64_t delta) {
|
||||||
if (IsExtended())
|
if (IsExtended())
|
||||||
|
@ -956,41 +991,35 @@ namespace dxvk {
|
||||||
void TouchMappedTexture(D3D9CommonTexture* pTexture);
|
void TouchMappedTexture(D3D9CommonTexture* pTexture);
|
||||||
void RemoveMappedTexture(D3D9CommonTexture* pTexture);
|
void RemoveMappedTexture(D3D9CommonTexture* pTexture);
|
||||||
|
|
||||||
|
bool IsD3D8Compatible() const {
|
||||||
|
return m_isD3D8Compatible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetD3D8CompatibilityMode(bool compatMode) {
|
||||||
|
if (compatMode)
|
||||||
|
Logger::info("The D3D9 device is now operating in D3D8 compatibility mode.");
|
||||||
|
|
||||||
|
m_isD3D8Compatible = compatMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Device Lost
|
||||||
bool IsDeviceLost() const {
|
bool IsDeviceLost() const {
|
||||||
return m_deviceLostState != D3D9DeviceLostState::Ok;
|
return m_deviceLostState != D3D9DeviceLostState::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotifyFullscreen(HWND window, bool fullscreen) {
|
void NotifyFullscreen(HWND window, bool fullscreen);
|
||||||
D3D9DeviceLock lock = LockDevice();
|
void NotifyWindowActivated(HWND window, bool activated);
|
||||||
|
|
||||||
if (fullscreen) {
|
void IncrementLosableCounter() {
|
||||||
if (unlikely(window != m_fullscreenWindow && m_fullscreenWindow != NULL)) {
|
m_losableResourceCounter++;
|
||||||
Logger::warn("Multiple fullscreen windows detected.");
|
|
||||||
}
|
|
||||||
m_fullscreenWindow = window;
|
|
||||||
} else {
|
|
||||||
if (unlikely(m_fullscreenWindow != window)) {
|
|
||||||
Logger::warn("Window was not fullscreen in the first place.");
|
|
||||||
} else {
|
|
||||||
m_fullscreenWindow = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotifyWindowActivated(HWND window, bool activated) {
|
void DecrementLosableCounter() {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
m_losableResourceCounter--;
|
||||||
|
}
|
||||||
if (likely(!m_d3d9Options.deviceLost || IsExtended()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (activated && m_deviceLostState == D3D9DeviceLostState::Lost) {
|
bool CanOnlySWVP() const {
|
||||||
Logger::info("Device not reset");
|
return m_behaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
||||||
m_deviceLostState = D3D9DeviceLostState::NotReset;
|
|
||||||
} else if (!activated && m_deviceLostState != D3D9DeviceLostState::Lost && m_fullscreenWindow == window) {
|
|
||||||
Logger::info("Device lost");
|
|
||||||
m_deviceLostState = D3D9DeviceLostState::Lost;
|
|
||||||
m_fullscreenWindow = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1000,12 +1029,15 @@ namespace dxvk {
|
||||||
return DxvkCsChunkRef(chunk, &m_csChunkPool);
|
return DxvkCsChunkRef(chunk, &m_csChunkPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Cmd>
|
template<bool AllowFlush = true, typename Cmd>
|
||||||
void EmitCs(Cmd&& command) {
|
void EmitCs(Cmd&& command) {
|
||||||
if (unlikely(!m_csChunk->push(command))) {
|
if (unlikely(!m_csChunk->push(command))) {
|
||||||
EmitCsChunk(std::move(m_csChunk));
|
EmitCsChunk(std::move(m_csChunk));
|
||||||
|
|
||||||
m_csChunk = AllocCsChunk();
|
m_csChunk = AllocCsChunk();
|
||||||
|
|
||||||
|
if constexpr (AllowFlush)
|
||||||
|
ConsiderFlush(GpuFlushType::ImplicitWeakHint);
|
||||||
|
|
||||||
m_csChunk->push(command);
|
m_csChunk->push(command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1019,10 +1051,18 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanSWVP() {
|
bool CanSWVP() const {
|
||||||
return m_behaviorFlags & (D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
|
return m_behaviorFlags & (D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Device Reset detection for D3D9SwapChainEx::Present
|
||||||
|
bool IsDeviceReset() {
|
||||||
|
return std::exchange(m_deviceHasBeenReset, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool Synchronize9On12>
|
||||||
|
void ExecuteFlush();
|
||||||
|
|
||||||
void DetermineConstantLayouts(bool canSWVP);
|
void DetermineConstantLayouts(bool canSWVP);
|
||||||
|
|
||||||
D3D9BufferSlice AllocUPBuffer(VkDeviceSize size);
|
D3D9BufferSlice AllocUPBuffer(VkDeviceSize size);
|
||||||
|
@ -1047,7 +1087,7 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t GetUPBufferSize(uint32_t vertexCount, uint32_t stride) {
|
inline uint32_t GetUPBufferSize(uint32_t vertexCount, uint32_t stride) {
|
||||||
return (vertexCount - 1) * stride + std::max(m_state.vertexDecl->GetSize(), stride);
|
return (vertexCount - 1) * stride + std::max(m_state.vertexDecl->GetSize(0), stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void FillUPVertexBuffer(void* buffer, const void* userData, uint32_t dataSize, uint32_t bufferSize) {
|
inline void FillUPVertexBuffer(void* buffer, const void* userData, uint32_t dataSize, uint32_t bufferSize) {
|
||||||
|
@ -1205,11 +1245,38 @@ namespace dxvk {
|
||||||
|
|
||||||
uint64_t GetCurrentSequenceNumber();
|
uint64_t GetCurrentSequenceNumber();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the swapchain that was used the most recently for presenting
|
||||||
|
* Has to be externally synchronized.
|
||||||
|
*
|
||||||
|
* @return D3D9SwapChainEx* Swapchain
|
||||||
|
*/
|
||||||
|
D3D9SwapChainEx* GetMostRecentlyUsedSwapchain() {
|
||||||
|
return m_mostRecentlyUsedSwapchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the swapchain that was used the most recently for presenting
|
||||||
|
* Has to be externally synchronized.
|
||||||
|
*
|
||||||
|
* @param swapchain Swapchain
|
||||||
|
*/
|
||||||
|
void SetMostRecentlyUsedSwapchain(D3D9SwapChainEx* swapchain) {
|
||||||
|
m_mostRecentlyUsedSwapchain = swapchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset the most recently swapchain back to the implicit one
|
||||||
|
* Has to be externally synchronized.
|
||||||
|
*/
|
||||||
|
void ResetMostRecentlyUsedSwapchain() {
|
||||||
|
m_mostRecentlyUsedSwapchain = m_implicitSwapchain.ptr();
|
||||||
|
}
|
||||||
|
|
||||||
Com<D3D9InterfaceEx> m_parent;
|
Com<D3D9InterfaceEx> m_parent;
|
||||||
D3DDEVTYPE m_deviceType;
|
D3DDEVTYPE m_deviceType;
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
WORD m_behaviorFlags;
|
WORD m_behaviorFlags;
|
||||||
D3DPRESENT_PARAMETERS m_presentParams;
|
|
||||||
|
|
||||||
D3D9Adapter* m_adapter;
|
D3D9Adapter* m_adapter;
|
||||||
Rc<DxvkDevice> m_dxvkDevice;
|
Rc<DxvkDevice> m_dxvkDevice;
|
||||||
|
@ -1288,14 +1355,16 @@ namespace dxvk {
|
||||||
uint32_t m_dirtySamplerStates = 0;
|
uint32_t m_dirtySamplerStates = 0;
|
||||||
uint32_t m_dirtyTextures = 0;
|
uint32_t m_dirtyTextures = 0;
|
||||||
|
|
||||||
uint32_t m_boundRTs = 0;
|
uint32_t m_boundRTs : 4;
|
||||||
|
uint32_t m_anyColorWrites : 4;
|
||||||
|
uint32_t m_activeRTsWhichAreTextures : 4;
|
||||||
|
uint32_t m_alphaSwizzleRTs : 4;
|
||||||
|
uint32_t m_lastHazardsRT : 4;
|
||||||
|
|
||||||
uint32_t m_activeRTs = 0;
|
uint32_t m_activeTextureRTs = 0;
|
||||||
uint32_t m_activeRTTextures = 0;
|
uint32_t m_activeTextureDSs = 0;
|
||||||
uint32_t m_activeDSTextures = 0;
|
|
||||||
uint32_t m_activeHazardsRT = 0;
|
uint32_t m_activeHazardsRT = 0;
|
||||||
uint32_t m_activeHazardsDS = 0;
|
uint32_t m_activeHazardsDS = 0;
|
||||||
uint32_t m_alphaSwizzleRTs = 0;
|
|
||||||
uint32_t m_activeTextures = 0;
|
uint32_t m_activeTextures = 0;
|
||||||
uint32_t m_activeTexturesToUpload = 0;
|
uint32_t m_activeTexturesToUpload = 0;
|
||||||
uint32_t m_activeTexturesToGen = 0;
|
uint32_t m_activeTexturesToGen = 0;
|
||||||
|
@ -1310,7 +1379,6 @@ namespace dxvk {
|
||||||
uint32_t m_fetch4 = 0;
|
uint32_t m_fetch4 = 0;
|
||||||
|
|
||||||
uint32_t m_lastHazardsDS = 0;
|
uint32_t m_lastHazardsDS = 0;
|
||||||
uint32_t m_lastHazardsRT = 0;
|
|
||||||
uint32_t m_lastSamplerTypesFF = 0;
|
uint32_t m_lastSamplerTypesFF = 0;
|
||||||
|
|
||||||
D3D9SpecializationInfo m_specInfo = D3D9SpecializationInfo();
|
D3D9SpecializationInfo m_specInfo = D3D9SpecializationInfo();
|
||||||
|
@ -1319,14 +1387,17 @@ namespace dxvk {
|
||||||
D3D9ShaderMasks m_psShaderMasks = FixedFunctionMask;
|
D3D9ShaderMasks m_psShaderMasks = FixedFunctionMask;
|
||||||
|
|
||||||
bool m_isSWVP;
|
bool m_isSWVP;
|
||||||
bool m_amdATOC = false;
|
bool m_isD3D8Compatible = false;
|
||||||
bool m_nvATOC = false;
|
bool m_amdATOC = false;
|
||||||
bool m_ffZTest = false;
|
bool m_nvATOC = false;
|
||||||
|
bool m_ffZTest = false;
|
||||||
|
|
||||||
VkImageLayout m_hazardLayout = VK_IMAGE_LAYOUT_GENERAL;
|
VkImageLayout m_hazardLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
|
||||||
bool m_usingGraphicsPipelines = false;
|
bool m_usingGraphicsPipelines = false;
|
||||||
|
bool m_deviceHasBeenReset = false;
|
||||||
|
|
||||||
|
DxvkDepthBiasRepresentation m_depthBiasRepresentation = { VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT, false };
|
||||||
float m_depthBiasScale = 0.0f;
|
float m_depthBiasScale = 0.0f;
|
||||||
|
|
||||||
uint32_t m_robustSSBOAlignment = 1;
|
uint32_t m_robustSSBOAlignment = 1;
|
||||||
|
@ -1348,18 +1419,25 @@ namespace dxvk {
|
||||||
D3D9ViewportInfo m_viewportInfo;
|
D3D9ViewportInfo m_viewportInfo;
|
||||||
|
|
||||||
DxvkCsChunkPool m_csChunkPool;
|
DxvkCsChunkPool m_csChunkPool;
|
||||||
dxvk::high_resolution_clock::time_point m_lastFlush
|
|
||||||
= dxvk::high_resolution_clock::now();
|
|
||||||
DxvkCsThread m_csThread;
|
DxvkCsThread m_csThread;
|
||||||
DxvkCsChunkRef m_csChunk;
|
DxvkCsChunkRef m_csChunk;
|
||||||
uint64_t m_csSeqNum = 0ull;
|
uint64_t m_csSeqNum = 0ull;
|
||||||
bool m_csIsBusy = false;
|
|
||||||
|
Rc<sync::Fence> m_submissionFence;
|
||||||
|
uint64_t m_submissionId = 0ull;
|
||||||
|
DxvkSubmitStatus m_submitStatus;
|
||||||
|
|
||||||
|
uint64_t m_flushSeqNum = 0ull;
|
||||||
|
GpuFlushTracker m_flushTracker;
|
||||||
|
|
||||||
std::atomic<int64_t> m_availableMemory = { 0 };
|
std::atomic<int64_t> m_availableMemory = { 0 };
|
||||||
std::atomic<int32_t> m_samplerCount = { 0 };
|
std::atomic<int32_t> m_samplerCount = { 0 };
|
||||||
|
|
||||||
D3D9DeviceLostState m_deviceLostState = D3D9DeviceLostState::Ok;
|
D3D9DeviceLostState m_deviceLostState = D3D9DeviceLostState::Ok;
|
||||||
HWND m_fullscreenWindow = NULL;
|
HWND m_fullscreenWindow = NULL;
|
||||||
|
std::atomic<uint32_t> m_losableResourceCounter = { 0 };
|
||||||
|
|
||||||
|
D3D9SwapChainEx* m_mostRecentlyUsedSwapchain = nullptr;
|
||||||
|
|
||||||
#ifdef D3D9_ALLOW_UNMAPPING
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
||||||
|
@ -1370,6 +1448,8 @@ namespace dxvk {
|
||||||
Direct3DState9 m_state;
|
Direct3DState9 m_state;
|
||||||
|
|
||||||
D3D9VkInteropDevice m_d3d9Interop;
|
D3D9VkInteropDevice m_d3d9Interop;
|
||||||
|
D3D9On12 m_d3d9On12;
|
||||||
|
DxvkD3D8Bridge m_d3d8Bridge;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -336,7 +336,7 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SetupRenderStateBlock(SpirvModule& spvModule, uint32_t count) {
|
uint32_t SetupRenderStateBlock(SpirvModule& spvModule) {
|
||||||
uint32_t floatType = spvModule.defFloatType(32);
|
uint32_t floatType = spvModule.defFloatType(32);
|
||||||
uint32_t uintType = spvModule.defIntType(32, 0);
|
uint32_t uintType = spvModule.defIntType(32, 0);
|
||||||
uint32_t vec3Type = spvModule.defVectorType(floatType, 3);
|
uint32_t vec3Type = spvModule.defVectorType(floatType, 3);
|
||||||
|
@ -357,7 +357,7 @@ namespace dxvk {
|
||||||
floatType,
|
floatType,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
uint32_t rsStruct = spvModule.defStructTypeUnique(count, rsMembers.data());
|
uint32_t rsStruct = spvModule.defStructTypeUnique(rsMembers.size(), rsMembers.data());
|
||||||
uint32_t rsBlock = spvModule.newVar(
|
uint32_t rsBlock = spvModule.newVar(
|
||||||
spvModule.defPointerType(rsStruct, spv::StorageClassPushConstant),
|
spvModule.defPointerType(rsStruct, spv::StorageClassPushConstant),
|
||||||
spv::StorageClassPushConstant);
|
spv::StorageClassPushConstant);
|
||||||
|
@ -369,9 +369,6 @@ namespace dxvk {
|
||||||
|
|
||||||
uint32_t memberIdx = 0;
|
uint32_t memberIdx = 0;
|
||||||
auto SetMemberName = [&](const char* name, uint32_t offset) {
|
auto SetMemberName = [&](const char* name, uint32_t offset) {
|
||||||
if (memberIdx >= count)
|
|
||||||
return;
|
|
||||||
|
|
||||||
spvModule.setDebugMemberName (rsStruct, memberIdx, name);
|
spvModule.setDebugMemberName (rsStruct, memberIdx, name);
|
||||||
spvModule.memberDecorateOffset (rsStruct, memberIdx, offset);
|
spvModule.memberDecorateOffset (rsStruct, memberIdx, offset);
|
||||||
memberIdx++;
|
memberIdx++;
|
||||||
|
@ -781,8 +778,6 @@ namespace dxvk {
|
||||||
uint32_t m_inputMask = 0u;
|
uint32_t m_inputMask = 0u;
|
||||||
uint32_t m_outputMask = 0u;
|
uint32_t m_outputMask = 0u;
|
||||||
uint32_t m_flatShadingMask = 0u;
|
uint32_t m_flatShadingMask = 0u;
|
||||||
uint32_t m_pushConstOffset = 0u;
|
|
||||||
uint32_t m_pushConstSize = 0u;
|
|
||||||
|
|
||||||
DxsoProgramType m_programType;
|
DxsoProgramType m_programType;
|
||||||
D3D9FFShaderKeyVS m_vsKey;
|
D3D9FFShaderKeyVS m_vsKey;
|
||||||
|
@ -892,8 +887,8 @@ namespace dxvk {
|
||||||
info.inputMask = m_inputMask;
|
info.inputMask = m_inputMask;
|
||||||
info.outputMask = m_outputMask;
|
info.outputMask = m_outputMask;
|
||||||
info.flatShadingInputs = m_flatShadingMask;
|
info.flatShadingInputs = m_flatShadingMask;
|
||||||
info.pushConstOffset = m_pushConstOffset;
|
info.pushConstStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
info.pushConstSize = m_pushConstSize;
|
info.pushConstSize = sizeof(D3D9RenderStateInfo);
|
||||||
|
|
||||||
return new DxvkShader(info, m_module.compile());
|
return new DxvkShader(info, m_module.compile());
|
||||||
}
|
}
|
||||||
|
@ -1104,13 +1099,24 @@ namespace dxvk {
|
||||||
for (uint32_t i = 0; i < caps::TextureStageCount; i++) {
|
for (uint32_t i = 0; i < caps::TextureStageCount; i++) {
|
||||||
uint32_t inputIndex = (m_vsKey.Data.Contents.TexcoordIndices >> (i * 3)) & 0b111;
|
uint32_t inputIndex = (m_vsKey.Data.Contents.TexcoordIndices >> (i * 3)) & 0b111;
|
||||||
uint32_t inputFlags = (m_vsKey.Data.Contents.TexcoordFlags >> (i * 3)) & 0b111;
|
uint32_t inputFlags = (m_vsKey.Data.Contents.TexcoordFlags >> (i * 3)) & 0b111;
|
||||||
uint32_t texcoordCount = (m_vsKey.Data.Contents.TexcoordDeclMask >> (i * 3)) & 0b111;
|
uint32_t texcoordCount = (m_vsKey.Data.Contents.TexcoordDeclMask >> (inputIndex * 3)) & 0b111;
|
||||||
|
|
||||||
uint32_t transformed;
|
uint32_t transformed;
|
||||||
|
|
||||||
const uint32_t wIndex = 3;
|
const uint32_t wIndex = 3;
|
||||||
|
|
||||||
uint32_t flags = (m_vsKey.Data.Contents.TransformFlags >> (i * 3)) & 0b111;
|
uint32_t flags = (m_vsKey.Data.Contents.TransformFlags >> (i * 3)) & 0b111;
|
||||||
|
|
||||||
|
if (flags == D3DTTFF_COUNT1) {
|
||||||
|
// D3DTTFF_COUNT1 behaves like D3DTTFF_DISABLE on NV and like D3DTTFF_COUNT2 on AMD.
|
||||||
|
// The Nvidia behavior is easier to implement.
|
||||||
|
flags = D3DTTFF_DISABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passing 0xffffffff results in it getting clamped to the dimensions of the texture coords and getting treated as PROJECTED
|
||||||
|
// but D3D9 does not apply the transformation matrix.
|
||||||
|
bool applyTransform = flags >= D3DTTFF_COUNT1 && flags <= D3DTTFF_COUNT4;
|
||||||
|
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
switch (inputFlags) {
|
switch (inputFlags) {
|
||||||
default:
|
default:
|
||||||
|
@ -1121,27 +1127,30 @@ namespace dxvk {
|
||||||
count = flags;
|
count = flags;
|
||||||
if (texcoordCount) {
|
if (texcoordCount) {
|
||||||
// Clamp by the number of elements in the texcoord input.
|
// Clamp by the number of elements in the texcoord input.
|
||||||
if (!count || count > texcoordCount)
|
if (!count || count > texcoordCount) {
|
||||||
count = texcoordCount;
|
count = texcoordCount;
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
|
count = 0;
|
||||||
flags = D3DTTFF_DISABLE;
|
flags = D3DTTFF_DISABLE;
|
||||||
|
applyTransform = false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (DXVK_TSS_TCI_CAMERASPACENORMAL >> TCIOffset):
|
case (DXVK_TSS_TCI_CAMERASPACENORMAL >> TCIOffset):
|
||||||
transformed = outNrm;
|
transformed = outNrm;
|
||||||
count = 4;
|
count = std::min(flags, 4u);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (DXVK_TSS_TCI_CAMERASPACEPOSITION >> TCIOffset):
|
case (DXVK_TSS_TCI_CAMERASPACEPOSITION >> TCIOffset):
|
||||||
transformed = m_module.opCompositeInsert(m_vec4Type, m_module.constf32(1.0f), vtx, 1, &wIndex);
|
transformed = m_module.opCompositeInsert(m_vec4Type, m_module.constf32(1.0f), vtx, 1, &wIndex);
|
||||||
count = 4;
|
count = std::min(flags, 4u);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (DXVK_TSS_TCI_CAMERASPACEREFLECTIONVECTOR >> TCIOffset): {
|
case (DXVK_TSS_TCI_CAMERASPACEREFLECTIONVECTOR >> TCIOffset): {
|
||||||
uint32_t vtx3 = m_module.opVectorShuffle(m_vec3Type, vtx, vtx, 3, indices.data());
|
uint32_t vtx3 = m_module.opVectorShuffle(m_vec3Type, vtx, vtx, 3, indices.data());
|
||||||
vtx3 = m_module.opNormalize(m_vec3Type, vtx3);
|
vtx3 = m_module.opNormalize(m_vec3Type, vtx3);
|
||||||
|
|
||||||
uint32_t reflection = m_module.opReflect(m_vec3Type, vtx3, normal);
|
uint32_t reflection = m_module.opReflect(m_vec3Type, vtx3, normal);
|
||||||
|
|
||||||
std::array<uint32_t, 4> transformIndices;
|
std::array<uint32_t, 4> transformIndices;
|
||||||
|
@ -1150,7 +1159,7 @@ namespace dxvk {
|
||||||
transformIndices[3] = m_module.constf32(1.0f);
|
transformIndices[3] = m_module.constf32(1.0f);
|
||||||
|
|
||||||
transformed = m_module.opCompositeConstruct(m_vec4Type, transformIndices.size(), transformIndices.data());
|
transformed = m_module.opCompositeConstruct(m_vec4Type, transformIndices.size(), transformIndices.data());
|
||||||
count = 4;
|
count = std::min(flags, 4u);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1174,37 +1183,43 @@ namespace dxvk {
|
||||||
transformIndices[3] = m_module.constf32(1.0f);
|
transformIndices[3] = m_module.constf32(1.0f);
|
||||||
|
|
||||||
transformed = m_module.opCompositeConstruct(m_vec4Type, transformIndices.size(), transformIndices.data());
|
transformed = m_module.opCompositeConstruct(m_vec4Type, transformIndices.size(), transformIndices.data());
|
||||||
count = 4;
|
count = std::min(flags, 4u);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t type = flags;
|
if (applyTransform && !m_vsKey.Data.Contents.HasPositionT) {
|
||||||
if (type != D3DTTFF_DISABLE) {
|
for (uint32_t j = count; j < 4; j++) {
|
||||||
if (!m_vsKey.Data.Contents.HasPositionT) {
|
// If we're outside the component count of the vertex decl for this texcoord then we pad with zeroes.
|
||||||
for (uint32_t j = count; j < 4; j++) {
|
// Otherwise, pad with ones.
|
||||||
// If we're outside the component count of the vertex decl for this texcoord then we pad with zeroes.
|
|
||||||
// Otherwise, pad with ones.
|
|
||||||
|
|
||||||
// Very weird quirk in order to get texcoord transforms to work like they do in native.
|
// Very weird quirk in order to get texcoord transforms to work like they do in native.
|
||||||
// In future, maybe we could sort this out properly by chopping matrices of different sizes, but thats
|
// In future, maybe we could sort this out properly by chopping matrices of different sizes, but thats
|
||||||
// a project for another day.
|
// a project for another day.
|
||||||
uint32_t texcoordCount = (m_vsKey.Data.Contents.TexcoordDeclMask >> (3 * inputIndex)) & 0x7;
|
uint32_t texcoordCount = (m_vsKey.Data.Contents.TexcoordDeclMask >> (3 * inputIndex)) & 0x7;
|
||||||
uint32_t value = j > texcoordCount ? m_module.constf32(0) : m_module.constf32(1);
|
uint32_t value = j > texcoordCount ? m_module.constf32(0) : m_module.constf32(1);
|
||||||
transformed = m_module.opCompositeInsert(m_vec4Type, value, transformed, 1, &j);
|
transformed = m_module.opCompositeInsert(m_vec4Type, value, transformed, 1, &j);
|
||||||
}
|
|
||||||
|
|
||||||
transformed = m_module.opVectorTimesMatrix(m_vec4Type, transformed, m_vs.constants.texcoord[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pad the unused section of it with the value for projection.
|
transformed = m_module.opVectorTimesMatrix(m_vec4Type, transformed, m_vs.constants.texcoord[i]);
|
||||||
uint32_t lastIdx = count - 1;
|
|
||||||
uint32_t projValue = m_module.opCompositeExtract(m_floatType, transformed, 1, &lastIdx);
|
|
||||||
|
|
||||||
for (uint32_t j = count; j < 4; j++)
|
|
||||||
transformed = m_module.opCompositeInsert(m_vec4Type, projValue, transformed, 1, &j);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The projection idx is always based on the flags, even when the input mode is not DXVK_TSS_TCI_PASSTHRU.
|
||||||
|
uint32_t projValue;
|
||||||
|
if (count < 3) {
|
||||||
|
// Not enough components to do projection.
|
||||||
|
// Native drivers render normally or garbage with D3DFVF_TEXCOORDSIZE2 or D3DTTFF_COUNT <3
|
||||||
|
projValue = m_module.constf32(1.0f);
|
||||||
|
} else {
|
||||||
|
uint32_t projIdx = count - 1;
|
||||||
|
projValue = m_module.opCompositeExtract(m_floatType, transformed, 1, &projIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The w component is only used for projection or unused, so always insert the component that's supposed to be divided by there.
|
||||||
|
// The fragment shader will then decide whether to project or not.
|
||||||
|
uint32_t wIdx = 3;
|
||||||
|
transformed = m_module.opCompositeInsert(m_vec4Type, projValue, transformed, 1, &wIdx);
|
||||||
|
|
||||||
m_module.opStore(m_vs.out.TEXCOORD[i], transformed);
|
m_module.opStore(m_vs.out.TEXCOORD[i], transformed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1384,20 +1399,7 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
void D3D9FFShaderCompiler::setupRenderStateInfo() {
|
void D3D9FFShaderCompiler::setupRenderStateInfo() {
|
||||||
uint32_t count;
|
m_rsBlock = SetupRenderStateBlock(m_module);
|
||||||
|
|
||||||
if (m_programType == DxsoProgramType::PixelShader) {
|
|
||||||
m_pushConstOffset = 0;
|
|
||||||
m_pushConstSize = offsetof(D3D9RenderStateInfo, pointSize);
|
|
||||||
count = 5;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_pushConstOffset = offsetof(D3D9RenderStateInfo, pointSize);
|
|
||||||
m_pushConstSize = sizeof(float) * 6;
|
|
||||||
count = 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_rsBlock = SetupRenderStateBlock(m_module, count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1808,21 +1810,17 @@ namespace dxvk {
|
||||||
texcoord = m_module.opVectorShuffle(texcoord_t,
|
texcoord = m_module.opVectorShuffle(texcoord_t,
|
||||||
texcoord, texcoord, texcoordCnt, indices.data());
|
texcoord, texcoord, texcoordCnt, indices.data());
|
||||||
|
|
||||||
uint32_t projIdx = m_fsKey.Stages[i].Contents.ProjectedCount;
|
bool shouldProject = m_fsKey.Stages[i].Contents.Projected;
|
||||||
if (projIdx == 0 || projIdx > texcoordCnt)
|
|
||||||
projIdx = texcoordCnt;
|
|
||||||
--projIdx;
|
|
||||||
|
|
||||||
uint32_t projValue = 0;
|
uint32_t projValue = 0;
|
||||||
|
|
||||||
if (m_fsKey.Stages[i].Contents.Projected) {
|
if (shouldProject) {
|
||||||
|
// Always use w, the vertex shader puts the correct value there.
|
||||||
|
const uint32_t projIdx = 3;
|
||||||
projValue = m_module.opCompositeExtract(m_floatType, m_ps.in.TEXCOORD[i], 1, &projIdx);
|
projValue = m_module.opCompositeExtract(m_floatType, m_ps.in.TEXCOORD[i], 1, &projIdx);
|
||||||
uint32_t insertIdx = texcoordCnt - 1;
|
uint32_t insertIdx = texcoordCnt - 1;
|
||||||
texcoord = m_module.opCompositeInsert(texcoord_t, projValue, texcoord, 1, &insertIdx);
|
texcoord = m_module.opCompositeInsert(texcoord_t, projValue, texcoord, 1, &insertIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldProject = m_fsKey.Stages[i].Contents.Projected;
|
|
||||||
|
|
||||||
if (i != 0 && (
|
if (i != 0 && (
|
||||||
m_fsKey.Stages[i - 1].Contents.ColorOp == D3DTOP_BUMPENVMAP ||
|
m_fsKey.Stages[i - 1].Contents.ColorOp == D3DTOP_BUMPENVMAP ||
|
||||||
m_fsKey.Stages[i - 1].Contents.ColorOp == D3DTOP_BUMPENVMAPLUMINANCE)) {
|
m_fsKey.Stages[i - 1].Contents.ColorOp == D3DTOP_BUMPENVMAPLUMINANCE)) {
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace dxvk {
|
||||||
void DoFixedFunctionAlphaTest(SpirvModule& spvModule, const D3D9AlphaTestContext& ctx);
|
void DoFixedFunctionAlphaTest(SpirvModule& spvModule, const D3D9AlphaTestContext& ctx);
|
||||||
|
|
||||||
// Returns a render state block
|
// Returns a render state block
|
||||||
uint32_t SetupRenderStateBlock(SpirvModule& spvModule, uint32_t count);
|
uint32_t SetupRenderStateBlock(SpirvModule& spvModule);
|
||||||
|
|
||||||
struct D3D9PointSizeInfoVS {
|
struct D3D9PointSizeInfoVS {
|
||||||
uint32_t defaultValue;
|
uint32_t defaultValue;
|
||||||
|
|
|
@ -134,7 +134,7 @@ namespace dxvk {
|
||||||
info.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
info.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
info.bindingCount = bindings.size();
|
info.bindingCount = bindings.size();
|
||||||
info.bindings = bindings.data();
|
info.bindings = bindings.data();
|
||||||
info.pushConstOffset = 0;
|
info.pushConstStages = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
info.pushConstSize = sizeof(VkExtent2D);
|
info.pushConstSize = sizeof(VkExtent2D);
|
||||||
|
|
||||||
return new DxvkShader(info, std::move(code));
|
return new DxvkShader(info, std::move(code));
|
||||||
|
|
|
@ -12,9 +12,9 @@
|
||||||
|
|
||||||
//for some reason we need to specify __declspec(dllexport) for MinGW
|
//for some reason we need to specify __declspec(dllexport) for MinGW
|
||||||
#if defined(__WINE__) || !defined(_WIN32)
|
#if defined(__WINE__) || !defined(_WIN32)
|
||||||
#define DLLEXPORT __attribute__((visibility("default")))
|
#define DLLEXPORT __attribute__((visibility("default")))
|
||||||
#else
|
#else
|
||||||
#define DLLEXPORT
|
#define DLLEXPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,3 +60,48 @@ typedef struct _D3DDEVINFO_RESOURCEMANAGER
|
||||||
#define D3DPOOL_MANAGED_EX D3DPOOL(6)
|
#define D3DPOOL_MANAGED_EX D3DPOOL(6)
|
||||||
|
|
||||||
using D3D9VertexElements = std::vector<D3DVERTEXELEMENT9>;
|
using D3D9VertexElements = std::vector<D3DVERTEXELEMENT9>;
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
// D3D9On12 content
|
||||||
|
/////////////////////
|
||||||
|
|
||||||
|
#include <d3d12.h>
|
||||||
|
|
||||||
|
#define MAX_D3D9ON12_QUEUES 2
|
||||||
|
|
||||||
|
struct D3D9ON12_ARGS {
|
||||||
|
BOOL Enable9On12;
|
||||||
|
IUnknown* pD3D12Device;
|
||||||
|
IUnknown* ppD3D12Queues[MAX_D3D9ON12_QUEUES];
|
||||||
|
UINT NumQueues;
|
||||||
|
UINT NodeMask;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// Ordinal 20
|
||||||
|
typedef IDirect3D9* (WINAPI* PFN_Direct3DCreate9On12)(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count);
|
||||||
|
IDirect3D9* WINAPI Direct3DCreate9On12(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count);
|
||||||
|
|
||||||
|
// Ordinal 21
|
||||||
|
typedef HRESULT(WINAPI* PFN_Direct3DCreate9On12Ex)(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count, IDirect3D9Ex** output);
|
||||||
|
HRESULT WINAPI Direct3DCreate9On12Ex(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count, IDirect3D9Ex** output);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDL_INTERFACE("e7fda234-b589-4049-940d-8878977531c8")
|
||||||
|
IDirect3DDevice9On12 : public IUnknown {
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** object) = 0;
|
||||||
|
virtual ULONG STDMETHODCALLTYPE AddRef() = 0;
|
||||||
|
virtual ULONG STDMETHODCALLTYPE Release() = 0;
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetD3D12Device(REFIID riid, void** object) = 0;
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE UnwrapUnderlyingResource(IDirect3DResource9* resource, ID3D12CommandQueue* command_queue, REFIID riid, void** object) = 0;
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE ReturnUnderlyingResource(IDirect3DResource9* resource, UINT num_sync, UINT64* signal_values, ID3D12Fence** fences) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
__CRT_UUID_DECL(IDirect3DDevice9On12, 0xe7fda234,0xb589,0x4049,0x94,0x0d,0x88,0x78,0x97,0x75,0x31,0xc8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "d3d9_monitor.h"
|
#include "d3d9_monitor.h"
|
||||||
#include "d3d9_caps.h"
|
#include "d3d9_caps.h"
|
||||||
#include "d3d9_device.h"
|
#include "d3d9_device.h"
|
||||||
|
#include "d3d9_bridge.h"
|
||||||
|
|
||||||
#include "../util/util_singleton.h"
|
#include "../util/util_singleton.h"
|
||||||
|
|
||||||
|
@ -13,7 +14,8 @@ namespace dxvk {
|
||||||
Singleton<DxvkInstance> g_dxvkInstance;
|
Singleton<DxvkInstance> g_dxvkInstance;
|
||||||
|
|
||||||
D3D9InterfaceEx::D3D9InterfaceEx(bool bExtended)
|
D3D9InterfaceEx::D3D9InterfaceEx(bool bExtended)
|
||||||
: m_instance ( g_dxvkInstance.acquire() )
|
: m_instance ( g_dxvkInstance.acquire(DxvkInstanceFlag::ClientApiIsD3D9) )
|
||||||
|
, m_d3d8Bridge ( this )
|
||||||
, m_extended ( bExtended )
|
, m_extended ( bExtended )
|
||||||
, m_d3d9Options ( nullptr, m_instance->config() )
|
, m_d3d9Options ( nullptr, m_instance->config() )
|
||||||
, m_d3d9Interop ( this ) {
|
, m_d3d9Interop ( this ) {
|
||||||
|
@ -86,6 +88,11 @@ namespace dxvk {
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (riid == __uuidof(IDxvkD3D8InterfaceBridge)) {
|
||||||
|
*ppvObject = ref(&m_d3d8Bridge);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (riid == __uuidof(ID3D9VkInteropInterface)) {
|
if (riid == __uuidof(ID3D9VkInteropInterface)) {
|
||||||
*ppvObject = ref(&m_d3d9Interop);
|
*ppvObject = ref(&m_d3d9Interop);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "d3d9_adapter.h"
|
#include "d3d9_adapter.h"
|
||||||
|
#include "d3d9_bridge.h"
|
||||||
#include "d3d9_interop.h"
|
#include "d3d9_interop.h"
|
||||||
|
|
||||||
#include "../dxvk/dxvk_instance.h"
|
#include "../dxvk/dxvk_instance.h"
|
||||||
|
@ -140,6 +141,8 @@ namespace dxvk {
|
||||||
|
|
||||||
Rc<DxvkInstance> m_instance;
|
Rc<DxvkInstance> m_instance;
|
||||||
|
|
||||||
|
DxvkD3D8InterfaceBridge m_d3d8Bridge;
|
||||||
|
|
||||||
bool m_extended;
|
bool m_extended;
|
||||||
|
|
||||||
D3D9Options m_d3d9Options;
|
D3D9Options m_d3d9Options;
|
||||||
|
|
|
@ -196,12 +196,42 @@ ID3D9VkInteropDevice : public IUnknown {
|
||||||
DWORD MapFlags) = 0;
|
DWORD MapFlags) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
/**
|
||||||
struct __declspec(uuid("3461a81b-ce41-485b-b6b5-fcf08ba6a6bd")) ID3D9VkInteropInterface;
|
* \brief D3D9 current output metadata
|
||||||
struct __declspec(uuid("d56344f5-8d35-46fd-806d-94c351b472c1")) ID3D9VkInteropTexture;
|
*/
|
||||||
struct __declspec(uuid("2eaa4b89-0107-4bdb-87f7-0f541c493ce0")) ID3D9VkInteropDevice;
|
struct D3D9VkExtOutputMetadata {
|
||||||
#else
|
float RedPrimary[2];
|
||||||
|
float GreenPrimary[2];
|
||||||
|
float BluePrimary[2];
|
||||||
|
float WhitePoint[2];
|
||||||
|
float MinLuminance;
|
||||||
|
float MaxLuminance;
|
||||||
|
float MaxFullFrameLuminance;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief D3D9 extended swapchain
|
||||||
|
*/
|
||||||
|
MIDL_INTERFACE("13776e93-4aa9-430a-a4ec-fe9e281181d5")
|
||||||
|
ID3D9VkExtSwapchain : public IUnknown {
|
||||||
|
virtual BOOL STDMETHODCALLTYPE CheckColorSpaceSupport(
|
||||||
|
VkColorSpaceKHR ColorSpace) = 0;
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE SetColorSpace(
|
||||||
|
VkColorSpaceKHR ColorSpace) = 0;
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE SetHDRMetaData(
|
||||||
|
const VkHdrMetadataEXT *pHDRMetadata) = 0;
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetCurrentOutputDesc(
|
||||||
|
D3D9VkExtOutputMetadata *pOutputDesc) = 0;
|
||||||
|
|
||||||
|
virtual void STDMETHODCALLTYPE UnlockAdditionalFormats() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
__CRT_UUID_DECL(ID3D9VkInteropInterface, 0x3461a81b,0xce41,0x485b,0xb6,0xb5,0xfc,0xf0,0x8b,0xa6,0xa6,0xbd);
|
__CRT_UUID_DECL(ID3D9VkInteropInterface, 0x3461a81b,0xce41,0x485b,0xb6,0xb5,0xfc,0xf0,0x8b,0xa6,0xa6,0xbd);
|
||||||
__CRT_UUID_DECL(ID3D9VkInteropTexture, 0xd56344f5,0x8d35,0x46fd,0x80,0x6d,0x94,0xc3,0x51,0xb4,0x72,0xc1);
|
__CRT_UUID_DECL(ID3D9VkInteropTexture, 0xd56344f5,0x8d35,0x46fd,0x80,0x6d,0x94,0xc3,0x51,0xb4,0x72,0xc1);
|
||||||
__CRT_UUID_DECL(ID3D9VkInteropDevice, 0x2eaa4b89,0x0107,0x4bdb,0x87,0xf7,0x0f,0x54,0x1c,0x49,0x3c,0xe0);
|
__CRT_UUID_DECL(ID3D9VkInteropDevice, 0x2eaa4b89,0x0107,0x4bdb,0x87,0xf7,0x0f,0x54,0x1c,0x49,0x3c,0xe0);
|
||||||
|
__CRT_UUID_DECL(ID3D9VkExtSwapchain, 0x13776e93,0x4aa9,0x430a,0xa4,0xec,0xfe,0x9e,0x28,0x11,0x81,0xd5);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -101,4 +101,14 @@ extern "C" {
|
||||||
DLLEXPORT void __stdcall Direct3D9ForceHybridEnumeration(UINT uHybrid) {
|
DLLEXPORT void __stdcall Direct3D9ForceHybridEnumeration(UINT uHybrid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DLLEXPORT IDirect3D9* __stdcall Direct3DCreate9On12(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count) {
|
||||||
|
dxvk::Logger::warn("Direct3DCreate9On12: 9On12 functionality is unimplemented.");
|
||||||
|
return Direct3DCreate9(sdk_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
DLLEXPORT HRESULT __stdcall Direct3DCreate9On12Ex(UINT sdk_version, D3D9ON12_ARGS* override_list, UINT override_entry_count, IDirect3D9Ex** output) {
|
||||||
|
dxvk::Logger::warn("Direct3DCreate9On12Ex: 9On12 functionality is unimplemented.");
|
||||||
|
return Direct3DCreate9Ex(sdk_version, output);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace dxvk {
|
||||||
D3D9Memory (D3D9Memory&& other);
|
D3D9Memory (D3D9Memory&& other);
|
||||||
D3D9Memory& operator = (D3D9Memory&& other);
|
D3D9Memory& operator = (D3D9Memory&& other);
|
||||||
|
|
||||||
operator bool() const { return m_chunk != nullptr; }
|
explicit operator bool() const { return m_chunk != nullptr; }
|
||||||
|
|
||||||
void Map();
|
void Map();
|
||||||
void Unmap();
|
void Unmap();
|
||||||
|
@ -139,7 +139,7 @@ namespace dxvk {
|
||||||
D3D9Memory (D3D9Memory&& other);
|
D3D9Memory (D3D9Memory&& other);
|
||||||
D3D9Memory& operator = (D3D9Memory&& other);
|
D3D9Memory& operator = (D3D9Memory&& other);
|
||||||
|
|
||||||
operator bool() const { return m_ptr != nullptr; }
|
explicit operator bool() const { return m_ptr != nullptr; }
|
||||||
|
|
||||||
void Map() {}
|
void Map() {}
|
||||||
void Unmap() {}
|
void Unmap() {}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include "d3d9_on_12.h"
|
||||||
|
|
||||||
|
#include "d3d9_device.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
D3D9On12::D3D9On12(D3D9DeviceEx* device)
|
||||||
|
: m_device(device) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D9On12::QueryInterface(REFIID riid, void** object) {
|
||||||
|
return m_device->QueryInterface(riid, object);
|
||||||
|
}
|
||||||
|
ULONG STDMETHODCALLTYPE D3D9On12::AddRef() {
|
||||||
|
return m_device->AddRef();
|
||||||
|
}
|
||||||
|
ULONG STDMETHODCALLTYPE D3D9On12::Release() {
|
||||||
|
return m_device->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D9On12::GetD3D12Device(REFIID riid, void** object) {
|
||||||
|
InitReturnPtr(object);
|
||||||
|
|
||||||
|
Logger::err("D3D9On12::GetD3D12Device: Stub");
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D9On12::UnwrapUnderlyingResource(IDirect3DResource9* resource, ID3D12CommandQueue* command_queue, REFIID riid, void** object) {
|
||||||
|
Logger::err("D3D9On12::GetD3D12Device: UnwrapUnderlyingResource: Stub");
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D9On12::ReturnUnderlyingResource(IDirect3DResource9* resource, UINT num_sync, UINT64* signal_values, ID3D12Fence** fences) {
|
||||||
|
if (num_sync)
|
||||||
|
Logger::err("D3D9On12::GetD3D12Device: ReturnUnderlyingResource: Stub");
|
||||||
|
|
||||||
|
m_device->FlushAndSync9On12();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "d3d9_include.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
class D3D9DeviceEx;
|
||||||
|
|
||||||
|
class D3D9On12 final : public IDirect3DDevice9On12 {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
D3D9On12(D3D9DeviceEx* device);
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** object);
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
ULONG STDMETHODCALLTYPE Release();
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE GetD3D12Device(REFIID riid, void** object);
|
||||||
|
HRESULT STDMETHODCALLTYPE UnwrapUnderlyingResource(IDirect3DResource9* resource, ID3D12CommandQueue* command_queue, REFIID riid, void** object);
|
||||||
|
HRESULT STDMETHODCALLTYPE ReturnUnderlyingResource(IDirect3DResource9* resource, UINT num_sync, UINT64* signal_values, ID3D12Fence** fences);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
D3D9DeviceEx* m_device;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "../util/util_math.h"
|
||||||
|
|
||||||
#include "d3d9_options.h"
|
#include "d3d9_options.h"
|
||||||
|
|
||||||
#include "d3d9_caps.h"
|
#include "d3d9_caps.h"
|
||||||
|
@ -35,8 +37,8 @@ namespace dxvk {
|
||||||
this->customDeviceId = parsePciId(config.getOption<std::string>("d3d9.customDeviceId"));
|
this->customDeviceId = parsePciId(config.getOption<std::string>("d3d9.customDeviceId"));
|
||||||
this->customDeviceDesc = config.getOption<std::string>("d3d9.customDeviceDesc");
|
this->customDeviceDesc = config.getOption<std::string>("d3d9.customDeviceDesc");
|
||||||
|
|
||||||
const int32_t vendorId = this->customDeviceId != -1
|
const uint32_t vendorId = this->customVendorId != -1
|
||||||
? this->customDeviceId
|
? this->customVendorId
|
||||||
: (adapter != nullptr ? adapter->deviceProperties().vendorID : 0);
|
: (adapter != nullptr ? adapter->deviceProperties().vendorID : 0);
|
||||||
|
|
||||||
this->maxFrameLatency = config.getOption<int32_t> ("d3d9.maxFrameLatency", 0);
|
this->maxFrameLatency = config.getOption<int32_t> ("d3d9.maxFrameLatency", 0);
|
||||||
|
@ -51,29 +53,34 @@ namespace dxvk {
|
||||||
this->deferSurfaceCreation = config.getOption<bool> ("d3d9.deferSurfaceCreation", false);
|
this->deferSurfaceCreation = config.getOption<bool> ("d3d9.deferSurfaceCreation", false);
|
||||||
this->samplerAnisotropy = config.getOption<int32_t> ("d3d9.samplerAnisotropy", -1);
|
this->samplerAnisotropy = config.getOption<int32_t> ("d3d9.samplerAnisotropy", -1);
|
||||||
this->maxAvailableMemory = config.getOption<int32_t> ("d3d9.maxAvailableMemory", 4096);
|
this->maxAvailableMemory = config.getOption<int32_t> ("d3d9.maxAvailableMemory", 4096);
|
||||||
this->supportDFFormats = config.getOption<bool> ("d3d9.supportDFFormats", true);
|
this->supportDFFormats = config.getOption<bool> ("d3d9.supportDFFormats", vendorId != uint32_t(DxvkGpuVendor::Nvidia));
|
||||||
this->supportX4R4G4B4 = config.getOption<bool> ("d3d9.supportX4R4G4B4", true);
|
this->supportX4R4G4B4 = config.getOption<bool> ("d3d9.supportX4R4G4B4", true);
|
||||||
this->supportD32 = config.getOption<bool> ("d3d9.supportD32", true);
|
this->supportD32 = config.getOption<bool> ("d3d9.supportD32", true);
|
||||||
this->useD32forD24 = config.getOption<bool> ("d3d9.useD32forD24", false);
|
this->useD32forD24 = config.getOption<bool> ("d3d9.useD32forD24", false);
|
||||||
this->disableA8RT = config.getOption<bool> ("d3d9.disableA8RT", false);
|
this->disableA8RT = config.getOption<bool> ("d3d9.disableA8RT", false);
|
||||||
this->invariantPosition = config.getOption<bool> ("d3d9.invariantPosition", true);
|
this->invariantPosition = config.getOption<bool> ("d3d9.invariantPosition", true);
|
||||||
this->memoryTrackTest = config.getOption<bool> ("d3d9.memoryTrackTest", false);
|
this->memoryTrackTest = config.getOption<bool> ("d3d9.memoryTrackTest", false);
|
||||||
this->supportVCache = config.getOption<bool> ("d3d9.supportVCache", vendorId == 0x10de);
|
this->supportVCache = config.getOption<bool> ("d3d9.supportVCache", vendorId == uint32_t(DxvkGpuVendor::Nvidia));
|
||||||
this->enableDialogMode = config.getOption<bool> ("d3d9.enableDialogMode", false);
|
this->enableDialogMode = config.getOption<bool> ("d3d9.enableDialogMode", false);
|
||||||
this->forceSamplerTypeSpecConstants = config.getOption<bool> ("d3d9.forceSamplerTypeSpecConstants", false);
|
this->forceSamplerTypeSpecConstants = config.getOption<bool> ("d3d9.forceSamplerTypeSpecConstants", false);
|
||||||
this->forceSwapchainMSAA = config.getOption<int32_t> ("d3d9.forceSwapchainMSAA", -1);
|
this->forceSwapchainMSAA = config.getOption<int32_t> ("d3d9.forceSwapchainMSAA", -1);
|
||||||
this->forceSampleRateShading = config.getOption<bool> ("d3d9.forceSampleRateShading", false);
|
this->forceSampleRateShading = config.getOption<bool> ("d3d9.forceSampleRateShading", false);
|
||||||
this->forceAspectRatio = config.getOption<std::string> ("d3d9.forceAspectRatio", "");
|
this->forceAspectRatio = config.getOption<std::string> ("d3d9.forceAspectRatio", "");
|
||||||
this->allowDiscard = config.getOption<bool> ("d3d9.allowDiscard", true);
|
|
||||||
this->enumerateByDisplays = config.getOption<bool> ("d3d9.enumerateByDisplays", true);
|
this->enumerateByDisplays = config.getOption<bool> ("d3d9.enumerateByDisplays", true);
|
||||||
this->longMad = config.getOption<bool> ("d3d9.longMad", false);
|
this->longMad = config.getOption<bool> ("d3d9.longMad", false);
|
||||||
this->tearFree = config.getOption<Tristate> ("d3d9.tearFree", Tristate::Auto);
|
this->cachedDynamicBuffers = config.getOption<bool> ("d3d9.cachedDynamicBuffers", false);
|
||||||
this->apitraceMode = config.getOption<bool> ("d3d9.apitraceMode", false);
|
|
||||||
this->deviceLocalConstantBuffers = config.getOption<bool> ("d3d9.deviceLocalConstantBuffers", false);
|
this->deviceLocalConstantBuffers = config.getOption<bool> ("d3d9.deviceLocalConstantBuffers", false);
|
||||||
this->allowDirectBufferMapping = config.getOption<bool> ("d3d9.allowDirectBufferMapping", true);
|
this->allowDirectBufferMapping = config.getOption<bool> ("d3d9.allowDirectBufferMapping", true);
|
||||||
this->seamlessCubes = config.getOption<bool> ("d3d9.seamlessCubes", false);
|
this->seamlessCubes = config.getOption<bool> ("d3d9.seamlessCubes", false);
|
||||||
this->textureMemory = config.getOption<int32_t> ("d3d9.textureMemory", 100) << 20;
|
this->textureMemory = config.getOption<int32_t> ("d3d9.textureMemory", 100) << 20;
|
||||||
this->deviceLost = config.getOption<bool> ("d3d9.deviceLost", false);
|
this->deviceLossOnFocusLoss = config.getOption<bool> ("d3d9.deviceLossOnFocusLoss", false);
|
||||||
|
this->samplerLodBias = config.getOption<float> ("d3d9.samplerLodBias", 0.0f);
|
||||||
|
this->clampNegativeLodBias = config.getOption<bool> ("d3d9.clampNegativeLodBias", false);
|
||||||
|
this->countLosableResources = config.getOption<bool> ("d3d9.countLosableResources", true);
|
||||||
|
this->reproducibleCommandStream = config.getOption<bool> ("d3d9.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);
|
||||||
|
|
||||||
std::string floatEmulation = Config::toLower(config.getOption<std::string>("d3d9.floatEmulation", "auto"));
|
std::string floatEmulation = Config::toLower(config.getOption<std::string>("d3d9.floatEmulation", "auto"));
|
||||||
if (floatEmulation == "strict") {
|
if (floatEmulation == "strict") {
|
||||||
|
@ -84,7 +91,8 @@ namespace dxvk {
|
||||||
d3d9FloatEmulation = D3D9FloatEmulation::Enabled;
|
d3d9FloatEmulation = D3D9FloatEmulation::Enabled;
|
||||||
} else {
|
} else {
|
||||||
bool hasMulz = adapter != nullptr
|
bool hasMulz = adapter != nullptr
|
||||||
&& adapter->matchesDriver(VK_DRIVER_ID_MESA_RADV, 0, 0);
|
&& (adapter->matchesDriver(VK_DRIVER_ID_MESA_RADV)
|
||||||
|
|| adapter->matchesDriver(VK_DRIVER_ID_MESA_NVK));
|
||||||
d3d9FloatEmulation = hasMulz ? D3D9FloatEmulation::Strict : D3D9FloatEmulation::Enabled;
|
d3d9FloatEmulation = hasMulz ? D3D9FloatEmulation::Strict : D3D9FloatEmulation::Enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,9 +116,6 @@ namespace dxvk {
|
||||||
/// Forces sample rate shading
|
/// Forces sample rate shading
|
||||||
bool forceSampleRateShading;
|
bool forceSampleRateShading;
|
||||||
|
|
||||||
/// Allow D3DLOCK_DISCARD
|
|
||||||
bool allowDiscard;
|
|
||||||
|
|
||||||
/// Enumerate adapters by displays
|
/// Enumerate adapters by displays
|
||||||
bool enumerateByDisplays;
|
bool enumerateByDisplays;
|
||||||
|
|
||||||
|
@ -127,12 +124,8 @@ namespace dxvk {
|
||||||
/// don't match entirely to the regular vertex shader in this way.
|
/// don't match entirely to the regular vertex shader in this way.
|
||||||
bool longMad;
|
bool longMad;
|
||||||
|
|
||||||
/// Tear-free mode if vsync is disabled
|
/// Cached dynamic buffers: Maps all buffers in cached memory.
|
||||||
/// Tearing mode if vsync is enabled
|
bool cachedDynamicBuffers;
|
||||||
Tristate tearFree;
|
|
||||||
|
|
||||||
/// Apitrace mode: Maps all buffers in cached memory.
|
|
||||||
bool apitraceMode;
|
|
||||||
|
|
||||||
/// Use device local memory for constant buffers.
|
/// Use device local memory for constant buffers.
|
||||||
bool deviceLocalConstantBuffers;
|
bool deviceLocalConstantBuffers;
|
||||||
|
@ -143,6 +136,14 @@ namespace dxvk {
|
||||||
/// Don't use non seamless cube maps
|
/// Don't use non seamless cube maps
|
||||||
bool seamlessCubes;
|
bool seamlessCubes;
|
||||||
|
|
||||||
|
/// Mipmap LOD bias
|
||||||
|
///
|
||||||
|
/// Enforces the given LOD bias for all samplers.
|
||||||
|
float samplerLodBias;
|
||||||
|
|
||||||
|
/// Clamps negative LOD bias
|
||||||
|
bool clampNegativeLodBias;
|
||||||
|
|
||||||
/// How much virtual memory will be used for textures (in MB).
|
/// How much virtual memory will be used for textures (in MB).
|
||||||
int32_t textureMemory;
|
int32_t textureMemory;
|
||||||
|
|
||||||
|
@ -150,7 +151,15 @@ namespace dxvk {
|
||||||
std::string shaderDumpPath;
|
std::string shaderDumpPath;
|
||||||
|
|
||||||
/// Enable emulation of device loss when a fullscreen app loses focus
|
/// Enable emulation of device loss when a fullscreen app loses focus
|
||||||
bool deviceLost;
|
bool deviceLossOnFocusLoss;
|
||||||
|
|
||||||
|
/// Disable counting losable resources and rejecting calls to Reset() if any are still alive
|
||||||
|
bool countLosableResources;
|
||||||
|
|
||||||
|
/// 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,11 +41,6 @@ namespace dxvk {
|
||||||
case D3DQUERYTYPE_TIMESTAMPFREQ:
|
case D3DQUERYTYPE_TIMESTAMPFREQ:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
m_query[0] = dxvkDevice->createGpuQuery(
|
|
||||||
VK_QUERY_TYPE_PIPELINE_STATISTICS, 0, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw DxvkError(str::format("D3D9Query: Unsupported query type ", m_queryType));
|
throw DxvkError(str::format("D3D9Query: Unsupported query type ", m_queryType));
|
||||||
}
|
}
|
||||||
|
@ -160,7 +155,7 @@ namespace dxvk {
|
||||||
// they didn't call end, do some flushy stuff...
|
// they didn't call end, do some flushy stuff...
|
||||||
if (flush && hr == S_FALSE && m_state != D3D9_VK_QUERY_BEGUN) {
|
if (flush && hr == S_FALSE && m_state != D3D9_VK_QUERY_BEGUN) {
|
||||||
this->NotifyStall();
|
this->NotifyStall();
|
||||||
m_parent->FlushImplicit(FALSE);
|
m_parent->ConsiderFlush(GpuFlushType::ImplicitSynchronization);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -222,12 +217,10 @@ namespace dxvk {
|
||||||
|
|
||||||
switch (m_queryType) {
|
switch (m_queryType) {
|
||||||
case D3DQUERYTYPE_VCACHE:
|
case D3DQUERYTYPE_VCACHE:
|
||||||
// Don't know what the hell any of this means.
|
m_dataCache.VCache.Pattern = MAKEFOURCC('C', 'A', 'C', 'H');
|
||||||
// Nor do I care. This just makes games work.
|
|
||||||
m_dataCache.VCache.Pattern = MAKEFOURCC('H', 'C', 'A', 'C');
|
|
||||||
m_dataCache.VCache.OptMethod = 1;
|
m_dataCache.VCache.OptMethod = 1;
|
||||||
m_dataCache.VCache.CacheSize = 24;
|
m_dataCache.VCache.CacheSize = 16;
|
||||||
m_dataCache.VCache.MagicNumber = 20;
|
m_dataCache.VCache.MagicNumber = 7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3DQUERYTYPE_OCCLUSION:
|
case D3DQUERYTYPE_OCCLUSION:
|
||||||
|
@ -246,11 +239,6 @@ namespace dxvk {
|
||||||
m_dataCache.TimestampFreq = GetTimestampQueryFrequency();
|
m_dataCache.TimestampFreq = GetTimestampQueryFrequency();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
m_dataCache.VertexStats.NumRenderedTriangles = queryData[0].statistic.iaPrimitives;
|
|
||||||
m_dataCache.VertexStats.NumExtraClippingTriangles = queryData[0].statistic.clipPrimitives;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -276,7 +264,6 @@ namespace dxvk {
|
||||||
void D3D9Query::Begin(DxvkContext* ctx) {
|
void D3D9Query::Begin(DxvkContext* ctx) {
|
||||||
switch (m_queryType) {
|
switch (m_queryType) {
|
||||||
case D3DQUERYTYPE_OCCLUSION:
|
case D3DQUERYTYPE_OCCLUSION:
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
ctx->beginQuery(m_query[0]);
|
ctx->beginQuery(m_query[0]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -296,7 +283,6 @@ namespace dxvk {
|
||||||
ctx->writeTimestamp(m_query[0]);
|
ctx->writeTimestamp(m_query[0]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
case D3DQUERYTYPE_OCCLUSION:
|
case D3DQUERYTYPE_OCCLUSION:
|
||||||
ctx->endQuery(m_query[0]);
|
ctx->endQuery(m_query[0]);
|
||||||
break;
|
break;
|
||||||
|
@ -314,7 +300,6 @@ namespace dxvk {
|
||||||
|
|
||||||
bool D3D9Query::QueryBeginnable(D3DQUERYTYPE QueryType) {
|
bool D3D9Query::QueryBeginnable(D3DQUERYTYPE QueryType) {
|
||||||
return QueryType == D3DQUERYTYPE_OCCLUSION
|
return QueryType == D3DQUERYTYPE_OCCLUSION
|
||||||
|| QueryType == D3DQUERYTYPE_VERTEXSTATS
|
|
||||||
|| QueryType == D3DQUERYTYPE_TIMESTAMPDISJOINT;
|
|| QueryType == D3DQUERYTYPE_TIMESTAMPDISJOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +323,6 @@ namespace dxvk {
|
||||||
case D3DQUERYTYPE_TIMESTAMP:
|
case D3DQUERYTYPE_TIMESTAMP:
|
||||||
case D3DQUERYTYPE_TIMESTAMPDISJOINT:
|
case D3DQUERYTYPE_TIMESTAMPDISJOINT:
|
||||||
case D3DQUERYTYPE_TIMESTAMPFREQ:
|
case D3DQUERYTYPE_TIMESTAMPFREQ:
|
||||||
case D3DQUERYTYPE_VERTEXSTATS:
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -13,14 +13,14 @@ namespace dxvk {
|
||||||
enum D3D9SpecConstantId : uint32_t {
|
enum D3D9SpecConstantId : uint32_t {
|
||||||
SpecSamplerType, // 2 bits for 16 PS samplers | Bits: 32
|
SpecSamplerType, // 2 bits for 16 PS samplers | Bits: 32
|
||||||
|
|
||||||
SpecSamplerDepthMode, // 1 bit for 20 VS + PS samplers | Bits: 20
|
SpecSamplerDepthMode, // 1 bit for 21 VS + PS samplers | Bits: 21
|
||||||
SpecAlphaCompareOp, // Range: 0 -> 7 | Bits: 3
|
SpecAlphaCompareOp, // Range: 0 -> 7 | Bits: 3
|
||||||
SpecPointMode, // Range: 0 -> 3 | Bits: 2
|
SpecPointMode, // Range: 0 -> 3 | Bits: 2
|
||||||
SpecVertexFogMode, // Range: 0 -> 3 | Bits: 2
|
SpecVertexFogMode, // Range: 0 -> 3 | Bits: 2
|
||||||
SpecPixelFogMode, // Range: 0 -> 3 | Bits: 2
|
SpecPixelFogMode, // Range: 0 -> 3 | Bits: 2
|
||||||
SpecFogEnabled, // Range: 0 -> 1 | Bits: 1
|
SpecFogEnabled, // Range: 0 -> 1 | Bits: 1
|
||||||
|
|
||||||
SpecSamplerNull, // 1 bit for 20 samplers | Bits: 20
|
SpecSamplerNull, // 1 bit for 21 samplers | Bits: 21
|
||||||
SpecProjectionType, // 1 bit for 6 PS 1.x samplers | Bits: 6
|
SpecProjectionType, // 1 bit for 6 PS 1.x samplers | Bits: 6
|
||||||
SpecAlphaPrecisionBits, // Range: 0 -> 8 or 0xF | Bits: 4
|
SpecAlphaPrecisionBits, // Range: 0 -> 8 or 0xF | Bits: 4
|
||||||
|
|
||||||
|
@ -49,16 +49,16 @@ namespace dxvk {
|
||||||
static constexpr std::array<BitfieldPosition, SpecConstantCount> Layout{{
|
static constexpr std::array<BitfieldPosition, SpecConstantCount> Layout{{
|
||||||
{ 0, 0, 32 }, // SamplerType
|
{ 0, 0, 32 }, // SamplerType
|
||||||
|
|
||||||
{ 1, 0, 20 }, // SamplerDepthMode
|
{ 1, 0, 21 }, // SamplerDepthMode
|
||||||
{ 1, 20, 3 }, // AlphaCompareOp
|
{ 1, 21, 3 }, // AlphaCompareOp
|
||||||
{ 1, 23, 2 }, // PointMode
|
{ 1, 24, 2 }, // PointMode
|
||||||
{ 1, 25, 2 }, // VertexFogMode
|
{ 1, 26, 2 }, // VertexFogMode
|
||||||
{ 1, 27, 2 }, // PixelFogMode
|
{ 1, 28, 2 }, // PixelFogMode
|
||||||
{ 1, 29, 1 }, // FogEnabled
|
{ 1, 30, 1 }, // FogEnabled
|
||||||
|
|
||||||
{ 2, 0, 20 }, // SamplerNull
|
{ 2, 0, 21 }, // SamplerNull
|
||||||
{ 2, 20, 6 }, // ProjectionType
|
{ 2, 21, 6 }, // ProjectionType
|
||||||
{ 2, 26, 4 }, // AlphaPrecisionBits
|
{ 2, 27, 4 }, // AlphaPrecisionBits
|
||||||
|
|
||||||
{ 3, 0, 16 }, // VertexShaderBools
|
{ 3, 0, 16 }, // VertexShaderBools
|
||||||
{ 3, 16, 16 }, // PixelShaderBools
|
{ 3, 16, 16 }, // PixelShaderBools
|
||||||
|
|
|
@ -195,7 +195,7 @@ namespace dxvk {
|
||||||
const T* operator & () const { ensure(); return m_data.get(); }
|
const T* operator & () const { ensure(); return m_data.get(); }
|
||||||
T* operator & () { ensure(); return m_data.get(); }
|
T* operator & () { ensure(); return m_data.get(); }
|
||||||
|
|
||||||
operator bool() { return m_data != nullptr; }
|
explicit operator bool() const { return m_data != nullptr; }
|
||||||
operator T() { ensure(); return *m_data; }
|
operator T() { ensure(); return *m_data; }
|
||||||
|
|
||||||
void ensure() const { if (!m_data) m_data = std::make_unique<T>(); }
|
void ensure() const { if (!m_data) m_data = std::make_unique<T>(); }
|
||||||
|
@ -213,7 +213,7 @@ namespace dxvk {
|
||||||
|
|
||||||
T& operator=(const T& x) { m_data = x; return m_data; }
|
T& operator=(const T& x) { m_data = x; return m_data; }
|
||||||
|
|
||||||
operator bool() { return true; }
|
explicit operator bool() const { return true; }
|
||||||
operator T() { return m_data; }
|
operator T() { return m_data; }
|
||||||
|
|
||||||
const T* operator -> () const { return &m_data; }
|
const T* operator -> () const { return &m_data; }
|
||||||
|
|
|
@ -17,6 +17,10 @@ namespace dxvk {
|
||||||
CaptureType(Type);
|
CaptureType(Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D3D9StateBlock::~D3D9StateBlock() {
|
||||||
|
if (!m_parent->IsD3D8Compatible())
|
||||||
|
m_parent->DecrementLosableCounter();
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9StateBlock::QueryInterface(
|
HRESULT STDMETHODCALLTYPE D3D9StateBlock::QueryInterface(
|
||||||
REFIID riid,
|
REFIID riid,
|
||||||
|
@ -572,4 +576,4 @@ namespace dxvk {
|
||||||
this->Capture();
|
this->Capture();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,8 @@ namespace dxvk {
|
||||||
|
|
||||||
D3D9StateBlock(D3D9DeviceEx* pDevice, D3D9StateBlockType Type);
|
D3D9StateBlock(D3D9DeviceEx* pDevice, D3D9StateBlockType Type);
|
||||||
|
|
||||||
|
~D3D9StateBlock();
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||||
REFIID riid,
|
REFIID riid,
|
||||||
void** ppvObject) final;
|
void** ppvObject) final;
|
||||||
|
|
|
@ -28,19 +28,21 @@ namespace dxvk {
|
||||||
, m_device (pDevice->GetDXVKDevice())
|
, m_device (pDevice->GetDXVKDevice())
|
||||||
, m_context (m_device->createContext(DxvkContextType::Supplementary))
|
, m_context (m_device->createContext(DxvkContextType::Supplementary))
|
||||||
, m_frameLatencyCap (pDevice->GetOptions()->maxFrameLatency)
|
, m_frameLatencyCap (pDevice->GetOptions()->maxFrameLatency)
|
||||||
, m_frameLatencySignal(new sync::Fence(m_frameId))
|
, m_dialog (pDevice->GetOptions()->enableDialogMode)
|
||||||
, m_dialog (pDevice->GetOptions()->enableDialogMode) {
|
, m_swapchainExt (this) {
|
||||||
this->NormalizePresentParameters(pPresentParams);
|
this->NormalizePresentParameters(pPresentParams);
|
||||||
m_presentParams = *pPresentParams;
|
m_presentParams = *pPresentParams;
|
||||||
m_window = m_presentParams.hDeviceWindow;
|
m_window = m_presentParams.hDeviceWindow;
|
||||||
|
|
||||||
|
UpdateWindowCtx();
|
||||||
|
|
||||||
UpdatePresentRegion(nullptr, nullptr);
|
UpdatePresentRegion(nullptr, nullptr);
|
||||||
|
|
||||||
if (m_window) {
|
if (m_window) {
|
||||||
CreatePresenter();
|
CreatePresenter();
|
||||||
|
|
||||||
if (!pDevice->GetOptions()->deferSurfaceCreation)
|
if (!pDevice->GetOptions()->deferSurfaceCreation)
|
||||||
RecreateSwapChain(false);
|
RecreateSwapChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(CreateBackBuffers(m_presentParams.BackBufferCount)))
|
if (FAILED(CreateBackBuffers(m_presentParams.BackBufferCount)))
|
||||||
|
@ -63,6 +65,16 @@ namespace dxvk {
|
||||||
if (this_thread::isInModuleDetachment())
|
if (this_thread::isInModuleDetachment())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
// Locking here and in Device::GetFrontBufferData
|
||||||
|
// ensures that other threads don't accidentally access a stale pointer.
|
||||||
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
|
if (m_parent->GetMostRecentlyUsedSwapchain() == this) {
|
||||||
|
m_parent->ResetMostRecentlyUsedSwapchain();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DestroyBackBuffers();
|
DestroyBackBuffers();
|
||||||
|
|
||||||
ResetWindowProc(m_window);
|
ResetWindowProc(m_window);
|
||||||
|
@ -70,6 +82,8 @@ namespace dxvk {
|
||||||
|
|
||||||
m_device->waitForSubmission(&m_presentStatus);
|
m_device->waitForSubmission(&m_presentStatus);
|
||||||
m_device->waitForIdle();
|
m_device->waitForIdle();
|
||||||
|
|
||||||
|
m_parent->DecrementLosableCounter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,6 +100,11 @@ namespace dxvk {
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (riid == __uuidof(ID3D9VkExtSwapchain)) {
|
||||||
|
*ppvObject = ref(&m_swapchainExt);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (logQueryInterfaceError(__uuidof(IDirect3DSwapChain9), riid)) {
|
if (logQueryInterfaceError(__uuidof(IDirect3DSwapChain9), riid)) {
|
||||||
Logger::warn("D3D9SwapChainEx::QueryInterface: Unknown interface query");
|
Logger::warn("D3D9SwapChainEx::QueryInterface: Unknown interface query");
|
||||||
Logger::warn(str::format(riid));
|
Logger::warn(str::format(riid));
|
||||||
|
@ -103,6 +122,8 @@ namespace dxvk {
|
||||||
DWORD dwFlags) {
|
DWORD dwFlags) {
|
||||||
D3D9DeviceLock lock = m_parent->LockDevice();
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
|
m_parent->SetMostRecentlyUsedSwapchain(this);
|
||||||
|
|
||||||
if (unlikely(m_parent->IsDeviceLost()))
|
if (unlikely(m_parent->IsDeviceLost()))
|
||||||
return D3DERR_DEVICELOST;
|
return D3DERR_DEVICELOST;
|
||||||
|
|
||||||
|
@ -129,33 +150,32 @@ namespace dxvk {
|
||||||
if (options->presentInterval >= 0)
|
if (options->presentInterval >= 0)
|
||||||
presentInterval = options->presentInterval;
|
presentInterval = options->presentInterval;
|
||||||
|
|
||||||
bool vsync = presentInterval != 0;
|
m_window = m_presentParams.hDeviceWindow;
|
||||||
|
|
||||||
HWND window = m_presentParams.hDeviceWindow;
|
|
||||||
if (hDestWindowOverride != nullptr)
|
if (hDestWindowOverride != nullptr)
|
||||||
window = hDestWindowOverride;
|
m_window = hDestWindowOverride;
|
||||||
|
|
||||||
|
UpdateWindowCtx();
|
||||||
|
|
||||||
bool recreate = false;
|
bool recreate = false;
|
||||||
recreate |= m_presenter == nullptr;
|
recreate |= m_wctx->presenter == nullptr;
|
||||||
recreate |= window != m_window;
|
|
||||||
recreate |= m_dialog != m_lastDialog;
|
recreate |= m_dialog != m_lastDialog;
|
||||||
|
if (options->deferSurfaceCreation)
|
||||||
|
recreate |= m_parent->IsDeviceReset();
|
||||||
|
|
||||||
m_window = window;
|
if (m_wctx->presenter != nullptr) {
|
||||||
|
m_dirty |= m_wctx->presenter->setSyncInterval(presentInterval) != VK_SUCCESS;
|
||||||
|
m_dirty |= !m_wctx->presenter->hasSwapChain();
|
||||||
|
}
|
||||||
|
|
||||||
m_dirty |= vsync != m_vsync;
|
|
||||||
m_dirty |= UpdatePresentRegion(pSourceRect, pDestRect);
|
m_dirty |= UpdatePresentRegion(pSourceRect, pDestRect);
|
||||||
m_dirty |= recreate;
|
m_dirty |= recreate;
|
||||||
m_dirty |= m_presenter != nullptr &&
|
|
||||||
!m_presenter->hasSwapChain();
|
|
||||||
|
|
||||||
m_vsync = vsync;
|
|
||||||
|
|
||||||
m_lastDialog = m_dialog;
|
m_lastDialog = m_dialog;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
const bool useGDIFallback = m_partialCopy && !HasFrontBuffer();
|
const bool useGDIFallback = m_partialCopy && !HasFrontBuffer();
|
||||||
if (useGDIFallback)
|
if (useGDIFallback)
|
||||||
return PresentImageGDI(window);
|
return PresentImageGDI(m_window);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -163,12 +183,12 @@ namespace dxvk {
|
||||||
CreatePresenter();
|
CreatePresenter();
|
||||||
|
|
||||||
if (std::exchange(m_dirty, false))
|
if (std::exchange(m_dirty, false))
|
||||||
RecreateSwapChain(vsync);
|
RecreateSwapChain();
|
||||||
|
|
||||||
// We aren't going to device loss simply because
|
// We aren't going to device loss simply because
|
||||||
// 99% of D3D9 games don't handle this properly and
|
// 99% of D3D9 games don't handle this properly and
|
||||||
// just end up crashing (like with alt-tab loss)
|
// just end up crashing (like with alt-tab loss)
|
||||||
if (!m_presenter->hasSwapChain())
|
if (!m_wctx->presenter->hasSwapChain())
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
|
||||||
PresentImage(presentInterval);
|
PresentImage(presentInterval);
|
||||||
|
@ -176,7 +196,7 @@ namespace dxvk {
|
||||||
} catch (const DxvkError& e) {
|
} catch (const DxvkError& e) {
|
||||||
Logger::err(e.message());
|
Logger::err(e.message());
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return PresentImageGDI(window);
|
return PresentImageGDI(m_window);
|
||||||
#else
|
#else
|
||||||
return D3DERR_DEVICEREMOVED;
|
return D3DERR_DEVICEREMOVED;
|
||||||
#endif
|
#endif
|
||||||
|
@ -374,6 +394,20 @@ namespace dxvk {
|
||||||
blitInfo.srcOffsets[0] = VkOffset3D{ 0, 0, 0 };
|
blitInfo.srcOffsets[0] = VkOffset3D{ 0, 0, 0 };
|
||||||
blitInfo.srcOffsets[1] = VkOffset3D{ int32_t(srcExtent.width), int32_t(srcExtent.height), 1 };
|
blitInfo.srcOffsets[1] = VkOffset3D{ int32_t(srcExtent.width), int32_t(srcExtent.height), 1 };
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (m_presentParams.Windowed) {
|
||||||
|
// In windowed mode, GetFrontBufferData takes a screenshot of the entire screen.
|
||||||
|
// So place the copy of the front buffer at the position of the window.
|
||||||
|
POINT point = { 0, 0 };
|
||||||
|
if (ClientToScreen(m_window, &point) != 0) {
|
||||||
|
blitInfo.dstOffsets[0].x = point.x;
|
||||||
|
blitInfo.dstOffsets[0].y = point.y;
|
||||||
|
blitInfo.dstOffsets[1].x += point.x;
|
||||||
|
blitInfo.dstOffsets[1].y += point.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_parent->EmitCs([
|
m_parent->EmitCs([
|
||||||
cDstImage = blittedSrc,
|
cDstImage = blittedSrc,
|
||||||
cDstMap = dstTexInfo->GetMapping().Swizzle,
|
cDstMap = dstTexInfo->GetMapping().Swizzle,
|
||||||
|
@ -432,6 +466,13 @@ namespace dxvk {
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_backBuffers.empty()) {
|
||||||
|
// The backbuffers were destroyed and not recreated.
|
||||||
|
// This can happen when a call to Reset fails.
|
||||||
|
*ppBackBuffer = nullptr;
|
||||||
|
return D3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
*ppBackBuffer = ref(m_backBuffers[iBackBuffer].ptr());
|
*ppBackBuffer = ref(m_backBuffers[iBackBuffer].ptr());
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
@ -671,8 +712,10 @@ namespace dxvk {
|
||||||
if (hWindow == nullptr)
|
if (hWindow == nullptr)
|
||||||
hWindow = m_parent->GetWindow();
|
hWindow = m_parent->GetWindow();
|
||||||
|
|
||||||
if (m_presentParams.hDeviceWindow == hWindow) {
|
if (m_presenters.count(hWindow)) {
|
||||||
m_presenter = nullptr;
|
if (m_wctx == &m_presenters[hWindow])
|
||||||
|
m_wctx = nullptr;
|
||||||
|
m_presenters.erase(hWindow);
|
||||||
|
|
||||||
m_device->waitForSubmission(&m_presentStatus);
|
m_device->waitForSubmission(&m_presentStatus);
|
||||||
m_device->waitForIdle();
|
m_device->waitForIdle();
|
||||||
|
@ -741,25 +784,27 @@ namespace dxvk {
|
||||||
Rc<DxvkImage> swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage();
|
Rc<DxvkImage> swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage();
|
||||||
Rc<DxvkImageView> swapImageView = m_backBuffers[0]->GetImageView(false);
|
Rc<DxvkImageView> swapImageView = m_backBuffers[0]->GetImageView(false);
|
||||||
|
|
||||||
// Bump our frame id.
|
|
||||||
++m_frameId;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < SyncInterval || i < 1; i++) {
|
for (uint32_t i = 0; i < SyncInterval || i < 1; i++) {
|
||||||
SynchronizePresent();
|
SynchronizePresent();
|
||||||
|
|
||||||
// Presentation semaphores and WSI swap chain image
|
// Presentation semaphores and WSI swap chain image
|
||||||
vk::PresenterInfo info = m_presenter->info();
|
PresenterInfo info = m_wctx->presenter->info();
|
||||||
vk::PresenterSync sync;
|
PresenterSync sync;
|
||||||
|
|
||||||
uint32_t imageIndex = 0;
|
uint32_t imageIndex = 0;
|
||||||
|
|
||||||
VkResult status = m_presenter->acquireNextImage(sync, imageIndex);
|
VkResult status = m_wctx->presenter->acquireNextImage(sync, imageIndex);
|
||||||
|
|
||||||
while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) {
|
while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) {
|
||||||
RecreateSwapChain(m_vsync);
|
RecreateSwapChain();
|
||||||
|
|
||||||
info = m_presenter->info();
|
info = m_wctx->presenter->info();
|
||||||
status = m_presenter->acquireNextImage(sync, imageIndex);
|
status = m_wctx->presenter->acquireNextImage(sync, imageIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hdrMetadata && m_dirtyHdrMetadata) {
|
||||||
|
m_wctx->presenter->setHdrMetadata(*m_hdrMetadata);
|
||||||
|
m_dirtyHdrMetadata = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_context->beginRecording(
|
m_context->beginRecording(
|
||||||
|
@ -774,15 +819,12 @@ namespace dxvk {
|
||||||
{ uint32_t(m_dstRect.right - m_dstRect.left), uint32_t(m_dstRect.bottom - m_dstRect.top) } };
|
{ uint32_t(m_dstRect.right - m_dstRect.left), uint32_t(m_dstRect.bottom - m_dstRect.top) } };
|
||||||
|
|
||||||
m_blitter->presentImage(m_context.ptr(),
|
m_blitter->presentImage(m_context.ptr(),
|
||||||
m_imageViews.at(imageIndex), dstRect,
|
m_wctx->imageViews.at(imageIndex), dstRect,
|
||||||
swapImageView, srcRect);
|
swapImageView, srcRect);
|
||||||
|
|
||||||
if (m_hud != nullptr)
|
if (m_hud != nullptr)
|
||||||
m_hud->render(m_context, info.format, info.imageExtent);
|
m_hud->render(m_context, info.format, info.imageExtent);
|
||||||
|
|
||||||
if (i + 1 >= SyncInterval)
|
|
||||||
m_context->signal(m_frameLatencySignal, m_frameId);
|
|
||||||
|
|
||||||
SubmitPresent(sync, i);
|
SubmitPresent(sync, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,24 +839,33 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D9SwapChainEx::SubmitPresent(const vk::PresenterSync& Sync, uint32_t FrameId) {
|
void D3D9SwapChainEx::SubmitPresent(const PresenterSync& Sync, uint32_t Repeat) {
|
||||||
|
// Bump frame ID
|
||||||
|
if (!Repeat)
|
||||||
|
m_wctx->frameId += 1;
|
||||||
|
|
||||||
// Present from CS thread so that we don't
|
// Present from CS thread so that we don't
|
||||||
// have to synchronize with it first.
|
// have to synchronize with it first.
|
||||||
m_presentStatus.result = VK_NOT_READY;
|
m_presentStatus.result = VK_NOT_READY;
|
||||||
|
|
||||||
m_parent->EmitCs([this,
|
m_parent->EmitCs([this,
|
||||||
cFrameId = FrameId,
|
cRepeat = Repeat,
|
||||||
cSync = Sync,
|
cSync = Sync,
|
||||||
cHud = m_hud,
|
cHud = m_hud,
|
||||||
|
cPresentMode = m_wctx->presenter->info().presentMode,
|
||||||
|
cFrameId = m_wctx->frameId,
|
||||||
cCommandList = m_context->endRecording()
|
cCommandList = m_context->endRecording()
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
cCommandList->setWsiSemaphores(cSync);
|
cCommandList->setWsiSemaphores(cSync);
|
||||||
m_device->submitCommandList(cCommandList, nullptr);
|
m_device->submitCommandList(cCommandList, nullptr);
|
||||||
|
|
||||||
if (cHud != nullptr && !cFrameId)
|
if (cHud != nullptr && !cRepeat)
|
||||||
cHud->update();
|
cHud->update();
|
||||||
|
|
||||||
m_device->presentImage(m_presenter, &m_presentStatus);
|
uint64_t frameId = cRepeat ? 0 : cFrameId;
|
||||||
|
|
||||||
|
m_device->presentImage(m_wctx->presenter,
|
||||||
|
cPresentMode, frameId, &m_presentStatus);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_parent->FlushCsChunk();
|
m_parent->FlushCsChunk();
|
||||||
|
@ -826,34 +877,33 @@ namespace dxvk {
|
||||||
VkResult status = m_device->waitForSubmission(&m_presentStatus);
|
VkResult status = m_device->waitForSubmission(&m_presentStatus);
|
||||||
|
|
||||||
if (status != VK_SUCCESS)
|
if (status != VK_SUCCESS)
|
||||||
RecreateSwapChain(m_vsync);
|
RecreateSwapChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D9SwapChainEx::RecreateSwapChain(BOOL Vsync) {
|
void D3D9SwapChainEx::RecreateSwapChain() {
|
||||||
// Ensure that we can safely destroy the swap chain
|
// Ensure that we can safely destroy the swap chain
|
||||||
m_device->waitForSubmission(&m_presentStatus);
|
m_device->waitForSubmission(&m_presentStatus);
|
||||||
m_device->waitForIdle();
|
m_device->waitForIdle();
|
||||||
|
|
||||||
m_presentStatus.result = VK_SUCCESS;
|
m_presentStatus.result = VK_SUCCESS;
|
||||||
|
|
||||||
vk::PresenterDesc presenterDesc;
|
PresenterDesc presenterDesc;
|
||||||
presenterDesc.imageExtent = GetPresentExtent();
|
presenterDesc.imageExtent = GetPresentExtent();
|
||||||
presenterDesc.imageCount = PickImageCount(m_presentParams.BackBufferCount + 1);
|
presenterDesc.imageCount = PickImageCount(m_presentParams.BackBufferCount + 1);
|
||||||
presenterDesc.numFormats = PickFormats(EnumerateFormat(m_presentParams.BackBufferFormat), presenterDesc.formats);
|
presenterDesc.numFormats = PickFormats(EnumerateFormat(m_presentParams.BackBufferFormat), presenterDesc.formats);
|
||||||
presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes);
|
|
||||||
presenterDesc.fullScreenExclusive = PickFullscreenMode();
|
presenterDesc.fullScreenExclusive = PickFullscreenMode();
|
||||||
|
|
||||||
VkResult vr = m_presenter->recreateSwapChain(presenterDesc);
|
VkResult vr = m_wctx->presenter->recreateSwapChain(presenterDesc);
|
||||||
|
|
||||||
if (vr == VK_ERROR_SURFACE_LOST_KHR) {
|
if (vr == VK_ERROR_SURFACE_LOST_KHR) {
|
||||||
vr = m_presenter->recreateSurface([this] (VkSurfaceKHR* surface) {
|
vr = m_wctx->presenter->recreateSurface([this] (VkSurfaceKHR* surface) {
|
||||||
return CreateSurface(surface);
|
return CreateSurface(surface);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (vr)
|
if (vr)
|
||||||
throw DxvkError(str::format("D3D9SwapChainEx: Failed to recreate surface: ", vr));
|
throw DxvkError(str::format("D3D9SwapChainEx: Failed to recreate surface: ", vr));
|
||||||
|
|
||||||
vr = m_presenter->recreateSwapChain(presenterDesc);
|
vr = m_wctx->presenter->recreateSwapChain(presenterDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vr)
|
if (vr)
|
||||||
|
@ -870,27 +920,14 @@ namespace dxvk {
|
||||||
|
|
||||||
m_presentStatus.result = VK_SUCCESS;
|
m_presentStatus.result = VK_SUCCESS;
|
||||||
|
|
||||||
DxvkDeviceQueue graphicsQueue = m_device->queues().graphics;
|
PresenterDesc presenterDesc;
|
||||||
|
|
||||||
vk::PresenterDevice presenterDevice;
|
|
||||||
presenterDevice.queueFamily = graphicsQueue.queueFamily;
|
|
||||||
presenterDevice.queue = graphicsQueue.queueHandle;
|
|
||||||
presenterDevice.adapter = m_device->adapter()->handle();
|
|
||||||
|
|
||||||
vk::PresenterDesc presenterDesc;
|
|
||||||
presenterDesc.imageExtent = GetPresentExtent();
|
presenterDesc.imageExtent = GetPresentExtent();
|
||||||
presenterDesc.imageCount = PickImageCount(m_presentParams.BackBufferCount + 1);
|
presenterDesc.imageCount = PickImageCount(m_presentParams.BackBufferCount + 1);
|
||||||
presenterDesc.numFormats = PickFormats(EnumerateFormat(m_presentParams.BackBufferFormat), presenterDesc.formats);
|
presenterDesc.numFormats = PickFormats(EnumerateFormat(m_presentParams.BackBufferFormat), presenterDesc.formats);
|
||||||
presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes);
|
|
||||||
presenterDesc.fullScreenExclusive = PickFullscreenMode();
|
presenterDesc.fullScreenExclusive = PickFullscreenMode();
|
||||||
|
|
||||||
m_presenter = new vk::Presenter(
|
m_wctx->presenter = new Presenter(m_device, m_wctx->frameLatencySignal, presenterDesc);
|
||||||
m_device->adapter()->vki(),
|
m_wctx->presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate);
|
||||||
m_device->vkd(),
|
|
||||||
presenterDevice,
|
|
||||||
presenterDesc);
|
|
||||||
|
|
||||||
m_presenter->setFrameRateLimit(m_parent->GetOptions()->maxFrameRate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -905,10 +942,10 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
void D3D9SwapChainEx::CreateRenderTargetViews() {
|
void D3D9SwapChainEx::CreateRenderTargetViews() {
|
||||||
vk::PresenterInfo info = m_presenter->info();
|
PresenterInfo info = m_wctx->presenter->info();
|
||||||
|
|
||||||
m_imageViews.clear();
|
m_wctx->imageViews.clear();
|
||||||
m_imageViews.resize(info.imageCount);
|
m_wctx->imageViews.resize(info.imageCount);
|
||||||
|
|
||||||
DxvkImageCreateInfo imageInfo;
|
DxvkImageCreateInfo imageInfo;
|
||||||
imageInfo.type = VK_IMAGE_TYPE_2D;
|
imageInfo.type = VK_IMAGE_TYPE_2D;
|
||||||
|
@ -936,13 +973,13 @@ namespace dxvk {
|
||||||
viewInfo.numLayers = 1;
|
viewInfo.numLayers = 1;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < info.imageCount; i++) {
|
for (uint32_t i = 0; i < info.imageCount; i++) {
|
||||||
VkImage imageHandle = m_presenter->getImage(i).image;
|
VkImage imageHandle = m_wctx->presenter->getImage(i).image;
|
||||||
|
|
||||||
Rc<DxvkImage> image = new DxvkImage(
|
Rc<DxvkImage> image = new DxvkImage(
|
||||||
m_device.ptr(), imageInfo, imageHandle,
|
m_device.ptr(), imageInfo, imageHandle,
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
m_imageViews[i] = new DxvkImageView(
|
m_wctx->imageViews[i] = new DxvkImageView(
|
||||||
m_device->vkd(), image, viewInfo);
|
m_device->vkd(), image, viewInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -956,6 +993,20 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D9SwapChainEx::UpdateWindowCtx() {
|
||||||
|
if (!m_presenters.count(m_window)) {
|
||||||
|
auto res = m_presenters.emplace(
|
||||||
|
std::piecewise_construct,
|
||||||
|
std::forward_as_tuple(m_window),
|
||||||
|
std::forward_as_tuple());
|
||||||
|
|
||||||
|
auto& wctx = res.first->second;
|
||||||
|
wctx.frameLatencySignal = new sync::Fence(wctx.frameId);
|
||||||
|
}
|
||||||
|
m_wctx = &m_presenters[m_window];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT D3D9SwapChainEx::CreateBackBuffers(uint32_t NumBackBuffers) {
|
HRESULT D3D9SwapChainEx::CreateBackBuffers(uint32_t NumBackBuffers) {
|
||||||
// Explicitly destroy current swap image before
|
// Explicitly destroy current swap image before
|
||||||
// creating a new one to free up resources
|
// creating a new one to free up resources
|
||||||
|
@ -988,6 +1039,7 @@ namespace dxvk {
|
||||||
D3D9Surface* surface;
|
D3D9Surface* surface;
|
||||||
try {
|
try {
|
||||||
surface = new D3D9Surface(m_parent, &desc, this, nullptr);
|
surface = new D3D9Surface(m_parent, &desc, this, nullptr);
|
||||||
|
m_parent->IncrementLosableCounter();
|
||||||
} catch (const DxvkError& e) {
|
} catch (const DxvkError& e) {
|
||||||
DestroyBackBuffers();
|
DestroyBackBuffers();
|
||||||
Logger::err(e.message());
|
Logger::err(e.message());
|
||||||
|
@ -1057,9 +1109,13 @@ namespace dxvk {
|
||||||
|
|
||||||
void D3D9SwapChainEx::SyncFrameLatency() {
|
void D3D9SwapChainEx::SyncFrameLatency() {
|
||||||
// Wait for the sync event so that we respect the maximum frame latency
|
// Wait for the sync event so that we respect the maximum frame latency
|
||||||
m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency());
|
m_wctx->frameLatencySignal->wait(m_wctx->frameId - GetActualFrameLatency());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void D3D9SwapChainEx::SetApiName(const char* name) {
|
||||||
|
m_apiName = name;
|
||||||
|
CreateHud();
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t D3D9SwapChainEx::GetActualFrameLatency() {
|
uint32_t D3D9SwapChainEx::GetActualFrameLatency() {
|
||||||
uint32_t maxFrameLatency = m_parent->GetFrameLatency();
|
uint32_t maxFrameLatency = m_parent->GetFrameLatency();
|
||||||
|
@ -1086,46 +1142,36 @@ namespace dxvk {
|
||||||
case D3D9Format::X8R8G8B8:
|
case D3D9Format::X8R8G8B8:
|
||||||
case D3D9Format::A8B8G8R8:
|
case D3D9Format::A8B8G8R8:
|
||||||
case D3D9Format::X8B8G8R8: {
|
case D3D9Format::X8B8G8R8: {
|
||||||
pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
pDstFormats[n++] = { VK_FORMAT_R8G8B8A8_UNORM, m_colorspace };
|
||||||
pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
pDstFormats[n++] = { VK_FORMAT_B8G8R8A8_UNORM, m_colorspace };
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case D3D9Format::A2R10G10B10:
|
case D3D9Format::A2R10G10B10:
|
||||||
case D3D9Format::A2B10G10R10: {
|
case D3D9Format::A2B10G10R10: {
|
||||||
pDstFormats[n++] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
pDstFormats[n++] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, m_colorspace };
|
||||||
pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
pDstFormats[n++] = { VK_FORMAT_A2R10G10B10_UNORM_PACK32, m_colorspace };
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case D3D9Format::X1R5G5B5:
|
case D3D9Format::X1R5G5B5:
|
||||||
case D3D9Format::A1R5G5B5: {
|
case D3D9Format::A1R5G5B5: {
|
||||||
pDstFormats[n++] = { VK_FORMAT_B5G5R5A1_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
pDstFormats[n++] = { VK_FORMAT_B5G5R5A1_UNORM_PACK16, m_colorspace };
|
||||||
pDstFormats[n++] = { VK_FORMAT_R5G5B5A1_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
pDstFormats[n++] = { VK_FORMAT_R5G5B5A1_UNORM_PACK16, m_colorspace };
|
||||||
pDstFormats[n++] = { VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
pDstFormats[n++] = { VK_FORMAT_A1R5G5B5_UNORM_PACK16, m_colorspace };
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case D3D9Format::R5G6B5: {
|
case D3D9Format::R5G6B5: {
|
||||||
pDstFormats[n++] = { VK_FORMAT_B5G6R5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
pDstFormats[n++] = { VK_FORMAT_B5G6R5_UNORM_PACK16, m_colorspace };
|
||||||
pDstFormats[n++] = { VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
|
pDstFormats[n++] = { VK_FORMAT_R5G6B5_UNORM_PACK16, m_colorspace };
|
||||||
} break;
|
} break;
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
case D3D9Format::A16B16G16R16F: {
|
||||||
}
|
if (m_unlockAdditionalFormats) {
|
||||||
|
pDstFormats[n++] = { VK_FORMAT_R16G16B16A16_SFLOAT, m_colorspace };
|
||||||
|
} else {
|
||||||
uint32_t D3D9SwapChainEx::PickPresentModes(
|
Logger::warn(str::format("D3D9SwapChainEx: Unexpected format: ", Format));
|
||||||
BOOL Vsync,
|
}
|
||||||
VkPresentModeKHR* pDstModes) {
|
break;
|
||||||
uint32_t n = 0;
|
}
|
||||||
|
|
||||||
if (Vsync) {
|
|
||||||
if (m_parent->GetOptions()->tearFree == Tristate::False)
|
|
||||||
pDstModes[n++] = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
|
|
||||||
pDstModes[n++] = VK_PRESENT_MODE_FIFO_KHR;
|
|
||||||
} else {
|
|
||||||
if (m_parent->GetOptions()->tearFree != Tristate::True)
|
|
||||||
pDstModes[n++] = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
|
||||||
pDstModes[n++] = VK_PRESENT_MODE_MAILBOX_KHR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
|
@ -1278,8 +1324,9 @@ namespace dxvk {
|
||||||
|| dstRect.bottom - dstRect.top != LONG(height);
|
|| dstRect.bottom - dstRect.top != LONG(height);
|
||||||
|
|
||||||
bool recreate =
|
bool recreate =
|
||||||
m_swapchainExtent.width != width
|
m_wctx->presenter == nullptr
|
||||||
|| m_swapchainExtent.height != height;
|
|| m_wctx->presenter->info().imageExtent.width != width
|
||||||
|
|| m_wctx->presenter->info().imageExtent.height != height;
|
||||||
|
|
||||||
m_swapchainExtent = { width, height };
|
m_swapchainExtent = { width, height };
|
||||||
m_dstRect = dstRect;
|
m_dstRect = dstRect;
|
||||||
|
@ -1300,7 +1347,98 @@ namespace dxvk {
|
||||||
|
|
||||||
|
|
||||||
std::string D3D9SwapChainEx::GetApiName() {
|
std::string D3D9SwapChainEx::GetApiName() {
|
||||||
return this->GetParent()->IsExtended() ? "D3D9Ex" : "D3D9";
|
if (m_apiName == nullptr) {
|
||||||
|
return this->GetParent()->IsExtended() ? "D3D9Ex" : "D3D9";
|
||||||
|
} else {
|
||||||
|
return m_apiName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D9VkExtSwapchain::D3D9VkExtSwapchain(D3D9SwapChainEx *pSwapChain)
|
||||||
|
: m_swapchain(pSwapChain) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE D3D9VkExtSwapchain::AddRef() {
|
||||||
|
return m_swapchain->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE D3D9VkExtSwapchain::Release() {
|
||||||
|
return m_swapchain->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D9VkExtSwapchain::QueryInterface(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject) {
|
||||||
|
return m_swapchain->QueryInterface(riid, ppvObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL STDMETHODCALLTYPE D3D9VkExtSwapchain::CheckColorSpaceSupport(
|
||||||
|
VkColorSpaceKHR ColorSpace) {
|
||||||
|
return m_swapchain->m_wctx->presenter->supportsColorSpace(ColorSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D9VkExtSwapchain::SetColorSpace(
|
||||||
|
VkColorSpaceKHR ColorSpace) {
|
||||||
|
if (!CheckColorSpaceSupport(ColorSpace))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
m_swapchain->m_dirty |= ColorSpace != m_swapchain->m_colorspace;
|
||||||
|
m_swapchain->m_colorspace = ColorSpace;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D9VkExtSwapchain::SetHDRMetaData(
|
||||||
|
const VkHdrMetadataEXT *pHDRMetadata) {
|
||||||
|
if (!pHDRMetadata)
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
m_swapchain->m_hdrMetadata = *pHDRMetadata;
|
||||||
|
m_swapchain->m_dirtyHdrMetadata = true;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE D3D9VkExtSwapchain::GetCurrentOutputDesc(
|
||||||
|
D3D9VkExtOutputMetadata *pOutputDesc) {
|
||||||
|
HMONITOR monitor = m_swapchain->m_monitor;
|
||||||
|
if (!monitor)
|
||||||
|
monitor = wsi::getDefaultMonitor();
|
||||||
|
// ^ this should be the display we are mostly covering someday.
|
||||||
|
|
||||||
|
wsi::WsiEdidData edidData = wsi::getMonitorEdid(monitor);
|
||||||
|
wsi::WsiDisplayMetadata metadata = {};
|
||||||
|
{
|
||||||
|
std::optional<wsi::WsiDisplayMetadata> r_metadata = std::nullopt;
|
||||||
|
if (!edidData.empty())
|
||||||
|
r_metadata = wsi::parseColorimetryInfo(edidData);
|
||||||
|
|
||||||
|
if (r_metadata)
|
||||||
|
metadata = *r_metadata;
|
||||||
|
else
|
||||||
|
Logger::err("D3D9: Failed to parse display metadata + colorimetry info, using blank.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NormalizeDisplayMetadata(CheckColorSpaceSupport(VK_COLOR_SPACE_HDR10_ST2084_EXT), metadata);
|
||||||
|
|
||||||
|
pOutputDesc->RedPrimary[0] = metadata.redPrimary[0];
|
||||||
|
pOutputDesc->RedPrimary[1] = metadata.redPrimary[1];
|
||||||
|
pOutputDesc->GreenPrimary[0] = metadata.greenPrimary[0];
|
||||||
|
pOutputDesc->GreenPrimary[1] = metadata.greenPrimary[1];
|
||||||
|
pOutputDesc->BluePrimary[0] = metadata.bluePrimary[0];
|
||||||
|
pOutputDesc->BluePrimary[1] = metadata.bluePrimary[1];
|
||||||
|
pOutputDesc->WhitePoint[0] = metadata.whitePoint[0];
|
||||||
|
pOutputDesc->WhitePoint[1] = metadata.whitePoint[1];
|
||||||
|
pOutputDesc->MinLuminance = metadata.minLuminance;
|
||||||
|
pOutputDesc->MaxLuminance = metadata.maxLuminance;
|
||||||
|
pOutputDesc->MaxFullFrameLuminance = metadata.maxFullFrameLuminance;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE D3D9VkExtSwapchain::UnlockAdditionalFormats() {
|
||||||
|
m_swapchain->m_unlockAdditionalFormats = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,51 @@
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
class D3D9Surface;
|
class D3D9Surface;
|
||||||
|
class D3D9SwapChainEx;
|
||||||
|
|
||||||
|
class D3D9VkExtSwapchain final : public ID3D9VkExtSwapchain {
|
||||||
|
public:
|
||||||
|
D3D9VkExtSwapchain(D3D9SwapChainEx *pSwapChain);
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE Release();
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||||
|
REFIID riid,
|
||||||
|
void** ppvObject);
|
||||||
|
|
||||||
|
BOOL STDMETHODCALLTYPE CheckColorSpaceSupport(
|
||||||
|
VkColorSpaceKHR ColorSpace);
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE SetColorSpace(
|
||||||
|
VkColorSpaceKHR ColorSpace);
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE SetHDRMetaData(
|
||||||
|
const VkHdrMetadataEXT *pHDRMetadata);
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE GetCurrentOutputDesc(
|
||||||
|
D3D9VkExtOutputMetadata *pOutputDesc);
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE UnlockAdditionalFormats();
|
||||||
|
|
||||||
|
private:
|
||||||
|
D3D9SwapChainEx *m_swapchain;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D3D9WindowContext {
|
||||||
|
Rc<Presenter> presenter;
|
||||||
|
std::vector<Rc<DxvkImageView>> imageViews;
|
||||||
|
|
||||||
|
uint64_t frameId = D3D9DeviceEx::MaxFrameLatency;
|
||||||
|
Rc<sync::Fence> frameLatencySignal;
|
||||||
|
};
|
||||||
|
|
||||||
using D3D9SwapChainExBase = D3D9DeviceChild<IDirect3DSwapChain9Ex>;
|
using D3D9SwapChainExBase = D3D9DeviceChild<IDirect3DSwapChain9Ex>;
|
||||||
class D3D9SwapChainEx final : public D3D9SwapChainExBase {
|
class D3D9SwapChainEx final : public D3D9SwapChainExBase {
|
||||||
static constexpr uint32_t NumControlPoints = 256;
|
static constexpr uint32_t NumControlPoints = 256;
|
||||||
|
|
||||||
|
friend class D3D9VkExtSwapchain;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
D3D9SwapChainEx(
|
D3D9SwapChainEx(
|
||||||
|
@ -85,6 +126,14 @@ namespace dxvk {
|
||||||
|
|
||||||
void SyncFrameLatency();
|
void SyncFrameLatency();
|
||||||
|
|
||||||
|
bool HasFormatsUnlocked() const { return m_unlockAdditionalFormats; }
|
||||||
|
|
||||||
|
void DestroyBackBuffers();
|
||||||
|
|
||||||
|
void SetApiName(const char* name);
|
||||||
|
|
||||||
|
void UpdateWindowCtx();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum BindingIds : uint32_t {
|
enum BindingIds : uint32_t {
|
||||||
|
@ -99,7 +148,11 @@ namespace dxvk {
|
||||||
Rc<DxvkContext> m_context;
|
Rc<DxvkContext> m_context;
|
||||||
Rc<DxvkSwapchainBlitter> m_blitter;
|
Rc<DxvkSwapchainBlitter> m_blitter;
|
||||||
|
|
||||||
Rc<vk::Presenter> m_presenter;
|
std::unordered_map<
|
||||||
|
HWND,
|
||||||
|
D3D9WindowContext> m_presenters;
|
||||||
|
|
||||||
|
D3D9WindowContext* m_wctx = nullptr;
|
||||||
|
|
||||||
Rc<hud::Hud> m_hud;
|
Rc<hud::Hud> m_hud;
|
||||||
|
|
||||||
|
@ -112,17 +165,10 @@ namespace dxvk {
|
||||||
|
|
||||||
DxvkSubmitStatus m_presentStatus;
|
DxvkSubmitStatus m_presentStatus;
|
||||||
|
|
||||||
std::vector<Rc<DxvkImageView>> m_imageViews;
|
uint32_t m_frameLatencyCap = 0;
|
||||||
|
|
||||||
|
|
||||||
uint64_t m_frameId = D3D9DeviceEx::MaxFrameLatency;
|
|
||||||
uint32_t m_frameLatencyCap = 0;
|
|
||||||
Rc<sync::Fence> m_frameLatencySignal;
|
|
||||||
|
|
||||||
bool m_dirty = true;
|
bool m_dirty = true;
|
||||||
bool m_vsync = true;
|
bool m_dialog = false;
|
||||||
|
|
||||||
bool m_dialog;
|
|
||||||
bool m_lastDialog = false;
|
bool m_lastDialog = false;
|
||||||
|
|
||||||
HWND m_window = nullptr;
|
HWND m_window = nullptr;
|
||||||
|
@ -132,16 +178,25 @@ namespace dxvk {
|
||||||
|
|
||||||
double m_displayRefreshRate = 0.0;
|
double m_displayRefreshRate = 0.0;
|
||||||
|
|
||||||
|
const char* m_apiName = nullptr;
|
||||||
|
|
||||||
bool m_warnedAboutGDIFallback = false;
|
bool m_warnedAboutGDIFallback = false;
|
||||||
|
|
||||||
|
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||||
|
|
||||||
|
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
|
||||||
|
bool m_dirtyHdrMetadata = true;
|
||||||
|
bool m_unlockAdditionalFormats = false;
|
||||||
|
|
||||||
|
D3D9VkExtSwapchain m_swapchainExt;
|
||||||
|
|
||||||
void PresentImage(UINT PresentInterval);
|
void PresentImage(UINT PresentInterval);
|
||||||
|
|
||||||
void SubmitPresent(const vk::PresenterSync& Sync, uint32_t FrameId);
|
void SubmitPresent(const PresenterSync& Sync, uint32_t Repeat);
|
||||||
|
|
||||||
void SynchronizePresent();
|
void SynchronizePresent();
|
||||||
|
|
||||||
void RecreateSwapChain(
|
void RecreateSwapChain();
|
||||||
BOOL Vsync);
|
|
||||||
|
|
||||||
void CreatePresenter();
|
void CreatePresenter();
|
||||||
|
|
||||||
|
@ -149,8 +204,6 @@ namespace dxvk {
|
||||||
|
|
||||||
void CreateRenderTargetViews();
|
void CreateRenderTargetViews();
|
||||||
|
|
||||||
void DestroyBackBuffers();
|
|
||||||
|
|
||||||
HRESULT CreateBackBuffers(
|
HRESULT CreateBackBuffers(
|
||||||
uint32_t NumBackBuffers);
|
uint32_t NumBackBuffers);
|
||||||
|
|
||||||
|
@ -166,10 +219,6 @@ namespace dxvk {
|
||||||
D3D9Format Format,
|
D3D9Format Format,
|
||||||
VkSurfaceFormatKHR* pDstFormats);
|
VkSurfaceFormatKHR* pDstFormats);
|
||||||
|
|
||||||
uint32_t PickPresentModes(
|
|
||||||
BOOL Vsync,
|
|
||||||
VkPresentModeKHR* pDstModes);
|
|
||||||
|
|
||||||
uint32_t PickImageCount(
|
uint32_t PickImageCount(
|
||||||
UINT Preferred);
|
UINT Preferred);
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ namespace dxvk {
|
||||||
uint32_t primitiveId = m_module.opLoad(uint_t, primitiveIdPtr);
|
uint32_t primitiveId = m_module.opLoad(uint_t, primitiveIdPtr);
|
||||||
|
|
||||||
// The size of any given vertex
|
// The size of any given vertex
|
||||||
uint32_t vertexSize = m_module.constu32(pDecl->GetSize() / sizeof(uint32_t));
|
uint32_t vertexSize = m_module.constu32(pDecl->GetSize(0) / sizeof(uint32_t));
|
||||||
|
|
||||||
//The offset of this vertex from the beginning of the buffer
|
//The offset of this vertex from the beginning of the buffer
|
||||||
uint32_t thisVertexOffset = m_module.opIMul(uint_t, vertexSize, primitiveId);
|
uint32_t thisVertexOffset = m_module.opIMul(uint_t, vertexSize, primitiveId);
|
||||||
|
|
|
@ -176,19 +176,19 @@ namespace dxvk {
|
||||||
|
|
||||||
void ConvertRect(RECT rect, VkOffset2D& offset, VkExtent2D& extent);
|
void ConvertRect(RECT rect, VkOffset2D& offset, VkExtent2D& extent);
|
||||||
|
|
||||||
inline float GetDepthBufferRValue(VkFormat Format, int32_t vendorId) {
|
inline float GetDepthBufferRValue(VkFormat Format, int32_t vendorId, bool exact, bool forceUnorm) {
|
||||||
switch (Format) {
|
switch (Format) {
|
||||||
case VK_FORMAT_D16_UNORM_S8_UINT:
|
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||||
case VK_FORMAT_D16_UNORM:
|
case VK_FORMAT_D16_UNORM:
|
||||||
return vendorId == 0x10de ? float(1 << 15) : float(1 << 16);
|
return (vendorId == 0x10de && !exact) ? float(1 << 15) : float(1 << 16);
|
||||||
|
|
||||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||||
return vendorId == 0x10de ? float(1 << 23) : float(1 << 24);
|
return (vendorId == 0x10de && !exact) ? float(1 << 23) : float(1 << 24);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||||
case VK_FORMAT_D32_SFLOAT:
|
case VK_FORMAT_D32_SFLOAT:
|
||||||
return float(1 << 23);
|
return forceUnorm ? float(1 << 24) : float(1 << 23);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,38 +204,6 @@ namespace dxvk {
|
||||||
|
|
||||||
bool IsDepthFormat(D3D9Format Format);
|
bool IsDepthFormat(D3D9Format Format);
|
||||||
|
|
||||||
inline bool operator == (const D3DVIEWPORT9& a, const D3DVIEWPORT9& b) {
|
|
||||||
return a.X == b.X &&
|
|
||||||
a.Y == b.Y &&
|
|
||||||
a.Width == b.Width &&
|
|
||||||
a.Height == b.Height &&
|
|
||||||
a.MinZ == b.MinZ &&
|
|
||||||
a.MaxZ == b.MaxZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator != (const D3DVIEWPORT9& a, const D3DVIEWPORT9& b) {
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator == (const RECT& a, const RECT& b) {
|
|
||||||
return a.left == b.left &&
|
|
||||||
a.right == b.right &&
|
|
||||||
a.top == b.top &&
|
|
||||||
a.bottom == b.bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator != (const RECT& a, const RECT& b) {
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator == (const POINT& a, const POINT& b) {
|
|
||||||
return a.x == b.x && a.y == b.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator != (const POINT& a, const POINT& b) {
|
|
||||||
return !(a == b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool IsPoolManaged(D3DPOOL Pool) {
|
inline bool IsPoolManaged(D3DPOOL Pool) {
|
||||||
return Pool == D3DPOOL_MANAGED || Pool == D3DPOOL_MANAGED_EX;
|
return Pool == D3DPOOL_MANAGED || Pool == D3DPOOL_MANAGED_EX;
|
||||||
}
|
}
|
||||||
|
@ -295,4 +263,47 @@ namespace dxvk {
|
||||||
return D3D9TextureStageStateTypes(Type - 1);
|
return D3D9TextureStageStateTypes(Type - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool operator == (const D3DVIEWPORT9& a, const D3DVIEWPORT9& b) {
|
||||||
|
return a.X == b.X &&
|
||||||
|
a.Y == b.Y &&
|
||||||
|
a.Width == b.Width &&
|
||||||
|
a.Height == b.Height &&
|
||||||
|
a.MinZ == b.MinZ &&
|
||||||
|
a.MaxZ == b.MaxZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator != (const D3DVIEWPORT9& a, const D3DVIEWPORT9& b) {
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator == (const RECT& a, const RECT& b) {
|
||||||
|
return a.left == b.left &&
|
||||||
|
a.right == b.right &&
|
||||||
|
a.top == b.top &&
|
||||||
|
a.bottom == b.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator != (const RECT& a, const RECT& b) {
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator == (const POINT& a, const POINT& b) {
|
||||||
|
return a.x == b.x && a.y == b.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator != (const POINT& a, const POINT& b) {
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator == (const D3DDISPLAYMODEEX& a, const D3DDISPLAYMODEEX& b) {
|
||||||
|
return a.Size == b.Size &&
|
||||||
|
a.Width == b.Width &&
|
||||||
|
a.Height == b.Height &&
|
||||||
|
a.RefreshRate == b.RefreshRate &&
|
||||||
|
a.Format == b.Format &&
|
||||||
|
a.ScanLineOrdering == b.ScanLineOrdering;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -354,8 +354,8 @@ namespace dxvk {
|
||||||
|
|
||||||
void D3D9VertexDecl::Classify() {
|
void D3D9VertexDecl::Classify() {
|
||||||
for (const auto& element : m_elements) {
|
for (const auto& element : m_elements) {
|
||||||
if (element.Stream == 0 && element.Type != D3DDECLTYPE_UNUSED)
|
if (element.Type != D3DDECLTYPE_UNUSED)
|
||||||
m_size = std::max(m_size, element.Offset + GetDecltypeSize(D3DDECLTYPE(element.Type)));
|
m_sizes[element.Stream] = std::max(m_sizes[element.Stream], element.Offset + GetDecltypeSize(D3DDECLTYPE(element.Type)));
|
||||||
|
|
||||||
if (element.Usage == D3DDECLUSAGE_COLOR && element.UsageIndex == 0)
|
if (element.Usage == D3DDECLUSAGE_COLOR && element.UsageIndex == 0)
|
||||||
m_flags.set(D3D9VertexDeclFlag::HasColor0);
|
m_flags.set(D3D9VertexDeclFlag::HasColor0);
|
||||||
|
|
|
@ -50,8 +50,8 @@ namespace dxvk {
|
||||||
return m_elements;
|
return m_elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT GetSize() const {
|
UINT GetSize(UINT Stream) const {
|
||||||
return m_size;
|
return m_sizes[Stream];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestFlag(D3D9VertexDeclFlag flag) const {
|
bool TestFlag(D3D9VertexDeclFlag flag) const {
|
||||||
|
@ -94,8 +94,7 @@ namespace dxvk {
|
||||||
|
|
||||||
uint32_t m_texcoordMask = 0;
|
uint32_t m_texcoordMask = 0;
|
||||||
|
|
||||||
// The size of Stream 0. That's all we care about.
|
std::array<uint32_t, caps::MaxStreams> m_sizes = {};
|
||||||
uint32_t m_size = 0;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,9 @@ d3d9_src = [
|
||||||
'd3d9_annotation.cpp',
|
'd3d9_annotation.cpp',
|
||||||
'd3d9_mem.cpp',
|
'd3d9_mem.cpp',
|
||||||
'd3d9_window.cpp',
|
'd3d9_window.cpp',
|
||||||
'd3d9_interop.cpp'
|
'd3d9_interop.cpp',
|
||||||
|
'd3d9_on_12.cpp',
|
||||||
|
'd3d9_bridge.cpp'
|
||||||
]
|
]
|
||||||
|
|
||||||
d3d9_ld_args = []
|
d3d9_ld_args = []
|
||||||
|
@ -55,17 +57,24 @@ if platform != 'windows'
|
||||||
d3d9_link_depends += files('d3d9.sym')
|
d3d9_link_depends += files('d3d9.sym')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
d3d9_dll = shared_library('d3d9'+dll_ext, d3d9_src, glsl_generator.process(d3d9_shaders), d3d9_res,
|
d3d9_dll = shared_library(dxvk_name_prefix+'d3d9', d3d9_src, glsl_generator.process(d3d9_shaders), d3d9_res,
|
||||||
name_prefix : dxvk_name_prefix,
|
|
||||||
dependencies : [ dxso_dep, dxvk_dep ],
|
dependencies : [ dxso_dep, dxvk_dep ],
|
||||||
include_directories : dxvk_include_path,
|
include_directories : dxvk_include_path,
|
||||||
install : true,
|
install : true,
|
||||||
vs_module_defs : 'd3d9'+def_spec_ext,
|
vs_module_defs : 'd3d9'+def_spec_ext,
|
||||||
link_args : d3d9_ld_args,
|
link_args : d3d9_ld_args,
|
||||||
link_depends : [ d3d9_link_depends ],
|
link_depends : [ d3d9_link_depends ],
|
||||||
|
kwargs : dxvk_so_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
d3d9_dep = declare_dependency(
|
d3d9_dep = declare_dependency(
|
||||||
link_with : [ d3d9_dll ],
|
link_with : [ d3d9_dll ],
|
||||||
include_directories : [ dxvk_include_path ],
|
include_directories : [ dxvk_include_path ],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if platform != 'windows'
|
||||||
|
pkg.generate(d3d9_dll,
|
||||||
|
filebase: dxvk_pkg_prefix + 'd3d9',
|
||||||
|
subdirs: 'dxvk',
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
|
@ -87,9 +87,9 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < ins.dstCount; i++) {
|
for (uint32_t i = 0; i < ins.dstCount; i++) {
|
||||||
if (ins.dst[0].type == DxbcOperandType::IndexableTemp) {
|
if (ins.dst[i].type == DxbcOperandType::IndexableTemp) {
|
||||||
uint32_t index = ins.dst[0].idx[0].offset;
|
uint32_t index = ins.dst[i].idx[0].offset;
|
||||||
m_analysis->xRegMasks[index] |= ins.dst[0].mask;
|
m_analysis->xRegMasks[index] |= ins.dst[i].mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,11 @@ namespace dxvk {
|
||||||
entry.systemValue = static_cast<DxbcSystemValue>(reader.readu32());
|
entry.systemValue = static_cast<DxbcSystemValue>(reader.readu32());
|
||||||
entry.componentType = componentTypes.at(reader.readu32());
|
entry.componentType = componentTypes.at(reader.readu32());
|
||||||
entry.registerId = reader.readu32();
|
entry.registerId = reader.readu32();
|
||||||
entry.componentMask = bit::extract(reader.readu32(), 0, 3);
|
|
||||||
|
uint32_t mask = reader.readu32();
|
||||||
|
|
||||||
|
entry.componentMask = bit::extract(mask, 0, 3);
|
||||||
|
entry.componentUsed = bit::extract(mask, 8, 11);
|
||||||
|
|
||||||
if (hasPrecision)
|
if (hasPrecision)
|
||||||
reader.readu32();
|
reader.readu32();
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace dxvk {
|
||||||
uint32_t semanticIndex;
|
uint32_t semanticIndex;
|
||||||
uint32_t registerId;
|
uint32_t registerId;
|
||||||
DxbcRegMask componentMask;
|
DxbcRegMask componentMask;
|
||||||
|
DxbcRegMask componentUsed;
|
||||||
DxbcScalarType componentType;
|
DxbcScalarType componentType;
|
||||||
DxbcSystemValue systemValue;
|
DxbcSystemValue systemValue;
|
||||||
uint32_t streamId;
|
uint32_t streamId;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -512,6 +512,7 @@ namespace dxvk {
|
||||||
// Entry point description - we'll need to declare
|
// Entry point description - we'll need to declare
|
||||||
// the function ID and all input/output variables.
|
// the function ID and all input/output variables.
|
||||||
uint32_t m_entryPointId = 0;
|
uint32_t m_entryPointId = 0;
|
||||||
|
bool m_hasRawAccessChains = false;
|
||||||
|
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
// Inter-stage shader interface slots. Also
|
// Inter-stage shader interface slots. Also
|
||||||
|
@ -535,6 +536,8 @@ namespace dxvk {
|
||||||
DxbcOpcode m_lastOp = DxbcOpcode::Nop;
|
DxbcOpcode m_lastOp = DxbcOpcode::Nop;
|
||||||
DxbcOpcode m_currOp = DxbcOpcode::Nop;
|
DxbcOpcode m_currOp = DxbcOpcode::Nop;
|
||||||
|
|
||||||
|
VkPrimitiveTopology m_outputTopology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
// Shader interface and metadata declaration methods
|
// Shader interface and metadata declaration methods
|
||||||
void emitDcl(
|
void emitDcl(
|
||||||
|
@ -942,19 +945,6 @@ namespace dxvk {
|
||||||
const DxbcRegister& operand,
|
const DxbcRegister& operand,
|
||||||
const DxbcRegister& address);
|
const DxbcRegister& address);
|
||||||
|
|
||||||
///////////////////////////////
|
|
||||||
// Resource load/store methods
|
|
||||||
DxbcRegisterValue emitRawBufferLoad(
|
|
||||||
const DxbcRegister& operand,
|
|
||||||
DxbcRegisterValue elementIndex,
|
|
||||||
DxbcRegMask writeMask,
|
|
||||||
uint32_t& sparseFeedbackId);
|
|
||||||
|
|
||||||
void emitRawBufferStore(
|
|
||||||
const DxbcRegister& operand,
|
|
||||||
DxbcRegisterValue elementIndex,
|
|
||||||
DxbcRegisterValue value);
|
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
// Resource query methods
|
// Resource query methods
|
||||||
DxbcRegisterValue emitQueryBufferSize(
|
DxbcRegisterValue emitQueryBufferSize(
|
||||||
|
@ -1231,6 +1221,9 @@ namespace dxvk {
|
||||||
uint32_t getUavCoherence(
|
uint32_t getUavCoherence(
|
||||||
uint32_t registerId,
|
uint32_t registerId,
|
||||||
DxbcUavFlags flags);
|
DxbcUavFlags flags);
|
||||||
|
|
||||||
|
bool ignoreInputSystemValue(
|
||||||
|
DxbcSystemValue sv) const;
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
// Type definition methods
|
// Type definition methods
|
||||||
|
|
|
@ -149,6 +149,10 @@ namespace dxvk {
|
||||||
: m_mask((x ? 0x1 : 0) | (y ? 0x2 : 0)
|
: m_mask((x ? 0x1 : 0) | (y ? 0x2 : 0)
|
||||||
| (z ? 0x4 : 0) | (w ? 0x8 : 0)) { }
|
| (z ? 0x4 : 0) | (w ? 0x8 : 0)) { }
|
||||||
|
|
||||||
|
uint32_t raw() const {
|
||||||
|
return m_mask;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator [] (uint32_t id) const {
|
bool operator [] (uint32_t id) const {
|
||||||
return (m_mask >> id) & 1;
|
return (m_mask >> id) & 1;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +200,7 @@ namespace dxvk {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator bool () const {
|
explicit operator bool () const {
|
||||||
return m_mask != 0;
|
return m_mask != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@ namespace dxvk {
|
||||||
|
|
||||||
useDepthClipWorkaround
|
useDepthClipWorkaround
|
||||||
= !devFeatures.extDepthClipEnable.depthClipEnable;
|
= !devFeatures.extDepthClipEnable.depthClipEnable;
|
||||||
useSubgroupOpsForAtomicCounters
|
|
||||||
= (devInfo.vk11.subgroupSupportedStages & VK_SHADER_STAGE_COMPUTE_BIT)
|
|
||||||
&& (devInfo.vk11.subgroupSupportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT);
|
|
||||||
|
|
||||||
VkFormatFeatureFlags2 r32Features
|
VkFormatFeatureFlags2 r32Features
|
||||||
= device->getFormatFeatures(VK_FORMAT_R32_SFLOAT).optimal
|
= device->getFormatFeatures(VK_FORMAT_R32_SFLOAT).optimal
|
||||||
|
@ -27,6 +24,7 @@ namespace dxvk {
|
||||||
& device->getFormatFeatures(VK_FORMAT_R32_SINT).optimal;
|
& device->getFormatFeatures(VK_FORMAT_R32_SINT).optimal;
|
||||||
|
|
||||||
supportsTypedUavLoadR32 = (r32Features & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT);
|
supportsTypedUavLoadR32 = (r32Features & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT);
|
||||||
|
supportsRawAccessChains = device->features().nvRawAccessChains.shaderRawAccessChains;
|
||||||
|
|
||||||
switch (device->config().useRawSsbo) {
|
switch (device->config().useRawSsbo) {
|
||||||
case Tristate::Auto: minSsboAlignment = devInfo.core.properties.limits.minStorageBufferOffsetAlignment; break;
|
case Tristate::Auto: minSsboAlignment = devInfo.core.properties.limits.minStorageBufferOffsetAlignment; break;
|
||||||
|
@ -40,6 +38,7 @@ namespace dxvk {
|
||||||
disableMsaa = options.disableMsaa;
|
disableMsaa = options.disableMsaa;
|
||||||
forceSampleRateShading = options.forceSampleRateShading;
|
forceSampleRateShading = options.forceSampleRateShading;
|
||||||
enableSampleShadingInterlock = device->features().extFragmentShaderInterlock.fragmentShaderSampleInterlock;
|
enableSampleShadingInterlock = device->features().extFragmentShaderInterlock.fragmentShaderSampleInterlock;
|
||||||
|
longMad = options.longMad;
|
||||||
|
|
||||||
// Figure out float control flags to match D3D11 rules
|
// Figure out float control flags to match D3D11 rules
|
||||||
if (options.floatControls) {
|
if (options.floatControls) {
|
||||||
|
|
|
@ -27,9 +27,8 @@ namespace dxvk {
|
||||||
/// on typed UAV loads are required
|
/// on typed UAV loads are required
|
||||||
bool supportsTypedUavLoadR32 = false;
|
bool supportsTypedUavLoadR32 = false;
|
||||||
|
|
||||||
/// Use subgroup operations to reduce the number of
|
/// Determines whether raw access chains are supported
|
||||||
/// atomic operations for append/consume buffers.
|
bool supportsRawAccessChains = false;
|
||||||
bool useSubgroupOpsForAtomicCounters = false;
|
|
||||||
|
|
||||||
/// Clear thread-group shared memory to zero
|
/// Clear thread-group shared memory to zero
|
||||||
bool zeroInitWorkgroupMemory = false;
|
bool zeroInitWorkgroupMemory = false;
|
||||||
|
@ -55,6 +54,9 @@ namespace dxvk {
|
||||||
|
|
||||||
/// Minimum storage buffer alignment
|
/// Minimum storage buffer alignment
|
||||||
VkDeviceSize minSsboAlignment = 0;
|
VkDeviceSize minSsboAlignment = 0;
|
||||||
|
|
||||||
|
/// Should we make our Mads a FFma or do it the long way with an FMul and an FAdd?
|
||||||
|
bool longMad;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -130,7 +130,7 @@ namespace dxvk {
|
||||||
// We can't really reconstruct the version numbers
|
// We can't really reconstruct the version numbers
|
||||||
// returned by Windows drivers from Vulkan data
|
// returned by Windows drivers from Vulkan data
|
||||||
if (SUCCEEDED(hr) && pUMDVersion)
|
if (SUCCEEDED(hr) && pUMDVersion)
|
||||||
pUMDVersion->QuadPart = ~0ull;
|
pUMDVersion->QuadPart = INT64_MAX;
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
Logger::err("DXGI: CheckInterfaceSupport: Unsupported interface");
|
Logger::err("DXGI: CheckInterfaceSupport: Unsupported interface");
|
||||||
|
@ -272,7 +272,8 @@ namespace dxvk {
|
||||||
auto deviceProp = m_adapter->deviceProperties();
|
auto deviceProp = m_adapter->deviceProperties();
|
||||||
auto memoryProp = m_adapter->memoryProperties();
|
auto memoryProp = m_adapter->memoryProperties();
|
||||||
auto vk11 = m_adapter->devicePropertiesExt().vk11;
|
auto vk11 = m_adapter->devicePropertiesExt().vk11;
|
||||||
|
auto vk12 = m_adapter->devicePropertiesExt().vk12;
|
||||||
|
|
||||||
// Custom Vendor / Device ID
|
// Custom Vendor / Device ID
|
||||||
if (options->customVendorId >= 0)
|
if (options->customVendorId >= 0)
|
||||||
deviceProp.vendorID = options->customVendorId;
|
deviceProp.vendorID = options->customVendorId;
|
||||||
|
@ -283,13 +284,36 @@ namespace dxvk {
|
||||||
std::string description = options->customDeviceDesc.empty()
|
std::string description = options->customDeviceDesc.empty()
|
||||||
? std::string(deviceProp.deviceName)
|
? std::string(deviceProp.deviceName)
|
||||||
: options->customDeviceDesc;
|
: options->customDeviceDesc;
|
||||||
|
|
||||||
// XXX nvapi workaround for a lot of Unreal Engine 4 games
|
if (options->customVendorId < 0) {
|
||||||
if (options->customVendorId < 0 && options->customDeviceId < 0
|
uint16_t fallbackVendor = 0xdead;
|
||||||
&& options->nvapiHack && deviceProp.vendorID == uint16_t(DxvkGpuVendor::Nvidia)) {
|
uint16_t fallbackDevice = 0xbeef;
|
||||||
Logger::info("DXGI: NvAPI workaround enabled, reporting AMD GPU");
|
|
||||||
deviceProp.vendorID = uint16_t(DxvkGpuVendor::Amd);
|
if (!options->hideAmdGpu) {
|
||||||
deviceProp.deviceID = 0x67df; /* RX 480 */
|
// AMD RX 6700XT
|
||||||
|
fallbackVendor = uint16_t(DxvkGpuVendor::Amd);
|
||||||
|
fallbackDevice = 0x73df;
|
||||||
|
} else if (!options->hideNvidiaGpu) {
|
||||||
|
// Nvidia RTX 3060
|
||||||
|
fallbackVendor = uint16_t(DxvkGpuVendor::Nvidia);
|
||||||
|
fallbackDevice = 0x2487;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hideNvidiaGpu = vk12.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY
|
||||||
|
? options->hideNvidiaGpu : options->hideNvkGpu;
|
||||||
|
|
||||||
|
bool hideGpu = (deviceProp.vendorID == uint16_t(DxvkGpuVendor::Nvidia) && hideNvidiaGpu)
|
||||||
|
|| (deviceProp.vendorID == uint16_t(DxvkGpuVendor::Amd) && options->hideAmdGpu)
|
||||||
|
|| (deviceProp.vendorID == uint16_t(DxvkGpuVendor::Intel) && options->hideIntelGpu);
|
||||||
|
|
||||||
|
if (hideGpu) {
|
||||||
|
deviceProp.vendorID = fallbackVendor;
|
||||||
|
|
||||||
|
if (options->customDeviceId < 0)
|
||||||
|
deviceProp.deviceID = fallbackDevice;
|
||||||
|
|
||||||
|
Logger::info(str::format("DXGI: Hiding actual GPU, reporting vendor ID 0x", std::hex, deviceProp.vendorID, ", device ID ", deviceProp.deviceID));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert device name
|
// Convert device name
|
||||||
|
|
|
@ -11,6 +11,9 @@ namespace dxvk {
|
||||||
|
|
||||||
Singleton<DxvkInstance> g_dxvkInstance;
|
Singleton<DxvkInstance> g_dxvkInstance;
|
||||||
|
|
||||||
|
std::mutex s_globalHDRStateMutex;
|
||||||
|
DXVK_VK_GLOBAL_HDR_STATE s_globalHDRState{};
|
||||||
|
|
||||||
DxgiVkFactory::DxgiVkFactory(DxgiFactory* pFactory)
|
DxgiVkFactory::DxgiVkFactory(DxgiFactory* pFactory)
|
||||||
: m_factory(pFactory) {
|
: m_factory(pFactory) {
|
||||||
|
|
||||||
|
@ -47,10 +50,36 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DxgiVkFactory::GetGlobalHDRState(
|
||||||
|
DXGI_COLOR_SPACE_TYPE *pOutColorSpace,
|
||||||
|
DXGI_HDR_METADATA_HDR10 *pOutMetadata) {
|
||||||
|
std::unique_lock lock(s_globalHDRStateMutex);
|
||||||
|
if (!s_globalHDRState.Serial)
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
*pOutColorSpace = s_globalHDRState.ColorSpace;
|
||||||
|
*pOutMetadata = s_globalHDRState.Metadata.HDR10;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DxgiVkFactory::SetGlobalHDRState(
|
||||||
|
DXGI_COLOR_SPACE_TYPE ColorSpace,
|
||||||
|
const DXGI_HDR_METADATA_HDR10 *pMetadata) {
|
||||||
|
std::unique_lock lock(s_globalHDRStateMutex);
|
||||||
|
static uint32_t s_GlobalHDRStateSerial = 0;
|
||||||
|
|
||||||
|
s_globalHDRState.Serial = ++s_GlobalHDRStateSerial;
|
||||||
|
s_globalHDRState.ColorSpace = ColorSpace;
|
||||||
|
s_globalHDRState.Metadata.Type = DXGI_HDR_METADATA_TYPE_HDR10;
|
||||||
|
s_globalHDRState.Metadata.HDR10 = *pMetadata;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxgiFactory::DxgiFactory(UINT Flags)
|
DxgiFactory::DxgiFactory(UINT Flags)
|
||||||
: m_instance (g_dxvkInstance.acquire()),
|
: m_instance (g_dxvkInstance.acquire(0)),
|
||||||
m_interop (this),
|
m_interop (this),
|
||||||
m_options (m_instance->config()),
|
m_options (m_instance->config()),
|
||||||
m_monitorInfo (this, m_options),
|
m_monitorInfo (this, m_options),
|
||||||
|
@ -127,7 +156,8 @@ namespace dxvk {
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (riid == __uuidof(IDXGIVkInteropFactory)) {
|
if (riid == __uuidof(IDXGIVkInteropFactory)
|
||||||
|
|| riid == __uuidof(IDXGIVkInteropFactory1)) {
|
||||||
*ppvObject = ref(&m_interop);
|
*ppvObject = ref(&m_interop);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +230,7 @@ namespace dxvk {
|
||||||
descFs.Windowed = pDesc->Windowed;
|
descFs.Windowed = pDesc->Windowed;
|
||||||
|
|
||||||
IDXGISwapChain1* swapChain = nullptr;
|
IDXGISwapChain1* swapChain = nullptr;
|
||||||
HRESULT hr = CreateSwapChainForHwnd(
|
HRESULT hr = CreateSwapChainForHwndBase(
|
||||||
pDevice, pDesc->OutputWindow,
|
pDevice, pDesc->OutputWindow,
|
||||||
&desc, &descFs, nullptr,
|
&desc, &descFs, nullptr,
|
||||||
&swapChain);
|
&swapChain);
|
||||||
|
@ -214,6 +244,19 @@ namespace dxvk {
|
||||||
IUnknown* pDevice,
|
IUnknown* pDevice,
|
||||||
HWND hWnd,
|
HWND hWnd,
|
||||||
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
||||||
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
||||||
|
IDXGIOutput* pRestrictToOutput,
|
||||||
|
IDXGISwapChain1** ppSwapChain) {
|
||||||
|
return CreateSwapChainForHwndBase(
|
||||||
|
pDevice, hWnd,
|
||||||
|
pDesc, pFullscreenDesc, pRestrictToOutput,
|
||||||
|
ppSwapChain);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForHwndBase(
|
||||||
|
IUnknown* pDevice,
|
||||||
|
HWND hWnd,
|
||||||
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
||||||
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
||||||
IDXGIOutput* pRestrictToOutput,
|
IDXGIOutput* pRestrictToOutput,
|
||||||
IDXGISwapChain1** ppSwapChain) {
|
IDXGISwapChain1** ppSwapChain) {
|
||||||
|
@ -407,7 +450,8 @@ namespace dxvk {
|
||||||
if (pWindowHandle == nullptr)
|
if (pWindowHandle == nullptr)
|
||||||
return DXGI_ERROR_INVALID_CALL;
|
return DXGI_ERROR_INVALID_CALL;
|
||||||
|
|
||||||
*pWindowHandle = m_associatedWindow;
|
// Wine tests show that this is always null for whatever reason
|
||||||
|
*pWindowHandle = nullptr;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +466,6 @@ namespace dxvk {
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE DxgiFactory::MakeWindowAssociation(HWND WindowHandle, UINT Flags) {
|
HRESULT STDMETHODCALLTYPE DxgiFactory::MakeWindowAssociation(HWND WindowHandle, UINT Flags) {
|
||||||
Logger::warn("DXGI: MakeWindowAssociation: Ignoring flags");
|
Logger::warn("DXGI: MakeWindowAssociation: Ignoring flags");
|
||||||
m_associatedWindow = WindowHandle;
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,4 +562,9 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DXVK_VK_GLOBAL_HDR_STATE DxgiFactory::GlobalHDRState() {
|
||||||
|
std::unique_lock lock(s_globalHDRStateMutex);
|
||||||
|
return s_globalHDRState;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "dxgi_adapter.h"
|
#include "dxgi_adapter.h"
|
||||||
#include "dxgi_monitor.h"
|
#include "dxgi_monitor.h"
|
||||||
|
@ -12,7 +13,13 @@ namespace dxvk {
|
||||||
|
|
||||||
class DxgiFactory;
|
class DxgiFactory;
|
||||||
|
|
||||||
class DxgiVkFactory : public IDXGIVkInteropFactory {
|
struct DXVK_VK_GLOBAL_HDR_STATE {
|
||||||
|
uint32_t Serial;
|
||||||
|
DXGI_COLOR_SPACE_TYPE ColorSpace;
|
||||||
|
DXGI_VK_HDR_METADATA Metadata;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DxgiVkFactory : public IDXGIVkInteropFactory1 {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -30,6 +37,14 @@ namespace dxvk {
|
||||||
VkInstance* pInstance,
|
VkInstance* pInstance,
|
||||||
PFN_vkGetInstanceProcAddr* ppfnVkGetInstanceProcAddr);
|
PFN_vkGetInstanceProcAddr* ppfnVkGetInstanceProcAddr);
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE GetGlobalHDRState(
|
||||||
|
DXGI_COLOR_SPACE_TYPE *pOutColorSpace,
|
||||||
|
DXGI_HDR_METADATA_HDR10 *pOutMetadata);
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE SetGlobalHDRState(
|
||||||
|
DXGI_COLOR_SPACE_TYPE ColorSpace,
|
||||||
|
const DXGI_HDR_METADATA_HDR10 *pMetadata);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DxgiFactory* m_factory;
|
DxgiFactory* m_factory;
|
||||||
|
@ -173,6 +188,8 @@ namespace dxvk {
|
||||||
DxgiMonitorInfo* GetMonitorInfo() {
|
DxgiMonitorInfo* GetMonitorInfo() {
|
||||||
return &m_monitorInfo;
|
return &m_monitorInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DXVK_VK_GLOBAL_HDR_STATE GlobalHDRState();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -182,9 +199,15 @@ namespace dxvk {
|
||||||
DxgiMonitorInfo m_monitorInfo;
|
DxgiMonitorInfo m_monitorInfo;
|
||||||
UINT m_flags;
|
UINT m_flags;
|
||||||
BOOL m_monitorFallback;
|
BOOL m_monitorFallback;
|
||||||
|
|
||||||
HWND m_associatedWindow = nullptr;
|
|
||||||
|
HRESULT STDMETHODCALLTYPE CreateSwapChainForHwndBase(
|
||||||
|
IUnknown* pDevice,
|
||||||
|
HWND hWnd,
|
||||||
|
const DXGI_SWAP_CHAIN_DESC1* pDesc,
|
||||||
|
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
|
||||||
|
IDXGIOutput* pRestrictToOutput,
|
||||||
|
IDXGISwapChain1** ppSwapChain);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,8 @@
|
||||||
//for some reason we need to specify __declspec(dllexport) for MinGW
|
//for some reason we need to specify __declspec(dllexport) for MinGW
|
||||||
#if defined(__WINE__) || !defined(_WIN32)
|
#if defined(__WINE__) || !defined(_WIN32)
|
||||||
#define DLLEXPORT __attribute__((visibility("default")))
|
#define DLLEXPORT __attribute__((visibility("default")))
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
#define DLLEXPORT
|
|
||||||
#else
|
#else
|
||||||
#define DLLEXPORT __declspec(dllexport)
|
#define DLLEXPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../util/com/com_guid.h"
|
#include "../util/com/com_guid.h"
|
||||||
|
|
|
@ -44,6 +44,15 @@ struct DXGI_VK_HDR_METADATA {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Frame statistics
|
||||||
|
*/
|
||||||
|
struct DXGI_VK_FRAME_STATISTICS {
|
||||||
|
UINT64 PresentCount;
|
||||||
|
UINT64 PresentQPCTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Private DXGI surface factory
|
* \brief Private DXGI surface factory
|
||||||
*/
|
*/
|
||||||
|
@ -118,6 +127,16 @@ IDXGIVkSwapChain : public IUnknown {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MIDL_INTERFACE("785326d4-b77b-4826-ae70-8d08308ee6d1")
|
||||||
|
IDXGIVkSwapChain1 : public IDXGIVkSwapChain {
|
||||||
|
virtual void STDMETHODCALLTYPE GetLastPresentCount(
|
||||||
|
UINT64* pLastPresentCount) = 0;
|
||||||
|
|
||||||
|
virtual void STDMETHODCALLTYPE GetFrameStatistics(
|
||||||
|
DXGI_VK_FRAME_STATISTICS* pFrameStatistics) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Private DXGI presenter factory
|
* \brief Private DXGI presenter factory
|
||||||
*/
|
*/
|
||||||
|
@ -424,29 +443,33 @@ IDXGIVkInteropFactory : public IUnknown {
|
||||||
PFN_vkGetInstanceProcAddr* ppfnVkGetInstanceProcAddr) = 0;
|
PFN_vkGetInstanceProcAddr* ppfnVkGetInstanceProcAddr) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief DXGI factory interface for Vulkan interop
|
||||||
|
*/
|
||||||
|
MIDL_INTERFACE("2a289dbd-2d0a-4a51-89f7-f2adce465cd6")
|
||||||
|
IDXGIVkInteropFactory1 : public IDXGIVkInteropFactory {
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetGlobalHDRState(
|
||||||
|
DXGI_COLOR_SPACE_TYPE *pOutColorSpace,
|
||||||
|
DXGI_HDR_METADATA_HDR10 *ppOutMetadata) = 0;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
virtual HRESULT STDMETHODCALLTYPE SetGlobalHDRState(
|
||||||
struct __declspec(uuid("907bf281-ea3c-43b4-a8e4-9f231107b4ff")) IDXGIDXVKAdapter;
|
DXGI_COLOR_SPACE_TYPE ColorSpace,
|
||||||
struct __declspec(uuid("92a5d77b-b6e1-420a-b260-fdd701272827")) IDXGIDXVKDevice;
|
const DXGI_HDR_METADATA_HDR10 *pMetadata) = 0;
|
||||||
struct __declspec(uuid("c06a236f-5be3-448a-8943-89c611c0c2c1")) IDXGIVkMonitorInfo;
|
};
|
||||||
struct __declspec(uuid("4c5e1b0d-b0c8-4131-bfd8-9b2476f7f408")) IDXGIVkInteropFactory;
|
|
||||||
struct __declspec(uuid("3a6d8f2c-b0e8-4ab4-b4dc-4fd24891bfa5")) IDXGIVkInteropAdapter;
|
|
||||||
struct __declspec(uuid("e2ef5fa5-dc21-4af7-90c4-f67ef6a09323")) IDXGIVkInteropDevice;
|
#ifndef _MSC_VER
|
||||||
struct __declspec(uuid("e2ef5fa5-dc21-4af7-90c4-f67ef6a09324")) IDXGIVkInteropDevice1;
|
|
||||||
struct __declspec(uuid("5546cf8c-77e7-4341-b05d-8d4d5000e77d")) IDXGIVkInteropSurface;
|
|
||||||
struct __declspec(uuid("1e7895a1-1bc3-4f9c-a670-290a4bc9581a")) IDXGIVkSurfaceFactory;
|
|
||||||
struct __declspec(uuid("e4a9059e-b569-46ab-8de7-501bd2bc7f7a")) IDXGIVkSwapChain;
|
|
||||||
struct __declspec(uuid("e7d6c3ca-23a0-4e08-9f2f-ea5231df6633")) IDXGIVkSwapChainFactory;
|
|
||||||
#else
|
|
||||||
__CRT_UUID_DECL(IDXGIDXVKAdapter, 0x907bf281,0xea3c,0x43b4,0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff);
|
__CRT_UUID_DECL(IDXGIDXVKAdapter, 0x907bf281,0xea3c,0x43b4,0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff);
|
||||||
__CRT_UUID_DECL(IDXGIDXVKDevice, 0x92a5d77b,0xb6e1,0x420a,0xb2,0x60,0xfd,0xf7,0x01,0x27,0x28,0x27);
|
__CRT_UUID_DECL(IDXGIDXVKDevice, 0x92a5d77b,0xb6e1,0x420a,0xb2,0x60,0xfd,0xf7,0x01,0x27,0x28,0x27);
|
||||||
__CRT_UUID_DECL(IDXGIVkMonitorInfo, 0xc06a236f,0x5be3,0x448a,0x89,0x43,0x89,0xc6,0x11,0xc0,0xc2,0xc1);
|
__CRT_UUID_DECL(IDXGIVkMonitorInfo, 0xc06a236f,0x5be3,0x448a,0x89,0x43,0x89,0xc6,0x11,0xc0,0xc2,0xc1);
|
||||||
__CRT_UUID_DECL(IDXGIVkInteropFactory, 0x4c5e1b0d,0xb0c8,0x4131,0xbf,0xd8,0x9b,0x24,0x76,0xf7,0xf4,0x08);
|
__CRT_UUID_DECL(IDXGIVkInteropFactory, 0x4c5e1b0d,0xb0c8,0x4131,0xbf,0xd8,0x9b,0x24,0x76,0xf7,0xf4,0x08);
|
||||||
|
__CRT_UUID_DECL(IDXGIVkInteropFactory1, 0x2a289dbd,0x2d0a,0x4a51,0x89,0xf7,0xf2,0xad,0xce,0x46,0x5c,0xd6);
|
||||||
__CRT_UUID_DECL(IDXGIVkInteropAdapter, 0x3a6d8f2c,0xb0e8,0x4ab4,0xb4,0xdc,0x4f,0xd2,0x48,0x91,0xbf,0xa5);
|
__CRT_UUID_DECL(IDXGIVkInteropAdapter, 0x3a6d8f2c,0xb0e8,0x4ab4,0xb4,0xdc,0x4f,0xd2,0x48,0x91,0xbf,0xa5);
|
||||||
__CRT_UUID_DECL(IDXGIVkInteropDevice, 0xe2ef5fa5,0xdc21,0x4af7,0x90,0xc4,0xf6,0x7e,0xf6,0xa0,0x93,0x23);
|
__CRT_UUID_DECL(IDXGIVkInteropDevice, 0xe2ef5fa5,0xdc21,0x4af7,0x90,0xc4,0xf6,0x7e,0xf6,0xa0,0x93,0x23);
|
||||||
__CRT_UUID_DECL(IDXGIVkInteropDevice1, 0xe2ef5fa5,0xdc21,0x4af7,0x90,0xc4,0xf6,0x7e,0xf6,0xa0,0x93,0x24);
|
__CRT_UUID_DECL(IDXGIVkInteropDevice1, 0xe2ef5fa5,0xdc21,0x4af7,0x90,0xc4,0xf6,0x7e,0xf6,0xa0,0x93,0x24);
|
||||||
__CRT_UUID_DECL(IDXGIVkInteropSurface, 0x5546cf8c,0x77e7,0x4341,0xb0,0x5d,0x8d,0x4d,0x50,0x00,0xe7,0x7d);
|
__CRT_UUID_DECL(IDXGIVkInteropSurface, 0x5546cf8c,0x77e7,0x4341,0xb0,0x5d,0x8d,0x4d,0x50,0x00,0xe7,0x7d);
|
||||||
__CRT_UUID_DECL(IDXGIVkSurfaceFactory, 0x1e7895a1,0x1bc3,0x4f9c,0xa6,0x70,0x29,0x0a,0x4b,0xc9,0x58,0x1a);
|
__CRT_UUID_DECL(IDXGIVkSurfaceFactory, 0x1e7895a1,0x1bc3,0x4f9c,0xa6,0x70,0x29,0x0a,0x4b,0xc9,0x58,0x1a);
|
||||||
__CRT_UUID_DECL(IDXGIVkSwapChain, 0xe4a9059e,0xb569,0x46ab,0x8d,0xe7,0x50,0x1b,0xd2,0xbc,0x7f,0x7a);
|
__CRT_UUID_DECL(IDXGIVkSwapChain, 0xe4a9059e,0xb569,0x46ab,0x8d,0xe7,0x50,0x1b,0xd2,0xbc,0x7f,0x7a);
|
||||||
|
__CRT_UUID_DECL(IDXGIVkSwapChain1, 0x785326d4,0xb77b,0x4826,0xae,0x70,0x8d,0x08,0x30,0x8e,0xe6,0xd1);
|
||||||
__CRT_UUID_DECL(IDXGIVkSwapChainFactory, 0xe7d6c3ca,0x23a0,0x4e08,0x9f,0x2f,0xea,0x52,0x31,0xdf,0x66,0x33);
|
__CRT_UUID_DECL(IDXGIVkSwapChainFactory, 0xe7d6c3ca,0x23a0,0x4e08,0x9f,0x2f,0xea,0x52,0x31,0xdf,0x66,0x33);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -107,7 +107,11 @@ namespace dxvk {
|
||||||
return 32;
|
return 32;
|
||||||
|
|
||||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||||
return 64;
|
// Floating point output doesn't really make sense.
|
||||||
|
// This seemingly works on Windows, and based on FindClosestMode etc documentaton,
|
||||||
|
// this seems required to work for any format that scanout it supported for.
|
||||||
|
// Treat as 10-bit -> 32.
|
||||||
|
return 32;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Logger::warn(str::format(
|
Logger::warn(str::format(
|
||||||
|
|
|
@ -26,6 +26,26 @@ namespace dxvk {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* First generation XeSS causes crash on proton for Intel due to missing
|
||||||
|
* Intel interface. Avoid crash by pretending to be non-Intel if the
|
||||||
|
* libxess.dll module is loaded by an application.
|
||||||
|
*/
|
||||||
|
static bool isXessUsed() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (GetModuleHandleA("libxess") != nullptr ||
|
||||||
|
GetModuleHandleA("libxess_dx11") != nullptr)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isNvapiEnabled() {
|
||||||
|
return env::getEnvVar("DXVK_ENABLE_NVAPI") == "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool isHDRDisallowed() {
|
static bool isHDRDisallowed() {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -53,7 +73,7 @@ namespace dxvk {
|
||||||
bool isUE4 = exeName.find("-Win64-Shipping") != std::string::npos;
|
bool isUE4 = exeName.find("-Win64-Shipping") != std::string::npos;
|
||||||
bool hasD3D12 = GetModuleHandleA("d3d12") != nullptr;
|
bool hasD3D12 = GetModuleHandleA("d3d12") != nullptr;
|
||||||
|
|
||||||
if (isUE4 && !hasD3D12)
|
if (isUE4 && !hasD3D12 && !isNvapiEnabled())
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
@ -73,11 +93,28 @@ namespace dxvk {
|
||||||
this->maxDeviceMemory = VkDeviceSize(config.getOption<int32_t>("dxgi.maxDeviceMemory", 0)) << 20;
|
this->maxDeviceMemory = VkDeviceSize(config.getOption<int32_t>("dxgi.maxDeviceMemory", 0)) << 20;
|
||||||
this->maxSharedMemory = VkDeviceSize(config.getOption<int32_t>("dxgi.maxSharedMemory", 0)) << 20;
|
this->maxSharedMemory = VkDeviceSize(config.getOption<int32_t>("dxgi.maxSharedMemory", 0)) << 20;
|
||||||
|
|
||||||
// Force nvapiHack to be disabled if NvAPI is enabled in environment
|
this->syncInterval = config.getOption<int32_t>("dxgi.syncInterval", -1);
|
||||||
if (env::getEnvVar("DXVK_ENABLE_NVAPI") == "1")
|
|
||||||
this->nvapiHack = false;
|
// Expose Nvidia GPUs properly if NvAPI is enabled in environment
|
||||||
else
|
this->hideNvidiaGpu = !isNvapiEnabled();
|
||||||
this->nvapiHack = config.getOption<bool>("dxgi.nvapiHack", true);
|
applyTristate(this->hideNvidiaGpu, config.getOption<Tristate>("dxgi.hideNvidiaGpu", Tristate::Auto));
|
||||||
|
|
||||||
|
// Treat NVK adapters the same as Nvidia cards on the proprietary by
|
||||||
|
// default, but provide an override in case something isn't working.
|
||||||
|
this->hideNvkGpu = this->hideNvidiaGpu;
|
||||||
|
applyTristate(this->hideNvkGpu, config.getOption<Tristate>("dxgi.hideNvkGpu", Tristate::Auto));
|
||||||
|
|
||||||
|
// Expose AMD and Intel GPU by default, unless a config override is active.
|
||||||
|
// Implement as a tristate so that we have the option to introduce similar
|
||||||
|
// logic to Nvidia later, if necessary.
|
||||||
|
this->hideAmdGpu = config.getOption<Tristate>("dxgi.hideAmdGpu", Tristate::Auto) == Tristate::True;
|
||||||
|
this->hideIntelGpu = config.getOption<Tristate>("dxgi.hideIntelGpu", Tristate::Auto) == Tristate::True;
|
||||||
|
|
||||||
|
/* Force vendor ID to non-Intel ID when XeSS is in use */
|
||||||
|
if (isXessUsed()) {
|
||||||
|
Logger::info(str::format("Detected XeSS usage, hiding Intel GPU Vendor"));
|
||||||
|
this->hideIntelGpu = true;
|
||||||
|
}
|
||||||
|
|
||||||
this->enableHDR = config.getOption<bool>("dxgi.enableHDR", env::getEnvVar("DXVK_HDR") == "1");
|
this->enableHDR = config.getOption<bool>("dxgi.enableHDR", env::getEnvVar("DXVK_HDR") == "1");
|
||||||
if (this->enableHDR && isHDRDisallowed()) {
|
if (this->enableHDR && isHDRDisallowed()) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue