Compare commits

..

2 Commits

Author SHA1 Message Date
Joshua Ashton 07e22a13d0 vkd3d: Fix potential lack of null termination on cache blob versions
The Git sha's are 7 characters long, but this may change if we tag a release that has a name.
Ensure this is null terminated to shut up a compiler warning.

Signed-off-by: Joshua Ashton <joshua@froggi.es>
2020-10-04 18:28:42 +01:00
Joshua Ashton 31edccd237 vkd3d: Migrate version to a header
Signed-off-by: Joshua Ashton <joshua@froggi.es>
2020-10-04 18:13:31 +01:00
177 changed files with 56683 additions and 111986 deletions

View File

@ -1,31 +0,0 @@
name: Artifacts (Package)
on: [push, pull_request, workflow_dispatch]
jobs:
build-artifacts:
runs-on: ubuntu-20.04
steps:
- name: Checkout code
id: checkout-code
uses: actions/checkout@v2
with:
submodules: recursive
- name: Build release
id: build-release
uses: Joshua-Ashton/arch-mingw-github-action@v8
with:
command: |
export VERSION_NAME="${GITHUB_REF##*/}-${GITHUB_SHA##*/}"
./package-release.sh ${VERSION_NAME} build --no-package
echo "VERSION_NAME=${VERSION_NAME}" >> $GITHUB_ENV
- name: Upload artifacts
id: upload-artifacts
uses: actions/upload-artifact@v2
with:
name: vkd3d-proton-${{ env.VERSION_NAME }}
path: build/vkd3d-proton-${{ env.VERSION_NAME }}
if-no-files-found: error

View File

@ -1,75 +0,0 @@
name: Test Builds on Linux
on: [push, pull_request, workflow_dispatch]
jobs:
build-set-linux:
runs-on: ubuntu-20.04
steps:
- name: Checkout code
id: checkout-code
uses: actions/checkout@v2
with:
submodules: recursive
- name: Setup problem matcher
uses: Joshua-Ashton/gcc-problem-matcher@v1
- name: Build MinGW x86
id: build-mingw-x86
uses: Joshua-Ashton/arch-mingw-github-action@v8
with:
command: |
meson -Denable_tests=True -Denable_extras=True --cross-file=build-win32.txt --buildtype release build-mingw-x86
ninja -C build-mingw-x86
- name: Build MinGW x64
id: build-mingw-x64
uses: Joshua-Ashton/arch-mingw-github-action@v8
with:
command: |
meson -Denable_tests=True -Denable_extras=True --cross-file=build-win64.txt --buildtype release build-mingw-x64
ninja -C build-mingw-x64
- name: Build Native GCC x86
id: build-native-gcc-x86
uses: Joshua-Ashton/arch-mingw-github-action@v8
with:
command: |
export CC="gcc -m32"
export CXX="g++ -m32"
export PKG_CONFIG_PATH="/usr/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/pkgconfig"
meson -Denable_tests=True -Denable_extras=True --buildtype release build-native-gcc-x86
ninja -C build-native-gcc-x86
- name: Build Native GCC x64
id: build-native-gcc-x64
uses: Joshua-Ashton/arch-mingw-github-action@v8
with:
command: |
export CC="gcc"
export CXX="g++"
meson -Denable_tests=True -Denable_extras=True --buildtype release build-native-gcc-x64
ninja -C build-native-gcc-x64
- name: Build Native Clang x86
id: build-native-clang-x86
uses: Joshua-Ashton/arch-mingw-github-action@v8
with:
command: |
export CC="clang -m32"
export CXX="clang++ -m32"
export PKG_CONFIG_PATH="/usr/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/pkgconfig"
meson -Denable_tests=True -Denable_extras=True --buildtype release build-native-clang-x86
ninja -C build-native-clang-x86
- name: Build Native Clang x64
id: build-native-clang-x64
uses: Joshua-Ashton/arch-mingw-github-action@v8
with:
command: |
export CC="clang"
export CXX="clang++"
meson -Denable_tests=True -Denable_extras=True --buildtype release build-native-clang-x64
ninja -C build-native-clang-x64

View File

@ -1,53 +0,0 @@
name: Test Builds on Windows
on: [push, pull_request, workflow_dispatch]
jobs:
build-set-windows:
runs-on: windows-2022
steps:
- name: Checkout code
id: checkout-code
uses: actions/checkout@v2
with:
submodules: recursive
- name: Setup widl and glslangValidator
shell: pwsh
run: |
choco install strawberryperl vulkan-sdk -y
Write-Output "C:\Strawberry\c\bin" | Out-File -FilePath "${Env:GITHUB_PATH}" -Append
Write-Output "$([System.Environment]::GetEnvironmentVariable('VULKAN_SDK', 'Machine'))\Bin" `
| Out-File -FilePath "${Env:GITHUB_PATH}" -Append
- name: Setup Meson
shell: pwsh
run: pip install meson
- name: Find Visual Studio
shell: pwsh
run: |
$installationPath = Get-VSSetupInstance `
| Select-VSSetupInstance -Require Microsoft.VisualStudio.Workload.NativeDesktop -Latest `
| Select-Object -ExpandProperty InstallationPath
Write-Output "VSDEVCMD=${installationPath}\Common7\Tools\VsDevCmd.bat" `
| Out-File -FilePath "${Env:GITHUB_ENV}" -Append
- name: Build MSVC x86
shell: pwsh
run: |
& "${Env:COMSPEC}" /s /c "`"${Env:VSDEVCMD}`" -arch=x86 -host_arch=x64 -no_logo && set" `
| % { , ($_ -Split '=', 2) } `
| % { [System.Environment]::SetEnvironmentVariable($_[0], $_[1]) }
meson -Denable_tests=True -Denable_extras=True --buildtype release --backend vs2022 build-msvc-x86
msbuild -m build-msvc-x86/vkd3d-proton.sln
- name: Build MSVC x64
shell: pwsh
run: |
& "${Env:COMSPEC}" /s /c "`"${Env:VSDEVCMD}`" -arch=x64 -host_arch=x64 -no_logo && set" `
| % { , ($_ -Split '=', 2) } `
| % { [System.Environment]::SetEnvironmentVariable($_[0], $_[1]) }
meson -Denable_tests=True -Denable_extras=True --buildtype release --backend vs2022 build-msvc-x64
msbuild -m build-msvc-x64/vkd3d-proton.sln

31
.gitignore vendored
View File

@ -1,5 +1,28 @@
build
build.*
vkd3d-proton-*.tar.zst
vkd3d-proton-*/
aclocal.m4
autom4te.cache
config.log
config.status
configure
libtool
Makefile
Makefile.in
test-suite.log
vkd3d-compiler
vkd3d-*.tar.xz
*.exe
*.la
*.lo
*.log
*.o
*.pc
*.trs
*~
.deps
.dirstamp
.libs
build
build.native
build.cross

9
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,9 @@
vkd3d:
variables:
GIT_SUBMODULE_STRATEGY: recursive
script:
- ./package-release.sh release build --no-package
artifacts:
name: "vkd3d-${CI_COMMIT_REF_NAME}.${CI_COMMIT_SHA}"
paths:
- build/vkd3d-release

View File

@ -1,4 +0,0 @@
Conor McCarthy <cmccarthy@codeweavers.com>
Ivan Fedorov <ifedorov@nvidia.com>
James Beddek <telans@protonmail.com>
Roshan Chaudhari <rochaudhari@nvidia.com>

85
ANNOUNCE Normal file
View File

@ -0,0 +1,85 @@
The Wine team is proud to announce that release 1.1 of vkd3d, the
Direct3D 12 to Vulkan translation library, is now available.
This release contains improvements that are listed in the release notes below.
The main highlights are:
- Initial support for placed resources.
- MoltenVK support.
- Support for geometry shaders.
The source is available from the following location:
https://dl.winehq.org/vkd3d/source/vkd3d-1.1.tar.xz
The current source can also be pulled directly from the git repository:
https://source.winehq.org/git/vkd3d.git/
Vkd3d is available thanks to the work of multiple people. See the file AUTHORS
for the complete list.
----------------------------------------------------------------
What's new in vkd3d 1.1
=======================
*** libvkd3d
- Initial support for memory heaps and placed resources.
- Improved support for resource views.
- ClearUnorderedAccessViewUint() is implemented for textures.
- Blend factor is implemented.
- Performance improvements.
- A new interface is available for enabling additional Vulkan instance
extensions.
- A new public function is available for mapping VkFormats to DXGI_FORMATs.
- Support for more DXGI formats.
- Various bug fixes.
*** libvkd3d-shader
- Support for geometry shaders.
- Pretty printing is implemented for shader code extracted from DXBC.
- Clip and cull distances are supported.
- Support for more shader instructions:
- round_ne,
- sincos,
- ineg,
- continue,
- continuec,
- gather4_po,
- gather4_po_c,
- gather4_c.
- Texel offsets are supported.
- Various shader translation fixes.
*** libvkd3d-utils
- Vulkan WSI extensions are detected at runtime.
*** build
- Demos are not built by default.
- libxcb is now an optional dependency required only for demos.
- MoltenVK is supported.

30
AUTHORS
View File

@ -1,34 +1,4 @@
Alexander Gabello
Alexandre Julliard
Andrew Eikum
Arkadiusz Hiler
Biswapriyo Nath
Chip Davis
Conor McCarthy
Danylo Piliaiev
David Gow
David McCloskey
Derek Lesho
Fabian Bornschein
Georg Lehmann
Hans-Kristian Arntzen
Henri Verbeet
Ivan Fedorov
Jactry Zeng
James Beddek
Jens Peters
Joshua Ashton
Józef Kucia
Juuso Alasuutari
Krzysztof Bogacki
Paul Gofman
Philip Rebohle
Rémi Bernon
Robin Kertels
Rodrigo Locatti
Roshan Chaudhari
Samuel Pitoiset
Sveinar Søpler
Sven Hesse
Thomas Crider
Zhiyi Zhang

View File

@ -1,388 +0,0 @@
# Change Log
## 2.6
It has been a long while since 2.5, and this release rolls up a lot of fixes, features and optimizations.
### Fixes
- Fix black screen rendering bug in Horizon Zero Dawn after latest game updates.
- Fix crashes on startup in Final Fantasy VII: Remake and Warframe.
- Fix crashes in Guardians of the Galaxy when interacting with certain game objects.
- Fix hang on game shutdown in Elden Ring.
- Fix broken geometry rendering in Age of Empires: IV.
### Optimization
- Improve generated shader code for vectorized load-store operations in DXIL.
- Greatly reduce CPU overhead for descriptor copy operations,
which is a key contributor to CPU overhead in D3D12.
### Features
#### Pipeline library rewrite
Support D3D12 pipeline libraries better where we can now also cache
generated SPIR-V from DXBC/DXIL.
Massively reduces subsequent load times in Monster Hunter: Rise,
and helps other titles like Guardian of the Galaxy and Elden Ring.
Also lays the groundwork for internal driver caches down the line for games which do not use this API.
Also, deduplicates binary blobs for reduced disk size requirements.
#### Shader models
Shader model 6.6 is now fully implemented. This includes support for:
- ResourceDescriptorHeap[] direct access
- 64-bit atomics
- IsHelperLane()
- Compute shader derivatives
- WaveSize attribute
- Packed math intrinsics
#### Minor features
- Handle API feature MinResourceLODClamp correctly if `VK_EXT_image_view_min_lod` is supported.
- Expose CastFullyTypedFormat feature.
- Expose some advanced shader features on Intel related to UAV formats (`VK_KHR_format_feature_flags2`).
- Support COLOR -> STENCIL copies.
### Workarounds
- Workaround DEATHLOOP not emitting synchronization commands correctly. Fixes menu flicker on RADV.
- Workaround quirky API usage in Elden Ring. Removes many kinds of stutter and chug when traversing the scenery.
- Workaround certain environments failing to create Vulkan device if some `VK_NVX_*` extensions are enabled.
- Workaround glitched foliage rendering in Horizon Zero Dawn after latest game updates.
- Workaround some questionable UE4 shaders causing glitched rendering on RADV.
### Note on future Vulkan driver requirements
2.6 is expected to be the last vkd3d-proton release before we require some newer Vulkan extensions.
`VK_KHR_dynamic_rendering` and `VK_EXT_extended_dynamic_state`
(and likely `dynamic_state_2` as well) will be required.
`VK_KHR_dynamic_rendering` in particular requires up-to-date drivers and the legacy render pass path
will be abandoned in favor of it. Supporting both paths at the same time is not practical.
Moving to `VK_KHR_dynamic_rendering` allows us to fix some critical flaws with the legacy API
which caused potential shader compilation stutters and extra CPU overhead.
## 2.5
This is a release with a little bit of everything!
### Features
#### DXR progress
DXR has seen significant work in the background.
- DXR 1.1 is now experimentally exposed. It can be enabled with `VKD3D_CONFIG=dxr11`.
Note that DXR 1.1 cannot be fully implemented in `VK_KHR_ray_tracing`'s current form, in particular
DispatchRays() indirect is not compatible yet,
although we have not observed a game which requires this API feature.
- DXR 1.1 inline raytracing support is fully implemented.
- DXR 1.0 support is more or less feature complete.
Some weird edge cases remain, but will likely not be implemented unless required by a game.
`VKD3D_CONFIG=dxr` will eventually be dropped when it matures.
Some new DXR games are starting to come alive, especially with DXR 1.1 enabled,
but there are significant bugs as well that we currently cannot easily debug.
Some experimental results on NVIDIA:
- **Control** - already worked
- **DEATHLOOP** - appears to work correctly
- **Cyberpunk 2077** - DXR can be enabled, but GPU timeouts
- **World of Warcraft** - according to a user, it works, but we have not confirmed ourselves
- **Metro Exodus: Enhanced Edition** -
gets ingame and appears to work? Not sure if it looks correct.
Heavy CPU stutter for some reason ...
- **Metro Exodus** (original release) - GPU timeouts when enabling DXR
- **Resident Evil: Village** - Appears to work, but the visual difference is subtle.
It's worth experimenting with these and others.
DXR is incredibly complicated, so expect bugs.
From here, DXR support is mostly a case of stamping out issues one by one.
#### NVIDIA DLSS
NVIDIA contributed integration APIs in vkd3d-proton which enables DLSS support in D3D12 titles in Proton.
See Proton documentation for how to enable NvAPI support.
#### Shader models
A fair bit of work went into DXIL translation support to catch up with native drivers.
- Shader model 6.5 is exposed.
Shader model 6.6 should be straight forward once that becomes relevant.
- Shader model 6.4 implementation takes advantage of `VK_KHR_shader_integer_dot_product` when supported.
- Proper fallback for FP16 math on GPUs which do not expose native FP16 support (Polaris, Pascal).
Notably fixes AMD FSR shaders in Resident Evil: Village (and others).
- Shader model 6.1 SV_Barycentric support implemented (NVIDIA only for now).
- Support shader model 6.2 FP32 denorm control.
### Performance
Resizable BAR can improve GPU performance about 10-15% in the best case, depends a lot on the game.
Horizon Zero Dawn and Death Stranding in particular improve massively with this change.
By default, vkd3d-proton will now take advantage of PCI-e BAR memory types through heuristics
as D3D12 does not expose direct support for resizable BAR, and native D3D12 drivers are known to use heuristics as well.
Without resizable BAR enabled in BIOS/vBIOS, we only get 256 MiB which can help performance,
but many games will improve performance even more
when we are allowed to use more than that.
There is an upper limit for how much VRAM is dedicated to this purpose.
We also added `VKD3D_CONFIG=no_upload_hvv` to disable all uses of PCI-e BAR memory.
Other performance improvements:
- Avoid redundant descriptor update work in certain scenarios (NVIDIA contribution).
- Minor tweaks here and there to reduce CPU overhead.
### Fixes and workarounds
- Fix behavior for swap chain presentation latency HANDLE. Fixes spurious deadlocks in some cases.
- Fix many issues related to depth-stencil handling, which fixed various issues in DEATHLOOP, F1 2021, WRC 10.
- Fix DIRT 5 rendering issues and crashes. Should be fully playable now.
- Fix some Diablo II Resurrected rendering issues.
- Workaround shader bugs in Psychonauts 2.
- Workaround some Unreal Engine 4 shader bugs which multiple titles trigger.
- Fix some stability issues when VRAM is exhausted on NVIDIA.
- Fix CPU crash in boot-up sequence of Far Cry 6 (game is still kinda buggy though, but gets in-game).
- Fix various bugs with host visible images. Fixes DEATHLOOP.
- Fix various DXIL conversion bugs.
- Add Invariant geometry workarounds for specific games which require it.
- Fix how d3d12.dll exports symbols to be more in line with MSVC.
- Fix some edge cases in bitfield instructions.
- Work around extreme CPU memory bloat on the specific NVIDIA driver versions which had this bug.
- Fix regression in Evil Genius 2: World Domination.
- Fix crashes in Hitman 3.
- Fix terrain rendering in Anno 1800.
- Various correctness and crash fixes.
## 2.4
This is a release which focuses on performance and bug-fixes.
### Performance
- Improve swapchain latency and frame pacing by up to one frame.
- Optimize lookup of format info.
- Avoid potential pipeline compilation stutter in certain scenarios.
- Rewrite how we handle image layouts for color and depth-stencil targets.
Allows us to remove a lot of dumb
barriers giving significant GPU-bound performance improvements.
~15%-20% GPU bound uplift in Horizon Zero Dawn,
~10% in Death Stranding,
and 5%-10% improvements in many other titles.
### Features
- Enable support for sparse 3D textures (tiled resources tier 3).
### Bug fixes and workarounds
- Various bug fixes in DXIL.
- Fix weird bug where sun would pop through walls in RE: Village.
- Workaround game bug in Cyberpunk 2077 where certain locales would render a black screen.
- Fix various bugs (in benchmark and in vkd3d-proton) allowing GravityMark to run.
- Improve robustness against certain app bugs related to NULL descriptors.
- Fix bug with constant FP64 vector handling in DXBC.
- Fix bug where Cyberpunk 2077 inventory screen could spuriously hang GPU on RADV.
- Add workaround for Necromunda: Hired Gun where character models would render random garbage on RADV.
- Fix bug in Necromunda: Hired Gun causing random screen flicker.
- Fix windowed mode tracking when leaving fullscreen. Fix Alt-Tab handling in Horizon Zero Dawn.
- Temporary workaround for SRV ResourceMinLODClamp. Fix black ground rendering in DIRT 5.
The overbright HDR rendering in DIRT 5 sadly persists however :(
- Implement fallback maximum swapchain latency correctly.
### Development features
Various features which are useful for developers were added to aid debugging.
- Descriptor QA can instrument shaders in runtime for GPU-assisted validation.
Performance is good enough (> 40 FPS) that games are actually playable in this mode.
See README for details.
- Allow forcing off CONCURRENT queue, and using EXCLUSIVE queue.
Not valid, but can be useful as a speed hack on Polaris when `single_queue` is not an option
and for testing driver behavior differences.
## 2.3.1
This is a minor bugfix release to address some issues solved shortly after the last release.
### Fixes
- Improved support for older Wine and Vulkan Loader versions.
- Fix blocky shadows in Horizon Zero Dawn.
- Fix the install script failing on Wine installs not built with upstream vkd3d.
- Fix minor dxil translation issues.
## 2.3
This release adds support for more D3D12 features and greatly improves GPU bound performance
in many scenarios.
### Features
#### Early DXR 1.0 support
`VK_KHR_raytracing` is used to enable cross-vendor ray-tracing support.
The implementation is WIP, but it is good enough to run some real content.
As of writing, only the NVIDIA driver works correctly.
It is expected AMD RDNA2 GPUs will work when working drivers are available
(amdgpu-pro 21.10 is known to not work).
Games which are expected to work include:
- Control (appears to be fully working)
- Ghostrunner (seems to work, not exhaustively tested)
To enable DXR support, `VKD3D_CONFIG=dxr %command%` should be used when launching game.
Certain games may be unstable if DXR is enabled by default.
#### Conservative rasterization
Full support (tier 3) for conservative rasterization was added.
#### Variable rate shading
Full support (tier 2) for variable rate shading was added.
#### Command list bundles
Allows Kingdom Hearts remaster to get past the errors, unsure if game fully works yet.
#### Write Watch and APITrace
Support for `D3D12_HEAP_FLAG_ALLOW_WRITE_WATCH` has been added.
This means [APITraces](https://github.com/Joshua-Ashton/apitrace/releases) of titles can now be captured.
### Performance
- Improve GPU bound performance in RE2 by up to 20% on NVIDIA.
- Enable async compute queues. Greatly improves GPU performance and frame pacing in many titles.
Horizon Zero Dawn and Death Stranding see exceptional gains with this fix,
due to how the engines work. GPU utilization should now reach ~100%.
For best results, AMD Navi+ GPUs are recommended, but Polaris and earlier still
see great results. It is possible to disable this path, if for whatever reason
multiple queues are causing issues. See README.
- Optimize bindless constant buffer GPU-bound performance on NVIDIA if certain API code paths are used.
- Optimize sparse binding CPU overhead.
- `TRACE` logging calls are disabled by default on release builds.
### Fixes and workarounds
- Fix various DXIL bugs.
- Be more robust against broken pipeline creation API calls.
Avoids driver crashes in Forza Horizon 4.
- Workaround some buggy shaders in F1 2020.
- Fix bugs if depth bounds test is used in certain ways.
- Fix a read out-of-bounds in `UpdateTileMappings`.
- Fix `SV_ClipDistance` and `SV_CullDistance` in Hull Shaders.
## 2.2
This release is mostly a maintenance release which fixes bugs and regressions.
It also unblocks significant future feature development.
### Workaround removals
- Replace old `force_bindless_texel_buffer` workaround with
a more correct and performant implementation.
Death Stranding and Cyberpunk 2077 (and probably other games as well) do the right thing by default without the hack now.
- Remove old workaround `disable_query_optimization` for occlusion queries which was enabled for AC: Valhalla,
and is now replaced by a correct and efficient implementation.
#### Cyberpunk 2077 status
From recent testing on our end, it is unknown at this time if `VK_VALVE_mutable_descriptor_type` is still required for
Cyberpunk 2077. Manual testing hasn't been able to trigger a GPU hang.
The memory allocation rewrite in 2.2 can plausibly work around some of the bugs that `VK_VALVE_mutable_descriptor_type` fixed by accident.
The bugs in question could also have been fixed since release day, but we cannot prove this since the bug is completely random in nature.
### Regression fixes
- Fix regression in Horizon Zero Dawn for screen space reflections on water surfaces.
### Stability fixes
- Greatly improve stability on Polaris or older cards for certain titles.
Crashes which used to happen in Horizon Zero Dawn and Death Stranding seem to have disappeared
after the memory allocation rewrite.
GPU memory usage should decrease on these cards as well.
- DIRT 5 can get in-game now due to DXIL fixes, but is not yet playable.
### New features
- Add support for Variable Rate Shading tier 1.
### Future development
DXR is not yet supported, but has seen a fair bit of background work.
- Basic DXR pipelines can be created successfully.
- Memory allocation rewrite in 2.2 unblocks further DXR development.
## 2.1
This release fixes various bugs (mostly workarounds) and improves GPU-bound performance.
New games added to "expected to work" list:
- The Division (was working already in 2.0, but missing from list)
- AC: Valhalla (*)
(*): Game requires full D3D12 sparse texture support to work.
Currently only works on NVIDIA drivers.
RADV status remains unknown until support for this feature lands in Mesa.
New games added to "kinda works, but expect a lot of jank" list:
- Cyberpunk 2077 (**)
(**): Currently only runs correctly on AMD hardware with RADV and `VK_VALVE_mutable_descriptor_type`.
As of game version 1.03, this requires the latest Mesa Git build.
The game has some fatal bugs where it relies on undefined behavior with descriptor management
which this extension works around by accident.
The game will start and run on NVIDIA, but just like what happens without the extension on AMD,
the GPU will randomly hang, making the game effectively unplayable.
A game update to fix this bug would likely make the game playable on NVIDIA as well.
Game version 1.04 changed some behavior, and support for this game will likely fluctuate over time as future patches come in.
Bug fixes and workarounds:
- Fix various implementation bugs which caused AC: Valhalla to not work.
- Work around game bug in Death Stranding where accessing map could cause corrupt rendering.
(Several games appear to have the same kind of application bug.)
- Fix corrupt textures in Horizon Zero Dawn benchmark.
- Fix SM 6.0 wave-op detection for Horizon Zero Dawn and DIRT 5.
- Work around GPU hangs in certain situations where games do not use D3D12 correctly,
but native D3D12 drivers just render wrong results rather than hang the system.
- Fix invalid SPIR-V generated by FP64 code.
- Fix crash with minimized windows in certain cases.
Performance:
- ~15% GPU-bound uplift in Ghostrunner. Might help UE4 titles in general.
- Slightly improve GPU bound performance when fully GPU bound on both AMD and NVIDIA.
- Slightly improve GPU bound performance on RADV in various titles.
- Reduce multi-threaded CPU overhead for certain D3D12 API usage patterns.
- Add support for `VK_VALVE_mutable_descriptor_type` which
improves CPU overhead, memory bloat, and avoids potential memory management thrashing on RADV.
Also avoids GPU hangs in certain situations where games misuse the D3D12 API.
Misc:
- Implement `DXGI_PRESENT_TEST`.
- Fix log spam when `DXGI_PRESENT_ALLOW_TEARING` is used.
## 2.0
This initial release supports D3D12 Feature Level 12.0 and Shader Model 6.0 (DXIL).
Games expected to work include:
- Control
- Death Stranding
- Devil May Cry 5
- Ghostrunner
- Horizon Zero Dawn
- Metro Exodus
- Monster Hunter World
- Resident Evil 2 / 3
Please refer to the README for supported driver versions.

View File

@ -1,7 +1,7 @@
Copyright 2016-2022 the vkd3d-proton project authors (see the file AUTHORS for a
Copyright 2016-2019 the Vkd3d project authors (see the file AUTHORS for a
complete list)
vkd3d-proton is free software; you can redistribute it and/or modify it under
Vkd3d is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.

337
README.md
View File

@ -9,54 +9,11 @@ The original project is available at [WineHQ](https://source.winehq.org/git/vkd3
## Priorities
Performance and game compatibility are important targets, at the expense of compatibility with older drivers and systems.
Modern Vulkan extensions and features are aggressively made use of to improve game performance and compatibility.
Performance and compatibility are important targets, at the expense of compatibility with older drivers and systems.
Modern Vulkan extensions and features are aggressively made use of to improve performance and compatibility.
It is recommended to use the very latest drivers you can get your hands on for the best experience.
Backwards compatibility with the vkd3d standalone API is not a goal of this project.
## Drivers
There are some hard requirements on drivers to be able to implement D3D12 in a reasonably performant way.
- Vulkan 1.1
- `VK_EXT_descriptor_indexing` with at least 1000000 UpdateAfterBind descriptors for all types except UniformBuffer.
Essentially all features in `VkPhysicalDeviceDescriptorIndexingFeatures` must be supported.
- `VK_KHR_timeline_semaphore`
- `VK_KHR_sampler_mirror_clamp_to_edge`
- `VK_EXT_robustness2`
- `VK_KHR_separate_depth_stencil_layouts`
- `VK_KHR_bind_memory2`
- `VK_KHR_copy_commands2`
- `VK_KHR_dynamic_rendering`
- `VK_EXT_extended_dynamic_state`
- `VK_EXT_extended_dynamic_state2`
Some notable extensions that **should** be supported for optimal or correct behavior.
These extensions will likely become mandatory later.
- `VK_KHR_buffer_device_address`
- `VK_EXT_image_view_min_lod`
`VK_VALVE_mutable_descriptor_type` is also highly recommended, but not mandatory.
### AMD (RADV)
For AMD, RADV is the recommended driver and the one that sees most testing on AMD GPUs.
The minimum requirement at the moment is Mesa 22.0 since it supports `VK_KHR_dynamic_rendering`.
NOTE: For older Mesa versions, use the v2.6 release.
### NVIDIA
The [Vulkan beta drivers](https://developer.nvidia.com/vulkan-driver) generally contain the latest
driver fixes that we identify while getting games to work.
The latest drivers (stable, beta or Vulkan beta tracks) are always preferred.
If you're having problems, always try the latest drivers.
### Intel
We have not done any testing against Intel iGPUs yet.
------
## Cloning the repo
@ -67,117 +24,92 @@ git clone --recursive https://github.com/HansKristian-Work/vkd3d-proton
```
in order to pull in all the submodules which are needed for building.
## Building VKD3D-Proton
## Building VKD3D
### Requirements:
- [wine](https://www.winehq.org/) (for `widl`) [for native builds]
- On Windows this may be substituted for [Strawberry Perl](http://strawberryperl.com/) as it ships `widl` and is easy to find and install -- although this dependency may be eliminated in the future.
- [Meson](http://mesonbuild.com/) build system (at least version 0.49)
- [Meson](http://mesonbuild.com/) build system (at least version 0.51)
- [glslang](https://github.com/KhronosGroup/glslang) compiler
- [Mingw-w64](http://mingw-w64.org/) compiler, headers and tools (at least version 7.0) [for cross-builds for d3d12.dll which are default]
### Building:
#### The simple way
Inside the VKD3D-Proton directory, run:
Inside the VKD3D directory, run:
```
./package-release.sh master /your/target/directory --no-package
```
This will create a folder `vkd3d-master` in `/your/target/directory`, which contains both 32-bit and 64-bit versions of VKD3D-Proton, which can be set up in the same way as the release versions as noted above.
This will create a folder `vkd3d-master` in `/your/target/directory`, which contains both 32-bit and 64-bit versions of VKD3D, which can be set up in the same way as the release versions as noted above.
If you want to build natively (ie. for `libvkd3d-proton.so`), pass `--native` to the build script. This option will make it build using your system's compilers.
If you want to build natively (ie. for `libvkd3d.so`), pass `--native` to the build script. This option will make it build using your system's compilers.
In order to preserve the build directories for development, pass `--dev-build` to the script. This option implies `--no-package`. After making changes to the source code, you can then do the following to rebuild VKD3D-Proton:
In order to preserve the build directories for development, pass `--dev-build` to the script. This option implies `--no-package`. After making changes to the source code, you can then do the following to rebuild VKD3D:
```
# change to build.86 for 32-bit
ninja -C /your/target/directory/build.64 install
cd /your/target/directory/build.64
ninja install
```
#### Compiling manually (cross for d3d12.dll, default)
```
# 64-bit build.
meson --cross-file build-win64.txt --buildtype release --prefix /your/vkd3d-proton/directory build.64
ninja -C build.64 install
meson --cross-file build-win64.txt -Denable_standalone_d3d12=True --buildtype release --prefix /your/vkd3d/directory build.64
cd build.64
ninja install
# 32-bit build
meson --cross-file build-win32.txt --buildtype release --prefix /your/vkd3d-proton/directory build.86
ninja -C build.86 install
meson --cross-file build-win32.txt -Denable_standalone_d3d12=True --buildtype release --prefix /your/vkd3d/directory build.86
cd build.86
ninja install
```
#### Compiling manually (native)
```
# 64-bit build.
meson --buildtype release --prefix /your/vkd3d-proton/directory build.64
ninja -C build.64 install
meson --buildtype release --prefix /your/vkd3d/directory build.64
cd build.64
ninja install
# 32-bit build
CC="gcc -m32" CXX="g++ -m32" \
PKG_CONFIG_PATH="/usr/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/pkgconfig" \
meson --buildtype release --prefix /your/vkd3d-proton/directory build.86
ninja -C build.86 install
meson --cross-file x86-linux-gnu --buildtype release --prefix /your/vkd3d/directory build.86
cd build.86
ninja install
```
## Using VKD3D-Proton
## Using VKD3D
The intended way to use VKD3D-Proton is as a native Win32 d3d12.dll.
This serves as a drop-in replacement for D3D12, and can be used in Wine (Proton or vanilla flavors), or on Windows.
VKD3D can be used by projects that target Direct3D 12 as a drop-in replacement
at build-time with some modest source modifications.
VKD3D-Proton does not supply the necessary DXGI component.
VKD3D-Proton can be used with either DXVK's DXGI implementation, or
Wine's DXGI implementation.
VKD3D-Proton implements its own IDXGISwapChain when built as a native d3d12.dll.
### A note on using VKD3D-Proton on Windows
Native Windows use is mostly relevant for developer testing purposes.
Do not expect games running on Windows 7 or 8.1 to magically make use of VKD3D-Proton,
as many games will only even attempt to load d3d12.dll if they are running on Windows 10.
### Native Linux build
A native Linux binary can be built, but it is not intended to be compatible with upstream Wine.
A native option is mostly relevant for development purposes.
If VKD3D is available when building Wine, then Wine will use it to support
Direct3D 12 applications.
## Environment variables
Most of the environment variables used by VKD3D-Proton are for debugging purposes. The
Most of the environment variables used by VKD3D are for debugging purposes. The
environment variables are not considered a part of API and might be changed or
removed in the future versions of VKD3D-Proton.
removed in the future versions of VKD3D.
Some of debug variables are lists of elements. Elements must be separated by
commas or semicolons.
- `VKD3D_CONFIG` - a list of options that change the behavior of vkd3d-proton.
- `vk_debug` - enables Vulkan debug extensions and loads validation layer.
- `skip_application_workarounds` - Skips all application workarounds.
For debugging purposes.
- `dxr` - Enables DXR support if supported by device.
- `dxr11` - Enables DXR tier 1.1 support if supported by device.
- `force_static_cbv` - Unsafe speed hack on NVIDIA. May or may not give a significant performance uplift.
- `single_queue` - Do not use asynchronous compute or transfer queues.
- `no_upload_hvv` - Blocks any attempt to use host-visible VRAM (large/resizable BAR) for the UPLOAD heap.
May free up vital VRAM in certain critical situations, at cost of lower GPU performance.
A fraction of VRAM is reserved for resizable BAR allocations either way,
so it should not be a real issue even on lower VRAM cards.
- `force_host_cached` - Forces all host visible allocations to be CACHED, which greatly accelerates captures.
- `no_invariant_position` - Avoids workarounds for invariant position. The workaround is enabled by default.
- `VKD3D_CONFIG` - a list of options that change the behavior of libvkd3d.
- vk_debug - enables Vulkan debug extensions and loads validation layer.
- `VKD3D_DEBUG` - controls the debug level for log messages produced by
vkd3d-proton. Accepts the following values: none, err, info, fixme, warn, trace.
libvkd3d. Accepts the following values: none, err, fixme, warn, trace.
- `VKD3D_SHADER_DEBUG` - controls the debug level for log messages produced by
the shader compilers. See `VKD3D_DEBUG` for accepted values.
libvkd3d-shader. See `VKD3D_DEBUG` for accepted values.
- `VKD3D_LOG_FILE` - If set, redirects `VKD3D_DEBUG` logging output to a file instead.
- `VKD3D_VULKAN_DEVICE` - a zero-based device index. Use to force the selected
Vulkan device.
- `VKD3D_FILTER_DEVICE_NAME` - skips devices that don't include this substring.
- `VKD3D_DISABLE_EXTENSIONS` - a list of Vulkan extensions that vkd3d-proton should
- `VKD3D_DISABLE_EXTENSIONS` - a list of Vulkan extensions that libvkd3d should
not use even if available.
- `VKD3D_TEST_DEBUG` - enables additional debug messages in tests. Set to 0, 1
or 2.
- `VKD3D_TEST_FILTER` - a filter string. Only the tests whose names matches the
filter string will be run, e.g. `VKD3D_TEST_FILTER=clear_render_target`.
Useful for debugging or developing new tests.
- `VKD3D_TEST_EXCLUDE` - excludes tests of which the name is included in the string,
e.g. `VKD3D_TEST_EXCLUDE=test_root_signature_priority,test_conservative_rasterization_dxil`.
- `VKD3D_TEST_PLATFORM` - can be set to "wine", "windows" or "other". The test
platform controls the behavior of todo(), todo_if(), bug_if() and broken()
conditions in tests.
@ -185,39 +117,6 @@ commas or semicolons.
- `VKD3D_PROFILE_PATH` - If profiling is enabled in the build, a profiling block is
emitted to `${VKD3D_PROFILE_PATH}.${pid}`.
## Shader cache
By default, vkd3d-proton manages its own driver cache.
This cache is intended to cache DXBC/DXIL -> SPIR-V conversion.
This reduces stutter (when pipelines are created last minute and app relies on hot driver cache)
and load times (when applications do the right thing of loading PSOs up front).
Behavior is designed to be close to DXVK state cache.
#### Default behavior
`vkd3d-proton.cache` (and `vkd3d-proton.cache.write`) are placed in the current working directory.
Generally, this is the game install folder when running in Steam.
#### Custom directory
`VKD3D_SHADER_CACHE_PATH=/path/to/directory` overrides the directory where `vkd3d-proton.cache` is placed.
#### Disable cache
`VKD3D_SHADER_CACHE_PATH=0` disables the internal cache, and any caching would have to be explicitly managed
by application.
### Behavior of ID3D12PipelineLibrary
When explicit shader cache is used, the need for application managed pipeline libraries is greatly diminished,
and the cache applications interact with is a dummy cache.
If the vkd3d-proton shader cache is disabled, ID3D12PipelineLibrary stores everything relevant for a full cache,
i.e. SPIR-V and PSO driver cache blob.
`VKD3D_CONFIG=pipeline_library_app_cache` is an alternative to `VKD3D_SHADER_CACHE_PATH=0` and can be
automatically enabled based on app-profiles if relevant in the future if applications manage the caches better
than vkd3d-proton can do automagically.
## CPU profiling (development)
Pass `-Denable_profiling=true` to Meson to enable a profiled build. With a profiled build, use `VKD3D_PROFILE_PATH` environment variable.
@ -239,26 +138,12 @@ pass `-Denable_renderdoc=true` to Meson.
vkd3d-proton will automatically make a capture when a specific shader is encountered.
- `VKD3D_AUTO_CAPTURE_COUNTS` - A comma-separated list of indices. This can be used to control which queue submissions to capture.
E.g., use `VKD3D_AUTO_CAPTURE_COUNTS=0,4,10` to capture the 0th (first submission), 4th and 10th submissions which are candidates for capturing.
If `VKD3D_AUTO_CAPTURE_COUNTS` is `-1`, the entire app runtime can be turned into one big capture.
This is only intended to be used when capturing something like the test suite,
or tiny applications with a finite runtime to make it easier to debug cross submission work.
If only `VKD3D_AUTO_CAPTURE_COUNTS` is set, any queue submission is considered for capturing.
If only `VKD3D_AUTO_CAPTURE_SHADER` is set, `VKD3D_AUTO_CAPTURE_COUNTS` is considered to be equal to `"0"`, i.e. a capture is only
made on first encounter with the target shader.
If both are set, the capture counter is only incremented and considered when a submission contains the use of the target shader.
### Breadcrumbs debugging
For debugging GPU hangs, it's useful to know where crashes happen.
If the build has trace enabled (non-release builds), breadcrumbs support is also enabled.
`VKD3D_CONFIG=breadcrumbs` will instrument command lists with `VK_AMD_buffer_marker` or `VK_NV_device_checkpoints`.
On GPU device lost or timeout, crash dumps are written to the log.
For best results on RADV, use `RADV_DEBUG=syncshaders`. The logs will print a digested form of the command lists
which were executing at the time, and attempt to narrow down the possible range of commands which could
have caused a crash.
### Shader logging
It is possible to log the output of replaced shaders, essentially a custom shader printf. To enable this feature, `VK_KHR_buffer_device_address` must be supported.
@ -270,11 +155,8 @@ and avoids any possible accidental hiding of bugs by introducing validation laye
Using `debugPrintEXT` is also possible if that fits better with your debugging scenario.
With this shader replacement scheme, we're able to add shader logging as unintrusive as possible.
```
# Inside folder full of override shaders, build everything with:
make -C /path/to/include/shader-debug M=$PWD
```
The shader can then include `#include "debug_channel.h"` and use various functions below.
Replaced shaders will need to include `debug_channel.h` from `include/shader-debug`.
Use `glslc -I/path/to/vkd3d-proton/include/shader-debug --target-env=vulkan1.1` when compiling replaced shaders.
```
void DEBUG_CHANNEL_INIT(uvec3 ID);
@ -298,150 +180,3 @@ void DEBUG_CHANNEL_MSG(float v0, float v1, ...); // Up to 4 components, ...
```
These functions log, formatting is `#%x` for uint, `%d` for int and `%f` for float type.
## Descriptor debugging
If `-Denable_descriptor_qa=true` is enabled in build, you can set the `VKD3D_DESCRIPTOR_QA_LOG` env-var to a file.
All descriptor updates and copies are logged so that it's possible to correlate descriptors with
GPU crash dumps. `enable_descriptor_qa` is not enabled by default,
since it adds some flat overhead in an extremely hot code path.
### GPU-assisted debugging
If `VKD3D_CONFIG=descriptor_qa_checks` is set with a build which enables `-Denable_descriptor_qa=true`,
all shaders will be instrumented to check for invalid access. In the log, you will see this to
make sure the feature is enabled.
```
932:info:vkd3d_descriptor_debug_init_once: Enabling descriptor QA checks!
```
The main motivation is the tight integration and high performance.
GPU-assisted debugging can be run at well over playable speeds.
#### Descriptor heap index out of bounds
```
============
Fault type: HEAP_OUT_OF_RANGE
Fault type: MISMATCH_DESCRIPTOR_TYPE
CBV_SRV_UAV heap cookie: 1800
Shader hash and instruction: edbaf1b5ed344467 (1)
Accessed resource/view cookie: 0
Shader desired descriptor type: 8 (STORAGE_BUFFER)
Found descriptor type in heap: 0 (NONE)
Failed heap index: 1024000
==========
```
The instruction `(1)`, is reported as well,
and a disassembly of the shader in question can be used to pinpoint exactly where
things are going wrong.
Dump all shaders with `VKD3D_SHADER_DUMP_PATH=/my/folder`,
and run `spirv-cross -V /my/folder/edbaf1b5ed344467.spv`.
(NOTE: clear out the folder before dumping, existing files are not overwritten).
The faulting instruction can be identified by looking at last argument, e.g.:
```
uint fixup_index = descriptor_qa_check(heap_index, descriptor_type, 1u /* instruction ID */);
```
#### Mismatch descriptor type
```
============
Fault type: MISMATCH_DESCRIPTOR_TYPE
CBV_SRV_UAV heap cookie: 1800 // Refer to VKD3D_DESCRIPTOR_QA_LOG
Shader hash and instruction: edbaf1b5ed344467 (1)
Accessed resource/view cookie: 1802 // Refer to VKD3D_DESCRIPTOR_QA_LOG
Shader desired descriptor type: 8 (STORAGE_BUFFER)
Found descriptor type in heap: 1 (SAMPLED_IMAGE)
Failed heap index: 1025
==========
```
#### Accessing destroyed resource
```
============
Fault type: DESTROYED_RESOURCE
CBV_SRV_UAV heap cookie: 1800
Shader hash and instruction: edbaf1b5ed344467 (2)
Accessed resource/view cookie: 1806
Shader desired descriptor type: 1 (SAMPLED_IMAGE)
Found descriptor type in heap: 1 (SAMPLED_IMAGE)
Failed heap index: 1029
==========
```
### Debugging descriptor crashes with RADV dumps (hardcore ultra nightmare mode)
For when you're absolutely desperate, there is a way to debug GPU hangs.
First, install [umr](https://gitlab.freedesktop.org/tomstdenis/umr) and make the binary setsuid.
`ACO_DEBUG=force-waitcnt RADV_DEBUG=hang VKD3D_DESCRIPTOR_QA_LOG=/somewhere/desc.txt %command%`
It is possible to use `RADV_DEBUG=hang,umr` as well, but from within Wine, there are weird things
happening where UMR dumps do not always succeed.
Instead, it is possible to invoke umr manually from an SSH shell when the GPU hangs.
```
#!/bin/bash
mkdir -p "$HOME/umr-dump"
# For Navi, older GPUs might have different rings. See RADV source.
umr -R gfx_0.0.0 > "$HOME/umr-dump/ring.txt" 2>&1
umr -O halt_waves -wa gfx_0.0.0 > "$HOME/umr-dump/halt-waves-1.txt" 2>&1
umr -O bits,halt_waves -wa gfx_0.0.0 > "$HOME/umr-dump/halt-waves-2.txt" 2>&1
```
A folder is placed in `~/radv_dumps*` by RADV, and the UMR script will place wave dumps in `~/umr-dump`.
First, we can study the wave dumps to see where things crash, e.g.:
```
pgm[6@0x800120e26c00 + 0x584 ] = 0xf0001108 image_load v47, v[4:5], s[48:55] dmask:0x1 dim:SQ_RSRC_IMG_2D unorm
pgm[6@0x800120e26c00 + 0x588 ] = 0x000c2f04 ;;
pgm[6@0x800120e26c00 + 0x58c ] = 0xbf8c3f70 s_waitcnt vmcnt(0)
* pgm[6@0x800120e26c00 + 0x590 ] = 0x930118c0 s_mul_i32 s1, 64, s24
pgm[6@0x800120e26c00 + 0x594 ] = 0xf40c0c09 s_load_dwordx8 s[48:55], s[18:19], s1
pgm[6@0x800120e26c00 + 0x598 ] = 0x02000000 ;;
```
excp: 256 is a memory error (at least on 5700xt).
```
TRAPSTS[50000100]:
excp: 256 | illegal_inst: 0 | buffer_oob: 0 | excp_cycle: 0 |
excp_wave64hi: 0 | xnack_error: 1 | dp_rate: 2 | excp_group_mask: 0 |
```
We can inspect all VGPRs and all SGPRs, here for the image descriptor.
```
[ 48.. 51] = { 0130a000, c0500080, 810dc1df, 93b00204 }
[ 52.. 55] = { 00000000, 00400000, 002b0000, 800130c8 }
```
Decode the VA and study `bo_history.log`. There is a script in RADV which lets you query history for a VA.
This lets us verify that the VA in question was freed at some point.
At point of writing, there is no easy way to decode raw descriptor blobs, but when you're desperate enough you can do it by hand :|
In `pipeline.log` we have the full SPIR-V (with OpSource reference to the source DXIL/DXBC)
and disassembly of the crashed pipeline. Here we can study the code to figure out which descriptor was read.
```
// s7 is the descriptor heap index, s1 is the offset (64 bytes per image descriptor),
// s[18:19] is the descriptor heap.
s_mul_i32 s1, 64, s7 ; 930107c0
s_load_dwordx8 s[48:55], s[18:19], s1 ; f40c0c09 02000000
s_waitcnt lgkmcnt(0) ; bf8cc07f
image_load v47, v[4:5], s[48:55] dmask:0x1 dim:SQ_RSRC_IMG_2D unorm ; f0001108 000c2f04
```
```
[ 4.. 7] = { 03200020, ffff8000, 0000002b, 00000103 }
```
Which is descriptor index #259. Based on this, we can inspect the descriptor QA log and verify that the application
did indeed do something invalid, which caused the GPU hang.

View File

@ -20,7 +20,7 @@
#include <stdbool.h>
#include <stdio.h>
#define DEMO_WINDOW_CLASS_NAME u"demo_wc"
#define DEMO_WINDOW_CLASS_NAME L"demo_wc"
struct demo
{

View File

@ -493,6 +493,8 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c
WaitForFences(vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX);
ResetFences(vk_device, 1, &vk_fence);
resource_create_info.type = VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO;
resource_create_info.next = NULL;
resource_create_info.desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
resource_create_info.desc.Alignment = 0;
resource_create_info.desc.Width = desc->width;
@ -504,7 +506,7 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c
resource_create_info.desc.SampleDesc.Quality = 0;
resource_create_info.desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resource_create_info.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
resource_create_info.flags = 0;
resource_create_info.flags = VKD3D_RESOURCE_INITIAL_STATE_TRANSITION | VKD3D_RESOURCE_PRESENT_STATE_TRANSITION;
resource_create_info.present_state = D3D12_RESOURCE_STATE_PRESENT;
for (i = 0; i < image_count; ++i)
{
@ -519,8 +521,6 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c
free(vk_images);
goto fail;
}
vkd3d_enqueue_initial_transition(command_queue, swapchain->buffers[i]);
}
swapchain->buffer_count = image_count;
free(vk_images);

View File

@ -291,7 +291,7 @@ static double cxg_get_time(void)
static void cxg_render_frame(struct cx_gears *cxg)
{
static double t_prev = -1.0;
static double t_prev = -1.0;
double dt, t;
float a;
@ -456,8 +456,13 @@ static void cxg_mesh_create(ID3D12Device *device, float inner_radius, float oute
float r0, r1, r2;
float angle, da;
vertices = calloc(tooth_count, 12 * sizeof(*vertices));
faces = calloc(tooth_count, 20 * sizeof(*faces));
if (!(vertices = calloc(tooth_count, 12 * sizeof(*vertices))))
return;
if (!(faces = calloc(tooth_count, 20 * sizeof(*faces))))
{
free(vertices);
return;
}
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0f;

View File

@ -1,5 +1,5 @@
demo_vkd3d_deps = [
threads_dep, vkd3d_common_dep
threads_dep
]
if vkd3d_platform != 'windows'
@ -18,16 +18,16 @@ else
]
endif
executable('gears', 'gears.c',
executable('gears', 'gears.c', vkd3d_headers,
dependencies : demo_vkd3d_deps,
include_directories : vkd3d_public_includes,
install : true,
gui_app : true,
override_options : [ 'c_std='+vkd3d_c_std ])
executable('triangle', 'triangle.c',
executable('triangle', 'triangle.c', vkd3d_headers,
dependencies : demo_vkd3d_deps,
include_directories : vkd3d_public_includes,
install : true,
gui_app : true,
override_options : [ 'c_std='+vkd3d_c_std ])
override_options : [ 'c_std='+vkd3d_c_std ])

View File

@ -10,8 +10,6 @@ vkd3d_idl = [
'vkd3d_dxgiformat.idl',
'vkd3d_dxgitype.idl',
'vkd3d_swapchain_factory.idl',
'vkd3d_command_list_vkd3d_ext.idl',
'vkd3d_device_vkd3d_ext.idl'
]
vkd3d_header_files = idl_generator.process(vkd3d_idl)
vkd3d_headers = idl_generator.process(vkd3d_idl)

View File

@ -23,7 +23,7 @@
#include <stddef.h>
#include "vkd3d_memory.h"
#include "memory.h"
enum hash_map_entry_flag
{
@ -50,17 +50,22 @@ struct hash_map
uint32_t used_count;
};
static inline struct hash_map_entry *hash_map_get_entry(const struct hash_map *hash_map, uint32_t entry_idx)
static inline void *hash_map_ptr_offset(void *ptr, size_t offset)
{
return void_ptr_offset(hash_map->entries, hash_map->entry_size * entry_idx);
return ((char*)ptr) + offset;
}
static inline uint32_t hash_map_get_entry_idx(const struct hash_map *hash_map, uint32_t hash_value)
static inline struct hash_map_entry *hash_map_get_entry(struct hash_map *hash_map, uint32_t entry_idx)
{
return hash_map_ptr_offset(hash_map->entries, hash_map->entry_size * entry_idx);
}
static inline uint32_t hash_map_get_entry_idx(struct hash_map *hash_map, uint32_t hash_value)
{
return hash_value % hash_map->entry_count;
}
static inline uint32_t hash_map_next_entry_idx(const struct hash_map *hash_map, uint32_t entry_idx)
static inline uint32_t hash_map_next_entry_idx(struct hash_map *hash_map, uint32_t entry_idx)
{
uint32_t next_idx = entry_idx + 1;
return next_idx < hash_map->entry_count ? next_idx : 0;
@ -93,7 +98,7 @@ static inline bool hash_map_grow(struct hash_map *hash_map)
for (i = 0; i < old_count; i++)
{
/* Relocate existing entries one by one */
struct hash_map_entry *old_entry = void_ptr_offset(old_entries, i * hash_map->entry_size);
struct hash_map_entry *old_entry = hash_map_ptr_offset(old_entries, i * hash_map->entry_size);
if (old_entry->flags & HASH_MAP_ENTRY_OCCUPIED)
{
@ -120,10 +125,10 @@ static inline bool hash_map_should_grow_before_insert(struct hash_map *hash_map)
return 10 * hash_map->used_count >= 7 * hash_map->entry_count;
}
static inline struct hash_map_entry *hash_map_find(const struct hash_map *hash_map, const void *key)
static inline struct hash_map_entry *hash_map_find(struct hash_map *hash_map, const void *key)
{
uint32_t hash_value, entry_idx;
if (!hash_map->entries)
return NULL;
@ -165,23 +170,18 @@ static inline struct hash_map_entry *hash_map_insert(struct hash_map *hash_map,
struct hash_map_entry *current = hash_map_get_entry(hash_map, entry_idx);
if (!(current->flags & HASH_MAP_ENTRY_OCCUPIED) ||
(current->hash_value == hash_value && hash_map->compare_func(key, current)))
(current->hash_value == hash_value && hash_map->compare_func(key, entry)))
target = current;
else
entry_idx = hash_map_next_entry_idx(hash_map, entry_idx);
entry_idx = hash_map_next_entry_idx(hash_map, entry_idx);
}
if (!(target->flags & HASH_MAP_ENTRY_OCCUPIED))
{
hash_map->used_count += 1;
target->flags = HASH_MAP_ENTRY_OCCUPIED;
target->hash_value = hash_value;
memcpy(target + 1, entry + 1, hash_map->entry_size - sizeof(*entry));
}
/* If target is occupied, we already have an entry in the hashmap.
* Return old one, caller is responsible for cleaning up the node we attempted to add. */
memcpy(target, entry, hash_map->entry_size);
target->flags = HASH_MAP_ENTRY_OCCUPIED;
target->hash_value = hash_value;
return target;
}
@ -193,7 +193,6 @@ static inline void hash_map_init(struct hash_map *hash_map, pfn_hash_func hash_f
hash_map->entry_size = entry_size;
hash_map->entry_count = 0;
hash_map->used_count = 0;
assert(entry_size > sizeof(struct hash_map_entry));
}
static inline void hash_map_clear(struct hash_map *hash_map)
@ -213,43 +212,4 @@ static inline uint32_t hash_uint64(uint64_t n)
return hash_combine((uint32_t)n, (uint32_t)(n >> 32));
}
/* A somewhat stronger hash when we're meant to store the hash (pipeline caches, etc). Based on FNV-1a. */
static inline uint64_t hash_fnv1_init()
{
return 0xcbf29ce484222325ull;
}
static inline uint64_t hash_fnv1_iterate_u8(uint64_t h, uint8_t value)
{
return (h * 0x100000001b3ull) ^ value;
}
static inline uint64_t hash_fnv1_iterate_u32(uint64_t h, uint32_t value)
{
return (h * 0x100000001b3ull) ^ value;
}
static inline uint64_t hash_fnv1_iterate_f32(uint64_t h, float value)
{
union u { float f32; uint32_t u32; } v;
v.f32 = value;
return hash_fnv1_iterate_u32(h, v.u32);
}
static inline uint64_t hash_fnv1_iterate_u64(uint64_t h, uint64_t value)
{
h = hash_fnv1_iterate_u32(h, value & UINT32_MAX);
h = hash_fnv1_iterate_u32(h, value >> 32);
return h;
}
static inline uint64_t hash_fnv1_iterate_string(uint64_t h, const char *str)
{
if (str)
while (*str)
h = hash_fnv1_iterate_u8(h, *str++);
h = hash_fnv1_iterate_u8(h, 0);
return h;
}
#endif /* __VKD3D_HASHMAP_H */

View File

@ -53,19 +53,18 @@ FORCEINLINE void vkd3d_atomic_load_barrier(vkd3d_memory_order order)
}
}
/* Redefinitions for invalid memory orders */
#define InterlockedExchangeRelease InterlockedExchange
#define InterlockedExchangeRelease64 InterlockedExchange64
// Redefinitions for invalid memory orders...
#define InterlockedExchangeRelease InterlockedExchange
#define vkd3d_atomic_choose_intrinsic(order, result, intrinsic, suffix, ...) \
switch (order) \
{ \
case vkd3d_memory_order_relaxed: result = intrinsic##NoFence##suffix (__VA_ARGS__); break; \
case vkd3d_memory_order_consume: \
case vkd3d_memory_order_acquire: result = intrinsic##Acquire##suffix (__VA_ARGS__); break; \
case vkd3d_memory_order_release: result = intrinsic##Release##suffix (__VA_ARGS__); break; \
case vkd3d_memory_order_acq_rel: \
case vkd3d_memory_order_seq_cst: result = intrinsic##suffix (__VA_ARGS__); break; \
#define vkd3d_atomic_choose_intrinsic(order, result, intrinsic, ...) \
switch (order) \
{ \
case vkd3d_memory_order_relaxed: result = intrinsic##NoFence (__VA_ARGS__); break; \
case vkd3d_memory_order_consume: \
case vkd3d_memory_order_acquire: result = intrinsic##Acquire (__VA_ARGS__); break; \
case vkd3d_memory_order_release: result = intrinsic##Release (__VA_ARGS__); break; \
case vkd3d_memory_order_acq_rel: \
case vkd3d_memory_order_seq_cst: result = intrinsic (__VA_ARGS__); break; \
}
FORCEINLINE uint32_t vkd3d_atomic_uint32_load_explicit(uint32_t *target, vkd3d_memory_order order)
@ -79,7 +78,7 @@ FORCEINLINE void vkd3d_atomic_uint32_store_explicit(uint32_t *target, uint32_t v
{
switch (order)
{
case vkd3d_memory_order_release: vkd3d_atomic_rw_barrier(); /* fallthrough */
case vkd3d_memory_order_release: vkd3d_atomic_rw_barrier(); // fallthrough...
case vkd3d_memory_order_relaxed: *((volatile uint32_t*)target) = value; break;
default:
case vkd3d_memory_order_seq_cst:
@ -90,170 +89,42 @@ FORCEINLINE void vkd3d_atomic_uint32_store_explicit(uint32_t *target, uint32_t v
FORCEINLINE uint32_t vkd3d_atomic_uint32_exchange_explicit(uint32_t *target, uint32_t value, vkd3d_memory_order order)
{
uint32_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedExchange, /* no suffix */,(LONG*)target, value);
vkd3d_atomic_choose_intrinsic(order, result, InterlockedExchange, (LONG*)target, value);
return result;
}
FORCEINLINE uint32_t vkd3d_atomic_uint32_increment(uint32_t *target, vkd3d_memory_order order)
{
uint32_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedIncrement, /* no suffix */,(LONG*)target);
vkd3d_atomic_choose_intrinsic(order, result, InterlockedIncrement, (LONG*)target);
return result;
}
FORCEINLINE uint32_t vkd3d_atomic_uint32_decrement(uint32_t *target, vkd3d_memory_order order)
{
uint32_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedDecrement, /* no suffix */,(LONG*)target);
return result;
}
FORCEINLINE uint32_t vkd3d_atomic_uint32_add(uint32_t *target, uint32_t value, vkd3d_memory_order order)
{
uint32_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedAdd, /* no suffix */,(LONG*)target, value);
return result;
}
FORCEINLINE uint32_t vkd3d_atomic_uint32_sub(uint32_t *target, uint32_t value, vkd3d_memory_order order)
{
uint32_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedAdd, /* no suffix */,(LONG*)target, (uint32_t)(-(int32_t)value));
return result;
}
FORCEINLINE uint32_t vkd3d_atomic_uint32_and(uint32_t *target, uint32_t value, vkd3d_memory_order order)
{
uint32_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedAnd, /* no suffix */,(LONG*)target, value);
return result;
}
FORCEINLINE uint32_t vkd3d_atomic_uint32_or(uint32_t *target, uint32_t value, vkd3d_memory_order order)
{
uint32_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedOr, /* no suffix */,(LONG*)target, value);
return result;
}
FORCEINLINE uint32_t vkd3d_atomic_uint32_compare_exchange(uint32_t* target, uint32_t expected, uint32_t desired,
vkd3d_memory_order success_order, vkd3d_memory_order fail_order)
{
uint32_t result;
/* InterlockedCompareExchange has desired (ExChange) first, then expected (Comperand) */
vkd3d_atomic_choose_intrinsic(success_order, result, InterlockedCompareExchange, /* no suffix */, (LONG*)target, desired, expected);
return result;
}
FORCEINLINE uint64_t vkd3d_atomic_uint64_load_explicit(uint64_t *target, vkd3d_memory_order order)
{
uint64_t value = *((volatile uint64_t*)target);
vkd3d_atomic_load_barrier(order);
return value;
}
FORCEINLINE void vkd3d_atomic_uint64_store_explicit(uint64_t *target, uint64_t value, vkd3d_memory_order order)
{
switch (order)
{
case vkd3d_memory_order_release: vkd3d_atomic_rw_barrier(); /* fallthrough */
case vkd3d_memory_order_relaxed: *((volatile uint64_t*)target) = value; break;
default:
case vkd3d_memory_order_seq_cst:
(void) InterlockedExchange64((LONG64*) target, value);
}
}
FORCEINLINE uint64_t vkd3d_atomic_uint64_exchange_explicit(uint64_t *target, uint64_t value, vkd3d_memory_order order)
{
uint64_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedExchange, 64, (LONG64*)target, value);
return result;
}
FORCEINLINE uint64_t vkd3d_atomic_uint64_increment(uint64_t *target, vkd3d_memory_order order)
{
uint64_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedIncrement, 64, (LONG64*)target);
return result;
}
FORCEINLINE uint64_t vkd3d_atomic_uint64_decrement(uint64_t *target, vkd3d_memory_order order)
{
uint64_t result;
vkd3d_atomic_choose_intrinsic(order, result, InterlockedDecrement, 64, (LONG64*)target);
return result;
}
FORCEINLINE uint64_t vkd3d_atomic_uint64_compare_exchange(UINT64* target, uint64_t expected, uint64_t desired,
vkd3d_memory_order success_order, vkd3d_memory_order fail_order)
{
uint64_t result;
/* InterlockedCompareExchange has desired (ExChange) first, then expected (Comperand). Use UINT64 to mark 8-byte alignment. */
vkd3d_atomic_choose_intrinsic(success_order, result, InterlockedCompareExchange, 64, (LONG64*)target, desired, expected);
vkd3d_atomic_choose_intrinsic(order, result, InterlockedDecrement, (LONG*)target);
return result;
}
#elif defined(__GNUC__) || defined(__clang__)
typedef enum
{
vkd3d_memory_order_relaxed = __ATOMIC_RELAXED,
vkd3d_memory_order_consume = __ATOMIC_CONSUME,
vkd3d_memory_order_acquire = __ATOMIC_ACQUIRE,
vkd3d_memory_order_release = __ATOMIC_RELEASE,
vkd3d_memory_order_acq_rel = __ATOMIC_ACQ_REL,
vkd3d_memory_order_seq_cst = __ATOMIC_SEQ_CST,
} vkd3d_memory_order;
#define vkd3d_memory_order_relaxed __ATOMIC_RELAXED
#define vkd3d_memory_order_consume __ATOMIC_CONSUME
#define vkd3d_memory_order_acquire __ATOMIC_ACQUIRE
#define vkd3d_memory_order_release __ATOMIC_RELEASE
#define vkd3d_memory_order_acq_rel __ATOMIC_ACQ_REL
#define vkd3d_memory_order_seq_cst __ATOMIC_SEQ_CST
# define vkd3d_atomic_generic_load_explicit(target, order) __atomic_load_n(target, order)
# define vkd3d_atomic_generic_store_explicit(target, value, order) __atomic_store_n(target, value, order)
# define vkd3d_atomic_generic_exchange_explicit(target, value, order) __atomic_exchange_n(target, value, order)
# define vkd3d_atomic_generic_increment(target, order) __atomic_add_fetch(target, 1, order)
# define vkd3d_atomic_generic_decrement(target, order) __atomic_sub_fetch(target, 1, order)
# define vkd3d_atomic_generic_add(target, value, order) __atomic_add_fetch(target, value, order)
# define vkd3d_atomic_generic_sub(target, value, order) __atomic_sub_fetch(target, value, order)
# define vkd3d_atomic_generic_and(target, value, order) __atomic_and_fetch(target, value, order)
# define vkd3d_atomic_generic_or(target, value, order) __atomic_or_fetch(target, value, order)
# define vkd3d_atomic_uint32_load_explicit(target, order) vkd3d_atomic_generic_load_explicit(target, order)
# define vkd3d_atomic_uint32_store_explicit(target, value, order) vkd3d_atomic_generic_store_explicit(target, value, order)
# define vkd3d_atomic_uint32_exchange_explicit(target, value, order) vkd3d_atomic_generic_exchange_explicit(target, value, order)
# define vkd3d_atomic_uint32_increment(target, order) vkd3d_atomic_generic_increment(target, order)
# define vkd3d_atomic_uint32_decrement(target, order) vkd3d_atomic_generic_decrement(target, order)
# define vkd3d_atomic_uint32_add(target, value, order) vkd3d_atomic_generic_add(target, value, order)
# define vkd3d_atomic_uint32_sub(target, value, order) vkd3d_atomic_generic_sub(target, value, order)
# define vkd3d_atomic_uint32_and(target, value, order) vkd3d_atomic_generic_and(target, value, order)
# define vkd3d_atomic_uint32_or(target, value, order) vkd3d_atomic_generic_or(target, value, order)
static inline uint32_t vkd3d_atomic_uint32_compare_exchange(uint32_t* target, uint32_t expected, uint32_t desired,
vkd3d_memory_order success_order, vkd3d_memory_order fail_order)
{
/* Expected is written to with the old value in the case that *target != expected */
__atomic_compare_exchange_n(target, &expected, desired, 0, success_order, fail_order);
return expected;
}
# define vkd3d_atomic_uint64_load_explicit(target, order) vkd3d_atomic_generic_load_explicit(target, order)
# define vkd3d_atomic_uint64_store_explicit(target, value, order) vkd3d_atomic_generic_store_explicit(target, value, order)
# define vkd3d_atomic_uint64_exchange_explicit(target, value, order) vkd3d_atomic_generic_exchange_explicit(target, value, order)
# define vkd3d_atomic_uint64_increment(target, order) vkd3d_atomic_generic_increment(target, order)
# define vkd3d_atomic_uint64_decrement(target, order) vkd3d_atomic_generic_decrement(target, order)
static inline uint64_t vkd3d_atomic_uint64_compare_exchange(UINT64* target, uint64_t expected, uint64_t desired,
vkd3d_memory_order success_order, vkd3d_memory_order fail_order)
{
/* Expected is written to with the old value in the case that *target != expected. Use UINT64 to mark 8-byte alignment. */
__atomic_compare_exchange_n(target, &expected, desired, 0, success_order, fail_order);
return expected;
}
# define vkd3d_atomic_uint32_load_explicit(target, order) __atomic_load_n(target, order)
# define vkd3d_atomic_uint32_store_explicit(target, value, order) __atomic_store_n(target, value, order)
# define vkd3d_atomic_uint32_exchange_explicit(target, value, order) __atomic_exchange_n(target, value, order)
# define vkd3d_atomic_uint32_increment(target, order) __atomic_add_fetch(target, 1, order)
# define vkd3d_atomic_uint32_decrement(target, order) __atomic_sub_fetch(target, 1, order)
# ifndef __MINGW32__
# define InterlockedIncrement(target) vkd3d_atomic_uint32_increment(target, vkd3d_memory_order_seq_cst)
# define InterlockedDecrement(target) vkd3d_atomic_uint32_decrement(target, vkd3d_memory_order_seq_cst)
# define InterlockedCompareExchange(target, desired, expected) vkd3d_atomic_uint32_compare_exchange(target, expected, desired, vkd3d_memory_order_seq_cst, vkd3d_memory_order_acquire)
# define InterlockedIncrement64(target) vkd3d_atomic_uint64_increment(target, vkd3d_memory_order_seq_cst)
# define InterlockedDecrement64(target) vkd3d_atomic_uint64_decrement(target, vkd3d_memory_order_seq_cst)
# define InterlockedCompareExchange64(target, desired, expected) vkd3d_atomic_uint64_compare_exchange(target, expected, desired, vkd3d_memory_order_seq_cst, vkd3d_memory_order_acquire)
# define InterlockedIncrement(target) vkd3d_atomic_uint32_increment(target, vkd3d_memory_order_seq_cst)
# define InterlockedDecrement(target) vkd3d_atomic_uint32_decrement(target, vkd3d_memory_order_seq_cst)
# endif
#else
@ -262,22 +133,4 @@ static inline uint64_t vkd3d_atomic_uint64_compare_exchange(UINT64* target, uint
#endif
#if INTPTR_MAX == INT64_MAX
# define vkd3d_atomic_ptr_load_explicit(target, order) ((void *)vkd3d_atomic_uint64_load_explicit((uint64_t *)target, order))
# define vkd3d_atomic_ptr_store_explicit(target, value, order) (vkd3d_atomic_uint64_store_explicit((uint64_t *)target, (uint64_t)value, order))
# define vkd3d_atomic_ptr_exchange_explicit(target, value, order) ((void *)vkd3d_atomic_uint64_exchange_explicit((uint64_t *)target, (uint64_t)value, order))
# define vkd3d_atomic_ptr_increment(target, order) ((void *)vkd3d_atomic_uint64_increment((uint64_t *)target, order))
# define vkd3d_atomic_ptr_decrement(target, order) ((void *)vkd3d_atomic_uint64_decrement((uint64_t *)target, order))
# define vkd3d_atomic_ptr_compare_exchange(target, expected, desired, success_order, fail_order) \
((void *)vkd3d_atomic_uint64_compare_exchange((UINT64 *)target, (uint64_t)expected, (uint64_t)desired, success_order, fail_order))
#else
# define vkd3d_atomic_ptr_load_explicit(target, order) ((void *)vkd3d_atomic_uint32_load_explicit((uint32_t *)target, order))
# define vkd3d_atomic_ptr_store_explicit(target, value, order) (vkd3d_atomic_uint32_store_explicit((uint32_t *)target, (uint32_t)value, order))
# define vkd3d_atomic_ptr_exchange_explicit(target, value, order) ((void *)vkd3d_atomic_uint32_exchange_explicit((uint32_t *)target, (uint32_t)value, order))
# define vkd3d_atomic_ptr_increment(target, order) ((void *)vkd3d_atomic_uint32_increment((uint32_t *)target, order))
# define vkd3d_atomic_ptr_decrement(target, order) ((void *)vkd3d_atomic_uint32_decrement((uint32_t *)target, order))
# define vkd3d_atomic_ptr_compare_exchange(target, expected, desired, success_order, fail_order) \
((void *)vkd3d_atomic_uint32_compare_exchange((uint32_t *)target, (uint32_t)expected, (uint32_t)desired, success_order, fail_order))
#endif
#endif
#endif

View File

@ -27,12 +27,9 @@
#include <stdint.h>
#include <limits.h>
#include <stdbool.h>
#include <assert.h>
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <time.h>
#endif
#ifndef ARRAY_SIZE
@ -45,15 +42,8 @@
#define MEMBER_SIZE(t, m) sizeof(((t *)0)->m)
static inline uint64_t align64(uint64_t addr, uint64_t alignment)
{
assert(alignment > 0 && (alignment & (alignment - 1)) == 0);
return (addr + (alignment - 1)) & ~(alignment - 1);
}
static inline size_t align(size_t addr, size_t alignment)
{
assert(alignment > 0 && (alignment & (alignment - 1)) == 0);
return (addr + (alignment - 1)) & ~(alignment - 1);
}
@ -69,7 +59,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v)
{
#ifdef _MSC_VER
return __popcnt(v);
#elif defined(__GNUC__) || defined(__clang__)
#elif defined(HAVE_BUILTIN_POPCOUNT)
return __builtin_popcount(v);
#else
v -= (v >> 1) & 0x55555555;
@ -123,7 +113,8 @@ static inline unsigned int vkd3d_bitmask_tzcnt32(uint32_t mask)
{
#ifdef _MSC_VER
unsigned long result;
return _BitScanForward(&result, mask) ? result : 32;
_BitScanForward(&result, mask) ? result : 32;
return result;
#elif defined(__GNUC__) || defined(__clang__)
return mask ? __builtin_ctz(mask) : 32;
#else
@ -183,7 +174,7 @@ static inline unsigned int vkd3d_log2i(unsigned int x)
unsigned long result;
_BitScanReverse(&result, x);
return (unsigned int)result;
#elif defined(__GNUC__) || defined(__clang__)
#elif defined(HAVE_BUILTIN_CLZ)
return __builtin_clz(x) ^ 0x1f;
#else
static const unsigned int l[] =
@ -212,14 +203,6 @@ static inline unsigned int vkd3d_log2i(unsigned int x)
#endif
}
static inline unsigned int vkd3d_log2i_ceil(unsigned int x)
{
if (x == 1)
return 0;
else
return vkd3d_log2i(x - 1) + 1;
}
static inline int ascii_isupper(int c)
{
return 'A' <= c && c <= 'Z';
@ -248,19 +231,16 @@ static inline bool is_power_of_two(unsigned int x)
return x && !(x & (x -1));
}
static inline void vkd3d_parse_version(const char *version, int *major, int *minor, int *patch)
static inline void vkd3d_parse_version(const char *version, int *major, int *minor)
{
char *end;
*major = atoi(version);
*major = strtol(version, &end, 10);
version = end;
while (isdigit(*version))
++version;
if (*version == '.')
++version;
*minor = strtol(version, &end, 10);
version = end;
if (*version == '.')
++version;
*patch = strtol(version, NULL, 10);
*minor = atoi(version);
}
static inline uint32_t float_bits_to_uint32(float f)
@ -270,60 +250,25 @@ static inline uint32_t float_bits_to_uint32(float f)
return u;
}
static inline size_t vkd3d_wcslen(const WCHAR *wstr)
static inline size_t vkd3d_wcslen(const WCHAR *wstr, size_t wchar_size)
{
const uint16_t *data_16 = (const uint16_t*)wstr;
const uint32_t *data_32 = (const uint32_t*)wstr;
uint32_t curr_char;
size_t length = 0;
while (true)
{
if (!wstr[length])
if (wchar_size == sizeof(uint16_t))
curr_char = data_16[length];
else /* if (wchar_size == sizeof(uint32_t)) */
curr_char = data_32[length];
if (!curr_char)
return length;
length += 1;
}
}
static inline void *void_ptr_offset(void *ptr, size_t offset)
{
return ((char*)ptr) + offset;
}
#ifdef _MSC_VER
#define VKD3D_THREAD_LOCAL __declspec(thread)
#else
#define VKD3D_THREAD_LOCAL __thread
#endif
static inline uint64_t vkd3d_get_current_time_ns(void)
{
#ifdef _WIN32
LARGE_INTEGER li, lf;
uint64_t whole, part;
QueryPerformanceCounter(&li);
QueryPerformanceFrequency(&lf);
whole = (li.QuadPart / lf.QuadPart) * 1000000000;
part = ((li.QuadPart % lf.QuadPart) * 1000000000) / lf.QuadPart;
return whole + part;
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
return ts.tv_sec * 1000000000ll + ts.tv_nsec;
#endif
}
#ifdef _MSC_VER
#pragma intrinsic(__rdtsc)
#endif
static inline uint64_t vkd3d_get_current_time_ticks(void)
{
#ifdef _MSC_VER
return __rdtsc();
#elif defined(__i386__) || defined(__x86_64__)
return __builtin_ia32_rdtsc();
#else
return vkd3d_get_current_time_ns();
#endif
}
#endif /* __VKD3D_COMMON_H */

View File

@ -26,13 +26,13 @@
#include <stdint.h>
#ifdef VKD3D_NO_TRACE_MESSAGES
#define TRACE(...) do { } while (0)
#define TRACE(args...) do { } while (0)
#define TRACE_ON() (false)
#endif
#ifdef VKD3D_NO_DEBUG_MESSAGES
#define WARN(...) do { } while (0)
#define FIXME(...) do { } while (0)
#define WARN(args...) do { } while (0)
#define FIXME(args...) do { } while (0)
#endif
enum vkd3d_dbg_level
@ -40,7 +40,6 @@ enum vkd3d_dbg_level
VKD3D_DBG_LEVEL_UNKNOWN,
VKD3D_DBG_LEVEL_NONE,
VKD3D_DBG_LEVEL_ERR,
VKD3D_DBG_LEVEL_INFO,
VKD3D_DBG_LEVEL_FIXME,
VKD3D_DBG_LEVEL_WARN,
VKD3D_DBG_LEVEL_TRACE,
@ -57,15 +56,15 @@ enum vkd3d_dbg_channel
VKD3D_DBG_CHANNEL_COUNT
};
enum vkd3d_dbg_level vkd3d_dbg_get_level(enum vkd3d_dbg_channel channel);
enum vkd3d_dbg_level vkd3d_dbg_get_level(enum vkd3d_dbg_channel channel) DECLSPEC_HIDDEN;
void vkd3d_dbg_printf(enum vkd3d_dbg_channel channel, enum vkd3d_dbg_level level, const char *function,
const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);
const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5) DECLSPEC_HIDDEN;
const char *vkd3d_dbg_sprintf(const char *fmt, ...) VKD3D_PRINTF_FUNC(1, 2);
const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args);
const char *debugstr_a(const char *str);
const char *debugstr_w(const WCHAR *wstr);
const char *vkd3d_dbg_sprintf(const char *fmt, ...) VKD3D_PRINTF_FUNC(1, 2) DECLSPEC_HIDDEN;
const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args) DECLSPEC_HIDDEN;
const char *debugstr_a(const char *str) DECLSPEC_HIDDEN;
const char *debugstr_w(const WCHAR *wstr, size_t wchar_size) DECLSPEC_HIDDEN;
#define VKD3D_DBG_LOG(level) \
do { \
@ -98,7 +97,6 @@ const char *debugstr_w(const WCHAR *wstr);
#endif
#define ERR VKD3D_DBG_LOG(ERR)
#define INFO VKD3D_DBG_LOG(INFO)
#ifndef TRACE_ON
#define TRACE_ON() (vkd3d_dbg_get_level(VKD3D_DBG_CHANNEL) == VKD3D_DBG_LEVEL_TRACE)
@ -117,7 +115,7 @@ static inline const char *debugstr_guid(const GUID *guid)
guid->Data4[5], guid->Data4[6], guid->Data4[7]);
}
unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value);
unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value) DECLSPEC_HIDDEN;
struct vkd3d_debug_option
{
@ -125,8 +123,8 @@ struct vkd3d_debug_option
uint64_t flag;
};
bool vkd3d_debug_list_has_member(const char *string, const char *member);
bool vkd3d_debug_list_has_member(const char *string, const char *member) DECLSPEC_HIDDEN;
uint64_t vkd3d_parse_debug_options(const char *string,
const struct vkd3d_debug_option *options, unsigned int option_count);
const struct vkd3d_debug_option *options, unsigned int option_count) DECLSPEC_HIDDEN;
#endif /* __VKD3D_DEBUG_H */

View File

@ -1,119 +0,0 @@
/*
* Copyright 2021 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __VKD3D_DESCRIPTOR_QA_DATA_H
#define __VKD3D_DESCRIPTOR_QA_DATA_H
#include <stdint.h>
/* Data types which are used by shader backends when emitting code. */
enum vkd3d_descriptor_qa_flag_bits
{
VKD3D_DESCRIPTOR_QA_TYPE_NONE_BIT = 0,
VKD3D_DESCRIPTOR_QA_TYPE_SAMPLED_IMAGE_BIT = 1 << 0,
VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_IMAGE_BIT = 1 << 1,
VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_BUFFER_BIT = 1 << 2,
VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT = 1 << 3,
VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_TEXEL_BUFFER_BIT = 1 << 4,
VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_TEXEL_BUFFER_BIT = 1 << 5,
VKD3D_DESCRIPTOR_QA_TYPE_RT_ACCELERATION_STRUCTURE_BIT = 1 << 6,
VKD3D_DESCRIPTOR_QA_TYPE_SAMPLER_BIT = 1 << 7,
VKD3D_DESCRIPTOR_QA_TYPE_RAW_VA_BIT = 1 << 8
};
typedef uint32_t vkd3d_descriptor_qa_flags;
struct vkd3d_descriptor_qa_cookie_descriptor
{
uint32_t cookie;
uint32_t descriptor_type;
};
enum vkd3d_descriptor_debug_fault_type
{
VKD3D_DESCRIPTOR_FAULT_TYPE_HEAP_OF_OF_RANGE = 1 << 0,
VKD3D_DESCRIPTOR_FAULT_TYPE_MISMATCH_DESCRIPTOR_TYPE = 1 << 1,
VKD3D_DESCRIPTOR_FAULT_TYPE_DESTROYED_RESOURCE = 1 << 2
};
/* Physical layout of QA buffer. */
struct vkd3d_descriptor_qa_global_buffer_data
{
uint64_t failed_hash;
uint32_t failed_offset;
uint32_t failed_heap;
uint32_t failed_cookie;
uint32_t fault_atomic;
uint32_t failed_instruction;
uint32_t failed_descriptor_type_mask;
uint32_t actual_descriptor_type_mask;
uint32_t fault_type;
uint32_t live_status_table[];
};
/* Physical layout of QA heap buffer. */
struct vkd3d_descriptor_qa_heap_buffer_data
{
uint32_t num_descriptors;
uint32_t heap_index;
struct vkd3d_descriptor_qa_cookie_descriptor desc[];
};
enum vkd3d_descriptor_qa_heap_buffer_data_member
{
VKD3D_DESCRIPTOR_QA_HEAP_MEMBER_NUM_DESCRIPTORS = 0,
VKD3D_DESCRIPTOR_QA_HEAP_MEMBER_HEAP_INDEX,
VKD3D_DESCRIPTOR_QA_HEAP_MEMBER_DESC,
VKD3D_DESCRIPTOR_QA_HEAP_MEMBER_COUNT
};
VKD3D_UNUSED static const char *vkd3d_descriptor_qa_heap_data_names[VKD3D_DESCRIPTOR_QA_HEAP_MEMBER_COUNT] = {
"num_descriptors",
"heap_index",
"desc",
};
enum vkd3d_descriptor_qa_global_buffer_data_member
{
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_FAILED_HASH = 0,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_FAILED_OFFSET,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_FAILED_HEAP,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_FAILED_COOKIE,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_FAULT_ATOMIC,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_FAILED_INSTRUCTION,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_FAILED_DESCRIPTOR_TYPE_MASK,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_ACTUAL_DESCRIPTOR_TYPE_MASK,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_FAULT_TYPE,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_LIVE_STATUS_TABLE,
VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_COUNT
};
VKD3D_UNUSED static const char *vkd3d_descriptor_qa_global_buffer_data_names[VKD3D_DESCRIPTOR_QA_GLOBAL_BUFFER_DATA_MEMBER_COUNT] = {
"failed_hash",
"failed_offset",
"failed_heap",
"failed_cookie",
"fault_atomic",
"failed_instruction",
"failed_descriptor_type_mask",
"actual_descriptor_type_mask",
"fault_type",
"live_status_table",
};
#endif

View File

@ -1,42 +0,0 @@
/*
* Copyright 2022 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __VKD3D_FILE_UTILS_H
#define __VKD3D_FILE_UTILS_H
#include <stddef.h>
#include <stdio.h>
#include <stdbool.h>
struct vkd3d_memory_mapped_file
{
void *mapped;
size_t mapped_size;
};
/* On failure, ensures the struct is cleared to zero.
* A reference to the file is kept through the memory mapping. */
bool vkd3d_file_map_read_only(const char *path, struct vkd3d_memory_mapped_file *file);
/* Clears out file on unmap. */
void vkd3d_file_unmap(struct vkd3d_memory_mapped_file *file);
bool vkd3d_file_rename_overwrite(const char *from_path, const char *to_path);
bool vkd3d_file_rename_no_replace(const char *from_path, const char *to_path);
bool vkd3d_file_delete(const char *path);
FILE *vkd3d_file_open_exclusive_write(const char *path);
#endif

View File

@ -23,7 +23,6 @@
#include <stdbool.h>
#include <stdlib.h>
#include "vkd3d_common.h"
#include "vkd3d_debug.h"
static inline void *vkd3d_malloc(size_t size)
@ -56,24 +55,6 @@ static inline void vkd3d_free(void *ptr)
}
bool vkd3d_array_reserve(void **elements, size_t *capacity,
size_t element_count, size_t element_size);
static inline void *vkd3d_malloc_aligned(size_t size, size_t alignment)
{
#ifdef _WIN32
return _aligned_malloc(size, alignment);
#else
return aligned_alloc(alignment, align(size, alignment));
#endif
}
static inline void vkd3d_free_aligned(void *ptr)
{
#ifdef _WIN32
_aligned_free(ptr);
#else
free(ptr);
#endif
}
size_t element_count, size_t element_size) DECLSPEC_HIDDEN;
#endif /* __VKD3D_MEMORY_H */

View File

@ -29,16 +29,14 @@
typedef void* vkd3d_module_t;
vkd3d_module_t vkd3d_dlopen(const char *name);
vkd3d_module_t vkd3d_dlopen(const char *name) DECLSPEC_HIDDEN;
void *vkd3d_dlsym(vkd3d_module_t handle, const char *symbol);
void *vkd3d_dlsym(vkd3d_module_t handle, const char *symbol) DECLSPEC_HIDDEN;
int vkd3d_dlclose(vkd3d_module_t handle);
int vkd3d_dlclose(vkd3d_module_t handle) DECLSPEC_HIDDEN;
const char *vkd3d_dlerror(void);
const char *vkd3d_dlerror(void) DECLSPEC_HIDDEN;
bool vkd3d_get_env_var(const char *name, char *value, size_t value_size);
bool vkd3d_get_program_name(char program_name[VKD3D_PATH_MAX]) DECLSPEC_HIDDEN;
bool vkd3d_get_program_name(char program_name[VKD3D_PATH_MAX]);
#endif
#endif

View File

@ -21,14 +21,38 @@
#include "vkd3d_windows.h"
#include "vkd3d_spinlock.h"
#include "vkd3d_common.h"
#include <stdint.h>
#ifdef VKD3D_ENABLE_PROFILING
void vkd3d_init_profiling(void);
bool vkd3d_uses_profiling(void);
unsigned int vkd3d_profiling_register_region(const char *name, spinlock_t *lock, uint32_t *latch);
void vkd3d_profiling_notify_work(unsigned int index, uint64_t start_ticks, uint64_t end_ticks, unsigned int iteration_count);
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <time.h>
#endif
void vkd3d_init_profiling(void) DECLSPEC_HIDDEN;
bool vkd3d_uses_profiling(void) DECLSPEC_HIDDEN;
unsigned int vkd3d_profiling_register_region(const char *name, spinlock_t *lock, uint32_t *latch) DECLSPEC_HIDDEN;
void vkd3d_profiling_notify_work(unsigned int index, uint64_t start_ticks, uint64_t end_ticks, unsigned int iteration_count) DECLSPEC_HIDDEN;
static inline uint64_t vkd3d_profiling_get_tick_count(void)
{
#ifdef _WIN32
LARGE_INTEGER li, lf;
uint64_t whole, part;
QueryPerformanceCounter(&li);
QueryPerformanceFrequency(&lf);
whole = (li.QuadPart / lf.QuadPart) * 1000000000;
part = ((li.QuadPart % lf.QuadPart) * 1000000000) / lf.QuadPart;
return whole + part;
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
return ts.tv_sec * 1000000000ll + ts.tv_nsec;
#endif
}
#define VKD3D_REGION_DECL(name) \
static uint32_t _vkd3d_region_latch_##name; \
@ -41,12 +65,12 @@ void vkd3d_profiling_notify_work(unsigned int index, uint64_t start_ticks, uint6
do { \
if (!(_vkd3d_region_index_##name = vkd3d_atomic_uint32_load_explicit(&_vkd3d_region_latch_##name, vkd3d_memory_order_acquire))) \
_vkd3d_region_index_##name = vkd3d_profiling_register_region(#name, &_vkd3d_region_lock_##name, &_vkd3d_region_latch_##name); \
_vkd3d_region_begin_tick_##name = vkd3d_get_current_time_ticks(); \
_vkd3d_region_begin_tick_##name = vkd3d_profiling_get_tick_count(); \
} while(0)
#define VKD3D_REGION_END_ITERATIONS(name, iter) \
do { \
_vkd3d_region_end_tick_##name = vkd3d_get_current_time_ticks(); \
_vkd3d_region_end_tick_##name = vkd3d_profiling_get_tick_count(); \
vkd3d_profiling_notify_work(_vkd3d_region_index_##name, _vkd3d_region_begin_tick_##name, _vkd3d_region_end_tick_##name, iter); \
} while(0)

View File

@ -1,59 +0,0 @@
/*
* Copyright 2020 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __VKD3D_RW_SPINLOCK_H
#define __VKD3D_RW_SPINLOCK_H
#include "vkd3d_spinlock.h"
#define VKD3D_RW_SPINLOCK_WRITE 1u
#define VKD3D_RW_SPINLOCK_READ 2u
#define VKD3D_RW_SPINLOCK_IDLE 0u
static inline void rw_spinlock_acquire_read(spinlock_t *spinlock)
{
uint32_t count = vkd3d_atomic_uint32_add(spinlock, VKD3D_RW_SPINLOCK_READ, vkd3d_memory_order_acquire);
while (count & VKD3D_RW_SPINLOCK_WRITE)
{
vkd3d_pause();
count = vkd3d_atomic_uint32_load_explicit(spinlock, vkd3d_memory_order_acquire);
}
}
static inline void rw_spinlock_release_read(spinlock_t *spinlock)
{
vkd3d_atomic_uint32_sub(spinlock, VKD3D_RW_SPINLOCK_READ, vkd3d_memory_order_release);
}
static inline void rw_spinlock_acquire_write(spinlock_t *spinlock)
{
while (vkd3d_atomic_uint32_load_explicit(spinlock, vkd3d_memory_order_relaxed) != VKD3D_RW_SPINLOCK_IDLE ||
vkd3d_atomic_uint32_compare_exchange(spinlock,
VKD3D_RW_SPINLOCK_IDLE, VKD3D_RW_SPINLOCK_WRITE,
vkd3d_memory_order_acquire, vkd3d_memory_order_relaxed) != VKD3D_RW_SPINLOCK_IDLE)
{
vkd3d_pause();
}
}
static inline void rw_spinlock_release_write(spinlock_t *spinlock)
{
vkd3d_atomic_uint32_and(spinlock, ~VKD3D_RW_SPINLOCK_WRITE, vkd3d_memory_order_release);
}
#endif

View File

@ -28,13 +28,6 @@
#include <emmintrin.h>
#endif
static inline void vkd3d_pause(void)
{
#ifdef __SSE2__
_mm_pause();
#endif
}
#define vkd3d_spinlock_try_lock(lock) \
(!vkd3d_atomic_uint32_load_explicit(lock, vkd3d_memory_order_relaxed) && \
!vkd3d_atomic_uint32_exchange_explicit(lock, 1u, vkd3d_memory_order_acquire))
@ -56,7 +49,11 @@ static inline bool spinlock_try_acquire(spinlock_t *lock)
static inline void spinlock_acquire(spinlock_t *lock)
{
while (!spinlock_try_acquire(lock))
vkd3d_pause();
#ifdef __SSE2__
_mm_pause();
#else
continue;
#endif
}
static inline void spinlock_release(spinlock_t *lock)

View File

@ -1,82 +0,0 @@
/*
* Copyright 2021 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __VKD3D_STRING_H
#define __VKD3D_STRING_H
#include "vkd3d_common.h"
#include <stddef.h>
/* Various string utilities. */
WCHAR *vkd3d_dup_entry_point(const char *str);
WCHAR *vkd3d_dup_entry_point_n(const char *str, size_t len);
WCHAR *vkd3d_dup_demangled_entry_point(const char *str);
char *vkd3d_dup_demangled_entry_point_ascii(const char *str);
bool vkd3d_export_strequal(const WCHAR *a, const WCHAR *b);
bool vkd3d_export_strequal_mixed(const WCHAR *a, const char *b);
bool vkd3d_export_strequal_substr(const WCHAR *a, size_t n, const WCHAR *b);
char *vkd3d_strdup(const char *str);
char *vkd3d_strdup_n(const char *str, size_t n);
WCHAR *vkd3d_wstrdup(const WCHAR *str);
WCHAR *vkd3d_wstrdup_n(const WCHAR *str, size_t n);
static inline bool vkd3d_string_ends_with_n(const char *str, size_t str_len, const char *ending, size_t ending_len)
{
return str_len >= ending_len && !strncmp(str + (str_len - ending_len), ending, ending_len);
}
static inline bool vkd3d_string_ends_with(const char *str, const char *ending)
{
return vkd3d_string_ends_with_n(str, strlen(str), ending, strlen(ending));
}
enum vkd3d_string_compare_mode
{
VKD3D_STRING_COMPARE_NEVER,
VKD3D_STRING_COMPARE_ALWAYS,
VKD3D_STRING_COMPARE_EXACT,
VKD3D_STRING_COMPARE_STARTS_WITH,
VKD3D_STRING_COMPARE_ENDS_WITH,
VKD3D_STRING_COMPARE_CONTAINS,
};
static inline bool vkd3d_string_compare(enum vkd3d_string_compare_mode mode, const char *string, const char *comparator)
{
switch (mode)
{
default:
case VKD3D_STRING_COMPARE_NEVER:
return false;
case VKD3D_STRING_COMPARE_ALWAYS:
return true;
case VKD3D_STRING_COMPARE_EXACT:
return !strcmp(string, comparator);
case VKD3D_STRING_COMPARE_STARTS_WITH:
return !strncmp(string, comparator, strlen(comparator));
case VKD3D_STRING_COMPARE_ENDS_WITH:
return vkd3d_string_ends_with(string, comparator);
case VKD3D_STRING_COMPARE_CONTAINS:
return strstr(string, comparator) != NULL;
}
}
#endif /* __VKD3D_STRING_H */

View File

@ -20,7 +20,6 @@
#define __VKD3D_TEST_H
#include "vkd3d_common.h"
#include "vkd3d_debug.h"
#include <assert.h>
#include <inttypes.h>
#include <stdarg.h>
@ -29,19 +28,16 @@
#include <stdlib.h>
#include <string.h>
#ifdef VKD3D_TEST_DECLARE_MAIN
static void vkd3d_test_main(int argc, char **argv);
#endif
extern const char *vkd3d_test_name;
extern const char *vkd3d_test_platform;
static const char *vkd3d_test_name;
static const char *vkd3d_test_platform = "other";
static void vkd3d_test_start_todo(bool is_todo);
static int vkd3d_test_loop_todo(void);
static void vkd3d_test_end_todo(void);
#define START_TEST(name) \
const char *vkd3d_test_name = #name; \
static const char *vkd3d_test_name = #name; \
static void vkd3d_test_main(int argc, char **argv)
/*
@ -104,7 +100,7 @@ static void vkd3d_test_end_todo(void);
#define todo todo_if(true)
struct vkd3d_test_state_context
static struct
{
LONG success_count;
LONG failure_count;
@ -123,10 +119,8 @@ struct vkd3d_test_state_context
bool bug_enabled;
const char *test_name_filter;
const char *test_exclude_list;
char context[1024];
};
extern struct vkd3d_test_state_context vkd3d_test_state;
} vkd3d_test_state;
static bool
vkd3d_test_platform_is_windows(void)
@ -251,7 +245,7 @@ vkd3d_test_debug(const char *fmt, ...)
int size;
size = snprintf(buffer, sizeof(buffer), "%s: ", vkd3d_test_name);
if (0 < size && size < (int)sizeof(buffer))
if (0 < size && size < sizeof(buffer))
{
va_start(args, fmt);
vsnprintf(buffer + size, sizeof(buffer) - size, fmt, args);
@ -270,20 +264,17 @@ vkd3d_test_debug(const char *fmt, ...)
}
}
#ifdef VKD3D_TEST_DECLARE_MAIN
int main(int argc, char **argv)
{
const char *exclude_list = getenv("VKD3D_TEST_EXCLUDE");
const char *test_filter = getenv("VKD3D_TEST_FILTER");
const char *debug_level = getenv("VKD3D_TEST_DEBUG");
char *test_platform = getenv("VKD3D_TEST_PLATFORM");
const char *bug = getenv("VKD3D_TEST_BUG");
memset(&vkd3d_test_state, 0, sizeof(vkd3d_test_state));
vkd3d_test_state.debug_level = debug_level ? atoi(debug_level) : 1;
vkd3d_test_state.debug_level = debug_level ? atoi(debug_level) : 0;
vkd3d_test_state.bug_enabled = bug ? atoi(bug) : true;
vkd3d_test_state.test_name_filter = test_filter;
vkd3d_test_state.test_exclude_list = exclude_list;
if (test_platform)
{
@ -296,13 +287,13 @@ int main(int argc, char **argv)
vkd3d_test_main(argc, argv);
printf("%s: %lu tests executed (%lu failures, %lu successful todo, %lu skipped, %lu todo, %lu bugs).\n",
printf("%s: %lu tests executed (%lu failures, %lu skipped, %lu todo, %lu bugs).\n",
vkd3d_test_name,
(unsigned long)(vkd3d_test_state.success_count
+ vkd3d_test_state.failure_count + vkd3d_test_state.todo_count
+ vkd3d_test_state.todo_success_count),
(unsigned long)vkd3d_test_state.failure_count,
(unsigned long)vkd3d_test_state.todo_success_count,
(unsigned long)(vkd3d_test_state.failure_count
+ vkd3d_test_state.todo_success_count),
(unsigned long)vkd3d_test_state.skip_count,
(unsigned long)vkd3d_test_state.todo_count,
(unsigned long)vkd3d_test_state.bug_count);
@ -311,7 +302,7 @@ int main(int argc, char **argv)
free(test_platform);
fflush(stdout);
return vkd3d_test_state.failure_count != 0;
return vkd3d_test_state.failure_count || vkd3d_test_state.todo_success_count;
}
#ifdef _WIN32
@ -360,27 +351,16 @@ int wmain(int argc, WCHAR **wargv)
return ret;
}
#endif /* _WIN32 */
#endif /* VKD3D_TEST_DECLARE_MAIN */
typedef void (*vkd3d_test_pfn)(void);
static inline void vkd3d_run_test(const char *name, vkd3d_test_pfn test_pfn)
{
const char *old_test_name;
if (vkd3d_test_state.test_name_filter && !strstr(name, vkd3d_test_state.test_name_filter))
return;
if (vkd3d_test_state.test_exclude_list
&& vkd3d_debug_list_has_member(vkd3d_test_state.test_exclude_list, name))
return;
old_test_name = vkd3d_test_name;
vkd3d_test_debug("======== %s begin ========", name);
vkd3d_test_name = name;
vkd3d_test_debug("%s", name);
test_pfn();
vkd3d_test_name = old_test_name;
vkd3d_test_debug("======== %s end ==========", name);
}
static inline void vkd3d_test_start_todo(bool is_todo)

View File

@ -43,16 +43,12 @@ typedef struct pthread_mutex
SRWLOCK lock;
} pthread_mutex_t;
#define PTHREAD_MUTEX_INITIALIZER {SRWLOCK_INIT}
/* pthread_cond_t is not copyable, so embed CV inline. */
typedef struct pthread_cond
{
CONDITION_VARIABLE cond;
} pthread_cond_t;
typedef pthread_cond_t condvar_reltime_t;
static DWORD WINAPI win32_thread_wrapper_routine(void *arg)
{
pthread_t thread = arg;
@ -81,9 +77,8 @@ static inline int pthread_create(pthread_t *out_thread, void *attr, void * (*thr
static inline int pthread_join(pthread_t thread, void **ret)
{
int success;
(void)ret;
success = WaitForSingleObject(thread->thread, INFINITE) == WAIT_OBJECT_0;
int success = WaitForSingleObject(thread->thread, INFINITE) == WAIT_OBJECT_0;
if (success)
{
CloseHandle(thread->thread);
@ -116,48 +111,6 @@ static inline int pthread_mutex_destroy(pthread_mutex_t *lock)
return 0;
}
/* SRWLocks distinguish between write and read unlocks, but pthread interface does not,
* so make a trivial wrapper type instead to avoid any possible API conflicts. */
typedef struct rwlock
{
SRWLOCK rwlock;
} rwlock_t;
static inline int rwlock_init(rwlock_t *lock)
{
InitializeSRWLock(&lock->rwlock);
return 0;
}
static inline int rwlock_lock_write(rwlock_t *lock)
{
AcquireSRWLockExclusive(&lock->rwlock);
return 0;
}
static inline int rwlock_lock_read(rwlock_t *lock)
{
AcquireSRWLockShared(&lock->rwlock);
return 0;
}
static inline int rwlock_unlock_write(rwlock_t *lock)
{
ReleaseSRWLockExclusive(&lock->rwlock);
return 0;
}
static inline int rwlock_unlock_read(rwlock_t *lock)
{
ReleaseSRWLockShared(&lock->rwlock);
return 0;
}
static inline int rwlock_destroy(rwlock_t *lock)
{
return 0;
}
static inline int pthread_cond_init(pthread_cond_t *cond, void *attr)
{
(void)attr;
@ -189,32 +142,6 @@ static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *lock)
return ret ? 0 : -1;
}
static inline int condvar_reltime_init(condvar_reltime_t *cond)
{
return pthread_cond_init(cond, NULL);
}
static inline int condvar_reltime_destroy(condvar_reltime_t *cond)
{
return pthread_cond_destroy(cond);
}
static inline int condvar_reltime_signal(condvar_reltime_t *cond)
{
return pthread_cond_signal(cond);
}
static inline int condvar_reltime_wait_timeout_seconds(condvar_reltime_t *cond, pthread_mutex_t *lock, unsigned int seconds)
{
BOOL ret = SleepConditionVariableSRW(&cond->cond, &lock->lock, seconds * 1000, 0);
if (ret)
return 0;
else if (GetLastError() == ERROR_TIMEOUT)
return 1;
else
return -1;
}
static inline void vkd3d_set_thread_name(const char *name)
{
(void)name;
@ -225,9 +152,9 @@ typedef INIT_ONCE pthread_once_t;
static inline BOOL CALLBACK pthread_once_wrapper(PINIT_ONCE once, PVOID parameter, PVOID *context)
{
void (*func)(void) = parameter;
(void)once;
(void)context;
void (*func)(void) = parameter;
func();
return TRUE;
}
@ -238,96 +165,10 @@ static inline void pthread_once(pthread_once_t *once, void (*func)(void))
}
#else
#include <pthread.h>
#include <errno.h>
#include <time.h>
static inline void vkd3d_set_thread_name(const char *name)
{
pthread_setname_np(pthread_self(), name);
}
typedef struct rwlock
{
pthread_rwlock_t rwlock;
} rwlock_t;
static inline int rwlock_init(rwlock_t *lock)
{
return pthread_rwlock_init(&lock->rwlock, NULL);
}
static inline int rwlock_lock_write(rwlock_t *lock)
{
return pthread_rwlock_wrlock(&lock->rwlock);
}
static inline int rwlock_lock_read(rwlock_t *lock)
{
return pthread_rwlock_rdlock(&lock->rwlock);
}
static inline int rwlock_unlock_write(rwlock_t *lock)
{
return pthread_rwlock_unlock(&lock->rwlock);
}
static inline int rwlock_unlock_read(rwlock_t *lock)
{
return pthread_rwlock_unlock(&lock->rwlock);
}
static inline int rwlock_destroy(rwlock_t *lock)
{
return pthread_rwlock_destroy(&lock->rwlock);
}
typedef struct condvar_reltime
{
pthread_cond_t cond;
} condvar_reltime_t;
static inline int condvar_reltime_init(condvar_reltime_t *cond)
{
pthread_condattr_t attr;
int rc;
pthread_condattr_init(&attr);
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
rc = pthread_cond_init(&cond->cond, &attr);
pthread_condattr_destroy(&attr);
return rc;
}
static inline void condvar_reltime_destroy(condvar_reltime_t *cond)
{
pthread_cond_destroy(&cond->cond);
}
static inline int condvar_reltime_signal(condvar_reltime_t *cond)
{
return pthread_cond_signal(&cond->cond);
}
static inline int condvar_reltime_wait_timeout_seconds(condvar_reltime_t *cond, pthread_mutex_t *lock, unsigned int seconds)
{
struct timespec ts;
int rc;
clock_gettime(CLOCK_MONOTONIC, &ts);
ts.tv_sec += seconds;
/* This is absolute time. */
rc = pthread_cond_timedwait(&cond->cond, lock, &ts);
if (rc == ETIMEDOUT)
return 1;
else if (rc == 0)
return 0;
else
return -1;
}
#define PTHREAD_ONCE_CALLBACK
#endif

View File

@ -23,6 +23,6 @@
/* max_elements is 0 if only nul-terminator should be used.
* Otherwise, terminate the string after either a nul-termination byte or max_elements. */
char *vkd3d_strdup_w_utf8(const WCHAR *wstr, size_t max_elements);
char *vkd3d_strdup_w_utf8(const WCHAR *wstr, size_t wchar_size, size_t max_elements) DECLSPEC_HIDDEN;
#endif /* __VKD3D_UTF8_H */

View File

@ -1,6 +0,0 @@
#ifndef __VULKAN_PRIVATE_EXTENSIONS_H__
#define __VULKAN_PRIVATE_EXTENSIONS_H__
/* Nothing here at the moment. Add hacks here! */
#endif

View File

@ -1,71 +0,0 @@
INCLUDE_DIR := $(CURDIR)
VERT_SOURCES := $(wildcard $(M)/*.vert)
FRAG_SOURCES := $(wildcard $(M)/*.frag)
COMP_SOURCES := $(wildcard $(M)/*.comp)
TESC_SOURCES := $(wildcard $(M)/*.tesc)
TESE_SOURCES := $(wildcard $(M)/*.tese)
GEOM_SOURCES := $(wildcard $(M)/*.geom)
RGEN_SOURCES := $(wildcard $(M)/*.rgen)
RINT_SOURCES := $(wildcard $(M)/*.rint)
RAHIT_SOURCES := $(wildcard $(M)/*.rahit)
RCHIT_SOURCES := $(wildcard $(M)/*.rchit)
RMISS_SOURCES := $(wildcard $(M)/*.rmiss)
RCALL_SOURCES := $(wildcard $(M)/*.rcall)
SPV_OBJECTS := \
$(VERT_SOURCES:.vert=.spv) \
$(FRAG_SOURCES:.frag=.spv) \
$(COMP_SOURCES:.comp=.spv) \
$(TESC_SOURCES:.tesc=.spv) \
$(TESE_SOURCES:.tese=.spv) \
$(GEOM_SOURCES:.geom=.spv) \
$(RGEN_SOURCES:.rgen=.spv) \
$(RINT_SOURCES:.rint=.spv) \
$(RAHIT_SOURCES:.rahit=.spv) \
$(RCHIT_SOURCES:.rchit=.spv) \
$(RMISS_SOURCES:.rmiss=.spv) \
$(RCALL_SOURCES:.rcall=.spv)
%.spv: %.vert
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 $(GLSLC_FLAGS)
%.spv: %.frag
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 -DDEBUG_CHANNEL_HELPER_LANES $(GLSLC_FLAGS)
%.spv: %.comp
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 $(GLSLC_FLAGS)
%.spv: %.geom
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 $(GLSLC_FLAGS)
%.spv: %.tesc
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 $(GLSLC_FLAGS)
%.spv: %.tese
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 $(GLSLC_FLAGS)
%.spv: %.rgen
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 --target-spv=spv1.4 $(GLSLC_FLAGS)
%.spv: %.rint
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 --target-spv=spv1.4 $(GLSLC_FLAGS)
%.spv: %.rahit
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 --target-spv=spv1.4 $(GLSLC_FLAGS)
%.spv: %.rchit
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 --target-spv=spv1.4 $(GLSLC_FLAGS)
%.spv: %.rmiss
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 --target-spv=spv1.4 $(GLSLC_FLAGS)
%.spv: %.rcall
glslc -o $@ $< -I$(INCLUDE_DIR) --target-env=vulkan1.1 --target-spv=spv1.4 $(GLSLC_FLAGS)
all: $(SPV_OBJECTS)
clean:
rm -f $(SPV_OBJECTS)
.PHONY: clean

View File

@ -23,17 +23,14 @@
#extension GL_ARB_gpu_shader_int64 : require
#extension GL_KHR_shader_subgroup_basic : require
#extension GL_KHR_shader_subgroup_ballot : require
#ifdef DEBUG_CHANNEL_HELPER_LANES
#extension GL_EXT_demote_to_helper_invocation : require
#endif
layout(buffer_reference, std430, buffer_reference_align = 4) coherent buffer ControlBlock
layout(buffer_reference, std430, buffer_reference_align = 4) buffer ControlBlock
{
uint message_counter;
uint instance_counter;
};
layout(buffer_reference, std430, buffer_reference_align = 4) coherent buffer RingBuffer
layout(buffer_reference, std430, buffer_reference_align = 4) buffer RingBuffer
{
uint data[];
};
@ -51,73 +48,24 @@ const uint DEBUG_CHANNEL_FMT_F32 = 2;
const uint DEBUG_CHANNEL_FMT_HEX_ALL = DEBUG_CHANNEL_FMT_HEX * 0x55555555u;
const uint DEBUG_CHANNEL_FMT_I32_ALL = DEBUG_CHANNEL_FMT_I32 * 0x55555555u;
const uint DEBUG_CHANNEL_FMT_F32_ALL = DEBUG_CHANNEL_FMT_F32 * 0x55555555u;
const uint DEBUG_CHANNEL_WORD_COOKIE = 0xdeadca70u; /* Let host fish for this cookie in device lost scenarios. */
uint DEBUG_CHANNEL_INSTANCE_COUNTER;
uvec3 DEBUG_CHANNEL_ID;
/* Need to make sure the elected subgroup can have side effects. */
#ifdef DEBUG_CHANNEL_HELPER_LANES
bool DEBUG_CHANNEL_ELECT()
{
bool elected = false;
if (!helperInvocationEXT())
elected = subgroupElect();
return elected;
}
#else
bool DEBUG_CHANNEL_ELECT()
{
return subgroupElect();
}
#endif
void DEBUG_CHANNEL_INIT(uvec3 id)
{
if (!DEBUG_SHADER_RING_ACTIVE)
return;
DEBUG_CHANNEL_ID = id;
uint inst;
#ifdef DEBUG_CHANNEL_HELPER_LANES
if (!helperInvocationEXT())
{
/* Elect and broadcast must happen without helper lanes here.
* We must perform the instance increment with side effects,
* and broadcast first must pick the elected lane. */
if (subgroupElect())
inst = atomicAdd(ControlBlock(DEBUG_SHADER_ATOMIC_BDA).instance_counter, 1u);
DEBUG_CHANNEL_INSTANCE_COUNTER = subgroupBroadcastFirst(inst);
}
/* Helper lanes cannot write debug messages, since they cannot have side effects.
* Leave it undefined, and we should ensure SGPR propagation either way ... */
#else
if (DEBUG_CHANNEL_ELECT())
if (subgroupElect())
inst = atomicAdd(ControlBlock(DEBUG_SHADER_ATOMIC_BDA).instance_counter, 1u);
DEBUG_CHANNEL_INSTANCE_COUNTER = subgroupBroadcastFirst(inst);
#endif
}
void DEBUG_CHANNEL_INIT_IMPLICIT_INSTANCE(uvec3 id, uint inst)
{
if (!DEBUG_SHADER_RING_ACTIVE)
return;
DEBUG_CHANNEL_ID = id;
DEBUG_CHANNEL_INSTANCE_COUNTER = inst;
}
void DEBUG_CHANNEL_UNLOCK_MESSAGE(RingBuffer buf, uint offset, uint num_words)
{
memoryBarrierBuffer();
/* Make sure this word is made visible last. This way the ring thread can avoid reading bogus messages.
* If the host thread observed a num_word of 0, we know a message was allocated, but we don't necessarily
* have a complete write yet.
* In a device lost scenario, we can try to fish for valid messages. */
buf.data[(offset + 0) & DEBUG_SHADER_RING_MASK] = num_words | DEBUG_CHANNEL_WORD_COOKIE;
memoryBarrierBuffer();
}
void DEBUG_CHANNEL_WRITE_HEADER(RingBuffer buf, uint offset, uint fmt)
void DEBUG_CHANNEL_WRITE_HEADER(RingBuffer buf, uint offset, uint num_words, uint fmt)
{
buf.data[(offset + 0) & DEBUG_SHADER_RING_MASK] = num_words;
buf.data[(offset + 1) & DEBUG_SHADER_RING_MASK] = uint(DEBUG_SHADER_HASH);
buf.data[(offset + 2) & DEBUG_SHADER_RING_MASK] = uint(DEBUG_SHADER_HASH >> 32);
buf.data[(offset + 3) & DEBUG_SHADER_RING_MASK] = DEBUG_CHANNEL_INSTANCE_COUNTER;
@ -139,9 +87,7 @@ void DEBUG_CHANNEL_MSG_()
return;
uint words = 8;
uint offset = DEBUG_CHANNEL_ALLOCATE(words);
RingBuffer buf = RingBuffer(DEBUG_SHADER_RING_BDA);
DEBUG_CHANNEL_WRITE_HEADER(buf, offset, 0);
DEBUG_CHANNEL_UNLOCK_MESSAGE(buf, offset, words);
DEBUG_CHANNEL_WRITE_HEADER(RingBuffer(DEBUG_SHADER_RING_BDA), offset, words, 0);
}
void DEBUG_CHANNEL_MSG_(uint fmt, uint v0)
@ -151,9 +97,8 @@ void DEBUG_CHANNEL_MSG_(uint fmt, uint v0)
RingBuffer buf = RingBuffer(DEBUG_SHADER_RING_BDA);
uint words = 9;
uint offset = DEBUG_CHANNEL_ALLOCATE(words);
DEBUG_CHANNEL_WRITE_HEADER(buf, offset, fmt);
DEBUG_CHANNEL_WRITE_HEADER(buf, offset, words, fmt);
buf.data[(offset + 8) & DEBUG_SHADER_RING_MASK] = v0;
DEBUG_CHANNEL_UNLOCK_MESSAGE(buf, offset, words);
}
void DEBUG_CHANNEL_MSG_(uint fmt, uint v0, uint v1)
@ -163,10 +108,9 @@ void DEBUG_CHANNEL_MSG_(uint fmt, uint v0, uint v1)
RingBuffer buf = RingBuffer(DEBUG_SHADER_RING_BDA);
uint words = 10;
uint offset = DEBUG_CHANNEL_ALLOCATE(words);
DEBUG_CHANNEL_WRITE_HEADER(buf, offset, fmt);
DEBUG_CHANNEL_WRITE_HEADER(buf, offset, words, fmt);
buf.data[(offset + 8) & DEBUG_SHADER_RING_MASK] = v0;
buf.data[(offset + 9) & DEBUG_SHADER_RING_MASK] = v1;
DEBUG_CHANNEL_UNLOCK_MESSAGE(buf, offset, words);
}
void DEBUG_CHANNEL_MSG_(uint fmt, uint v0, uint v1, uint v2)
@ -176,11 +120,10 @@ void DEBUG_CHANNEL_MSG_(uint fmt, uint v0, uint v1, uint v2)
RingBuffer buf = RingBuffer(DEBUG_SHADER_RING_BDA);
uint words = 11;
uint offset = DEBUG_CHANNEL_ALLOCATE(words);
DEBUG_CHANNEL_WRITE_HEADER(buf, offset, fmt);
DEBUG_CHANNEL_WRITE_HEADER(buf, offset, words, fmt);
buf.data[(offset + 8) & DEBUG_SHADER_RING_MASK] = v0;
buf.data[(offset + 9) & DEBUG_SHADER_RING_MASK] = v1;
buf.data[(offset + 10) & DEBUG_SHADER_RING_MASK] = v2;
DEBUG_CHANNEL_UNLOCK_MESSAGE(buf, offset, words);
}
void DEBUG_CHANNEL_MSG_(uint fmt, uint v0, uint v1, uint v2, uint v3)
@ -190,12 +133,11 @@ void DEBUG_CHANNEL_MSG_(uint fmt, uint v0, uint v1, uint v2, uint v3)
RingBuffer buf = RingBuffer(DEBUG_SHADER_RING_BDA);
uint words = 12;
uint offset = DEBUG_CHANNEL_ALLOCATE(words);
DEBUG_CHANNEL_WRITE_HEADER(buf, offset, fmt);
DEBUG_CHANNEL_WRITE_HEADER(buf, offset, words, fmt);
buf.data[(offset + 8) & DEBUG_SHADER_RING_MASK] = v0;
buf.data[(offset + 9) & DEBUG_SHADER_RING_MASK] = v1;
buf.data[(offset + 10) & DEBUG_SHADER_RING_MASK] = v2;
buf.data[(offset + 11) & DEBUG_SHADER_RING_MASK] = v3;
DEBUG_CHANNEL_UNLOCK_MESSAGE(buf, offset, words);
}
void DEBUG_CHANNEL_MSG()
@ -263,76 +205,4 @@ void DEBUG_CHANNEL_MSG(float v0, float v1, float v2, float v3)
DEBUG_CHANNEL_MSG_(DEBUG_CHANNEL_FMT_F32_ALL, floatBitsToUint(v0), floatBitsToUint(v1), floatBitsToUint(v2), floatBitsToUint(v3));
}
void DEBUG_CHANNEL_MSG_UNIFORM(uint v0)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0);
}
void DEBUG_CHANNEL_MSG_UNIFORM(uint v0, uint v1)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0, v1);
}
void DEBUG_CHANNEL_MSG_UNIFORM(uint v0, uint v1, uint v2)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0, v1, v2);
}
void DEBUG_CHANNEL_MSG_UNIFORM(uint v0, uint v1, uint v2, uint v3)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0, v1, v2, v3);
}
void DEBUG_CHANNEL_MSG_UNIFORM(int v0)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0);
}
void DEBUG_CHANNEL_MSG_UNIFORM(int v0, int v1)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0, v1);
}
void DEBUG_CHANNEL_MSG_UNIFORM(int v0, int v1, int v2)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0, v1, v2);
}
void DEBUG_CHANNEL_MSG_UNIFORM(int v0, int v1, int v2, int v3)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0, v1, v2, v3);
}
void DEBUG_CHANNEL_MSG_UNIFORM(float v0)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0);
}
void DEBUG_CHANNEL_MSG_UNIFORM(float v0, float v1)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0, v1);
}
void DEBUG_CHANNEL_MSG_UNIFORM(float v0, float v1, float v2)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0, v1, v2);
}
void DEBUG_CHANNEL_MSG_UNIFORM(float v0, float v1, float v2, float v3)
{
if (DEBUG_CHANNEL_ELECT())
DEBUG_CHANNEL_MSG(v0, v1, v2, v3);
}
#endif

View File

@ -31,67 +31,28 @@
# define VK_USE_PLATFORM_WIN32_KHR
# endif
# include <vulkan/vulkan.h>
# include "private/vulkan_private_extensions.h"
#endif /* VKD3D_NO_VULKAN_H */
#define VKD3D_MIN_API_VERSION VK_API_VERSION_1_1
#define VKD3D_MAX_API_VERSION VK_API_VERSION_1_1
#if defined(__GNUC__)
# define DECLSPEC_VISIBLE __attribute__((visibility("default")))
#else
# define DECLSPEC_VISIBLE
#endif
#if defined(_WIN32) && !defined(VKD3D_BUILD_STANDALONE_D3D12)
# ifdef VKD3D_EXPORTS
# define VKD3D_EXPORT __declspec(dllexport)
# else
# define VKD3D_EXPORT __declspec(dllimport)
# endif
#elif defined(__GNUC__)
# define VKD3D_EXPORT DECLSPEC_VISIBLE
#else
# define VKD3D_EXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define VKD3D_CONFIG_FLAG_VULKAN_DEBUG (1ull << 0)
#define VKD3D_CONFIG_FLAG_SKIP_APPLICATION_WORKAROUNDS (1ull << 1)
#define VKD3D_CONFIG_FLAG_DEBUG_UTILS (1ull << 2)
#define VKD3D_CONFIG_FLAG_FORCE_STATIC_CBV (1ull << 3)
#define VKD3D_CONFIG_FLAG_DXR (1ull << 4)
#define VKD3D_CONFIG_FLAG_SINGLE_QUEUE (1ull << 5)
#define VKD3D_CONFIG_FLAG_DESCRIPTOR_QA_CHECKS (1ull << 6)
#define VKD3D_CONFIG_FLAG_FORCE_RTV_EXCLUSIVE_QUEUE (1ull << 7)
#define VKD3D_CONFIG_FLAG_FORCE_DSV_EXCLUSIVE_QUEUE (1ull << 8)
#define VKD3D_CONFIG_FLAG_FORCE_MINIMUM_SUBGROUP_SIZE (1ull << 9)
#define VKD3D_CONFIG_FLAG_NO_UPLOAD_HVV (1ull << 10)
#define VKD3D_CONFIG_FLAG_LOG_MEMORY_BUDGET (1ull << 11)
#define VKD3D_CONFIG_FLAG_IGNORE_RTV_HOST_VISIBLE (1ull << 12)
#define VKD3D_CONFIG_FLAG_FORCE_HOST_CACHED (1ull << 13)
#define VKD3D_CONFIG_FLAG_DXR11 (1ull << 14)
#define VKD3D_CONFIG_FLAG_FORCE_NO_INVARIANT_POSITION (1ull << 15)
#define VKD3D_CONFIG_FLAG_GLOBAL_PIPELINE_CACHE (1ull << 16)
#define VKD3D_CONFIG_FLAG_PIPELINE_LIBRARY_NO_SERIALIZE_SPIRV (1ull << 17)
#define VKD3D_CONFIG_FLAG_PIPELINE_LIBRARY_SANITIZE_SPIRV (1ull << 18)
#define VKD3D_CONFIG_FLAG_PIPELINE_LIBRARY_LOG (1ull << 19)
#define VKD3D_CONFIG_FLAG_PIPELINE_LIBRARY_IGNORE_SPIRV (1ull << 20)
#define VKD3D_CONFIG_FLAG_MUTABLE_SINGLE_SET (1ull << 21)
#define VKD3D_CONFIG_FLAG_MEMORY_ALLOCATOR_SKIP_CLEAR (1ull << 22)
#define VKD3D_CONFIG_FLAG_RECYCLE_COMMAND_POOLS (1ull << 23)
#define VKD3D_CONFIG_FLAG_PIPELINE_LIBRARY_IGNORE_MISMATCH_DRIVER (1ull << 24)
#define VKD3D_CONFIG_FLAG_BREADCRUMBS (1ull << 25)
#define VKD3D_CONFIG_FLAG_PIPELINE_LIBRARY_APP_CACHE_ONLY (1ull << 26)
#define VKD3D_CONFIG_FLAG_SHADER_CACHE_SYNC (1ull << 27)
#define VKD3D_CONFIG_FLAG_FORCE_RAW_VA_CBV (1ull << 28)
#define VKD3D_CONFIG_FLAG_ZERO_MEMORY_WORKAROUNDS_COMMITTED_BUFFER_UAV (1ull << 29)
#define VKD3D_CONFIG_FLAG_ALLOW_SBT_COLLECTION (1ull << 30)
#define VKD3D_CONFIG_FLAG_FORCE_NATIVE_FP16 (1ull << 31)
#define VKD3D_CONFIG_FLAG_USE_HOST_IMPORT_FALLBACK (1ull << 32)
enum vkd3d_structure_type
{
/* 1.0 */
VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO,
/* 1.1 */
VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO,
/* 1.2 */
VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO,
VKD3D_STRUCTURE_TYPE_APPLICATION_INFO,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_STRUCTURE_TYPE),
};
typedef HRESULT (*PFN_vkd3d_signal_event)(HANDLE event);
@ -104,22 +65,49 @@ struct vkd3d_instance;
struct vkd3d_instance_create_info
{
enum vkd3d_structure_type type;
const void *next;
PFN_vkd3d_signal_event pfn_signal_event;
PFN_vkd3d_create_thread pfn_create_thread;
PFN_vkd3d_join_thread pfn_join_thread;
size_t wchar_size;
/* If set to NULL, libvkd3d loads libvulkan. */
PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr;
const char * const *instance_extensions;
uint32_t instance_extension_count;
};
const char * const *optional_instance_extensions;
uint32_t optional_instance_extension_count;
/* Extends vkd3d_instance_create_info. Available since 1.1. */
struct vkd3d_optional_instance_extensions_info
{
enum vkd3d_structure_type type;
const void *next;
const char * const *extensions;
uint32_t extension_count;
};
/* Extends vkd3d_instance_create_info. Available since 1.2. */
struct vkd3d_application_info
{
enum vkd3d_structure_type type;
const void *next;
const char *application_name;
uint32_t application_version;
const char *engine_name; /* "vkd3d" if NULL */
uint32_t engine_version; /* vkd3d version if engine_name is NULL */
};
struct vkd3d_device_create_info
{
enum vkd3d_structure_type type;
const void *next;
D3D_FEATURE_LEVEL minimum_feature_level;
struct vkd3d_instance *instance;
@ -130,15 +118,29 @@ struct vkd3d_device_create_info
const char * const *device_extensions;
uint32_t device_extension_count;
const char * const *optional_device_extensions;
uint32_t optional_device_extension_count;
IUnknown *parent;
LUID adapter_luid;
};
/* Extends vkd3d_device_create_info. Available since 1.2. */
struct vkd3d_optional_device_extensions_info
{
enum vkd3d_structure_type type;
const void *next;
const char * const *extensions;
uint32_t extension_count;
};
/* vkd3d_image_resource_create_info flags */
#define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001
#define VKD3D_RESOURCE_PRESENT_STATE_TRANSITION 0x00000002
struct vkd3d_image_resource_create_info
{
enum vkd3d_structure_type type;
const void *next;
VkImage vk_image;
D3D12_RESOURCE_DESC desc;
unsigned int flags;
@ -147,43 +149,42 @@ struct vkd3d_image_resource_create_info
#ifndef VKD3D_NO_PROTOTYPES
VKD3D_EXPORT HRESULT vkd3d_create_instance(const struct vkd3d_instance_create_info *create_info,
HRESULT vkd3d_create_instance(const struct vkd3d_instance_create_info *create_info,
struct vkd3d_instance **instance);
VKD3D_EXPORT ULONG vkd3d_instance_decref(struct vkd3d_instance *instance);
VKD3D_EXPORT VkInstance vkd3d_instance_get_vk_instance(struct vkd3d_instance *instance);
VKD3D_EXPORT ULONG vkd3d_instance_incref(struct vkd3d_instance *instance);
ULONG vkd3d_instance_decref(struct vkd3d_instance *instance);
VkInstance vkd3d_instance_get_vk_instance(struct vkd3d_instance *instance);
ULONG vkd3d_instance_incref(struct vkd3d_instance *instance);
VKD3D_EXPORT HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
REFIID iid, void **device);
VKD3D_EXPORT IUnknown *vkd3d_get_device_parent(ID3D12Device *device);
VKD3D_EXPORT VkDevice vkd3d_get_vk_device(ID3D12Device *device);
VKD3D_EXPORT VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device);
VKD3D_EXPORT struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device);
IUnknown *vkd3d_get_device_parent(ID3D12Device *device);
VkDevice vkd3d_get_vk_device(ID3D12Device *device);
VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device);
struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device);
VKD3D_EXPORT uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue);
VKD3D_EXPORT VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue);
VKD3D_EXPORT void vkd3d_release_vk_queue(ID3D12CommandQueue *queue);
VKD3D_EXPORT void vkd3d_enqueue_initial_transition(ID3D12CommandQueue *queue, ID3D12Resource *resource);
uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue);
VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue);
void vkd3d_release_vk_queue(ID3D12CommandQueue *queue);
VKD3D_EXPORT HRESULT vkd3d_create_image_resource(ID3D12Device *device,
HRESULT vkd3d_create_image_resource(ID3D12Device *device,
const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource);
VKD3D_EXPORT ULONG vkd3d_resource_decref(ID3D12Resource *resource);
VKD3D_EXPORT ULONG vkd3d_resource_incref(ID3D12Resource *resource);
ULONG vkd3d_resource_decref(ID3D12Resource *resource);
ULONG vkd3d_resource_incref(ID3D12Resource *resource);
VKD3D_EXPORT HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc,
HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc,
D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
VKD3D_EXPORT HRESULT vkd3d_create_root_signature_deserializer(const void *data, SIZE_T data_size,
HRESULT vkd3d_create_root_signature_deserializer(const void *data, SIZE_T data_size,
REFIID iid, void **deserializer);
VKD3D_EXPORT VkFormat vkd3d_get_vk_format(DXGI_FORMAT format);
VkFormat vkd3d_get_vk_format(DXGI_FORMAT format);
/* 1.1 */
VKD3D_EXPORT DXGI_FORMAT vkd3d_get_dxgi_format(VkFormat format);
DXGI_FORMAT vkd3d_get_dxgi_format(VkFormat format);
/* 1.2 */
VKD3D_EXPORT HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
ID3DBlob **blob, ID3DBlob **error_blob);
VKD3D_EXPORT HRESULT vkd3d_create_versioned_root_signature_deserializer(const void *data, SIZE_T data_size,
HRESULT vkd3d_create_versioned_root_signature_deserializer(const void *data, SIZE_T data_size,
REFIID iid, void **deserializer);
#endif /* VKD3D_NO_PROTOTYPES */

View File

@ -1,32 +0,0 @@
/*
* * Copyright 2021 NVIDIA Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
import "vkd3d_d3d12.idl";
import "vkd3d_vk_includes.h";
[
uuid(77a86b09-2bea-4801-b89a-37648e104af1),
object,
local,
pointer_default(unique)
]
interface ID3D12GraphicsCommandListExt : IUnknown
{
HRESULT GetVulkanHandle(VkCommandBuffer *pVkCommandBuffer);
HRESULT LaunchCubinShader(D3D12_CUBIN_DATA_HANDLE *handle, UINT32 block_x, UINT32 block_y, UINT32 block_z, const void *params, UINT32 param_size);
}

View File

@ -26,11 +26,11 @@ cpp_quote("#ifndef _D3D12_CONSTANTS")
cpp_quote("#define _D3D12_CONSTANTS")
cpp_quote("#ifndef D3D12_ERROR_ADAPTER_NOT_FOUND")
cpp_quote("#define D3D12_ERROR_ADAPTER_NOT_FOUND ((HRESULT)0x887e0001)")
cpp_quote("#define D3D12_ERROR_ADAPTER_NOT_FOUND 0x887e0001")
cpp_quote("#endif")
cpp_quote("#ifndef D3D12_ERROR_DRIVER_VERSION_MISMATCH")
cpp_quote("#define D3D12_ERROR_DRIVER_VERSION_MISMATCH ((HRESULT)0x887e0002)")
cpp_quote("#define D3D12_ERROR_DRIVER_VERSION_MISMATCH 0x887e0002")
cpp_quote("#endif")
const UINT D3D12_CS_TGSM_REGISTER_COUNT = 8192;
@ -109,7 +109,6 @@ typedef enum D3D12_SHADER_MIN_PRECISION_SUPPORT
D3D12_SHADER_MIN_PRECISION_SUPPORT_10_BIT = 0x1,
D3D12_SHADER_MIN_PRECISION_SUPPORT_16_BIT = 0x2,
} D3D12_SHADER_MIN_PRECISION_SUPPORT;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_SHADER_MIN_PRECISION_SUPPORT);")
typedef enum D3D12_TILED_RESOURCES_TIER
{
@ -169,7 +168,6 @@ typedef enum D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER
{
D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_0 = 0,
D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_1 = 1,
D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER_2 = 2,
} D3D12_SHARED_RESOURCE_COMPATIBILITY_TIER;
typedef enum D3D12_HEAP_SERIALIZATION_TIER
@ -189,7 +187,6 @@ typedef enum D3D12_RAYTRACING_TIER
{
D3D12_RAYTRACING_TIER_NOT_SUPPORTED = 0,
D3D12_RAYTRACING_TIER_1_0 = 10,
D3D12_RAYTRACING_TIER_1_1 = 11,
} D3D12_RAYTRACING_TIER;
typedef enum D3D12_VARIABLE_SHADING_RATE_TIER
@ -199,19 +196,6 @@ typedef enum D3D12_VARIABLE_SHADING_RATE_TIER
D3D12_VARIABLE_SHADING_RATE_TIER_2 = 2,
} D3D12_VARIABLE_SHADING_RATE_TIER;
typedef enum D3D12_MESH_SHADER_TIER
{
D3D12_MESH_SHADER_TIER_NOT_SUPPORTED = 0,
D3D12_MESH_SHADER_TIER_1 = 10,
} D3D12_MESH_SHADER_TIER;
typedef enum D3D12_SAMPLER_FEEDBACK_TIER
{
D3D12_SAMPLER_FEEDBACK_TIER_NOT_SUPPORTED = 0,
D3D12_SAMPLER_FEEDBACK_TIER_0_9 = 90,
D3D12_SAMPLER_FEEDBACK_TIER_1_0 = 100,
} D3D12_SAMPLER_FEEDBACK_TIER;
typedef enum D3D12_COMMAND_LIST_SUPPORT_FLAGS
{
D3D12_COMMAND_LIST_SUPPORT_FLAG_NONE = 0x0,
@ -221,9 +205,7 @@ typedef enum D3D12_COMMAND_LIST_SUPPORT_FLAGS
D3D12_COMMAND_LIST_SUPPORT_FLAG_COPY = 0x8,
D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_DECODE = 0x10,
D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_PROCESS = 0x20,
D3D12_COMMAND_LIST_SUPPORT_FLAG_VIDEO_ENCODE = 0x40,
} D3D12_COMMAND_LIST_SUPPORT_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_COMMAND_LIST_SUPPORT_FLAGS);")
typedef enum D3D12_FORMAT_SUPPORT1
{
@ -258,7 +240,6 @@ typedef enum D3D12_FORMAT_SUPPORT1
D3D12_FORMAT_SUPPORT1_VIDEO_PROCESSOR_INPUT = 0x20000000,
D3D12_FORMAT_SUPPORT1_VIDEO_ENCODER = 0x40000000,
} D3D12_FORMAT_SUPPORT1;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_FORMAT_SUPPORT1);")
typedef enum D3D12_FORMAT_SUPPORT2
{
@ -274,9 +255,7 @@ typedef enum D3D12_FORMAT_SUPPORT2
D3D12_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP = 0x00000100,
D3D12_FORMAT_SUPPORT2_TILED = 0x00000200,
D3D12_FORMAT_SUPPORT2_MULTIPLANE_OVERLAY = 0x00004000,
D3D12_FORMAT_SUPPORT2_SAMPLER_FEEDBACK = 0x00008000,
} D3D12_FORMAT_SUPPORT2;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_FORMAT_SUPPORT2);")
typedef enum D3D12_WRITEBUFFERIMMEDIATE_MODE
{
@ -285,12 +264,6 @@ typedef enum D3D12_WRITEBUFFERIMMEDIATE_MODE
D3D12_WRITEBUFFERIMMEDIATE_MODE_MARKER_OUT = 0x2,
} D3D12_WRITEBUFFERIMMEDIATE_MODE;
typedef enum D3D12_WAVE_MMA_TIER
{
D3D12_WAVE_MMA_TIER_NOT_SUPPORTED = 0,
D3D12_WAVE_MMA_TIER_1_0 = 10,
} D3D12_WAVE_MMA_TIER;
interface ID3D12Fence;
interface ID3D12RootSignature;
interface ID3D12Heap;
@ -342,13 +315,6 @@ typedef struct D3D12_SUBRESOURCE_RANGE_UINT64
D3D12_RANGE_UINT64 Range;
} D3D12_SUBRESOURCE_RANGE_UINT64;
typedef struct D3D12_SUBRESOURCE_INFO
{
UINT64 Offset;
UINT RowPitch;
UINT DepthPitch;
} D3D12_SUBRESOURCE_INFO;
typedef struct D3D12_RESOURCE_ALLOCATION_INFO
{
UINT64 SizeInBytes;
@ -453,38 +419,6 @@ typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS6
BOOL BackgroundProcessingSupported;
} D3D12_FEATURE_DATA_D3D12_OPTIONS6;
typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS7
{
D3D12_MESH_SHADER_TIER MeshShaderTier;
D3D12_SAMPLER_FEEDBACK_TIER SamplerFeedbackTier;
} D3D12_FEATURE_DATA_D3D12_OPTIONS7;
typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS8
{
BOOL UnalignedBlockTexturesSupported;
} D3D12_FEATURE_DATA_D3D12_OPTIONS8;
typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS9
{
BOOL MeshShaderPipelineStatsSupported;
BOOL MeshShaderSupportsFullRangeRenderTargetArrayIndex;
BOOL AtomicInt64OnTypedResourceSupported;
BOOL AtomicInt64OnGroupSharedSupported;
BOOL DerivativesInMeshAndAmplificationShadersSupported;
D3D12_WAVE_MMA_TIER WaveMMATier;
} D3D12_FEATURE_DATA_D3D12_OPTIONS9;
typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS10
{
BOOL VariableRateShadingSumCombinerSupported;
BOOL MeshShaderPerPrimitiveShadingRateSupported;
} D3D12_FEATURE_DATA_D3D12_OPTIONS10;
typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS11
{
BOOL AtomicInt64OnDescriptorHeapResourceSupported;
} D3D12_FEATURE_DATA_D3D12_OPTIONS11;
typedef struct D3D12_FEATURE_DATA_FORMAT_SUPPORT
{
DXGI_FORMAT Format;
@ -497,7 +431,6 @@ typedef enum D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS
D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE = 0x00000000,
D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_TILED_RESOURCE = 0x00000001,
} D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS);")
typedef struct D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS
{
@ -575,17 +508,11 @@ typedef enum D3D12_HEAP_FLAGS
D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER = 0x20,
D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES = 0x40,
D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES = 0x80,
D3D12_HEAP_FLAG_HARDWARE_PROTECTED = 0x100,
D3D12_HEAP_FLAG_ALLOW_WRITE_WATCH = 0x200,
D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS = 0x400,
D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT = 0x800,
D3D12_HEAP_FLAG_CREATE_NOT_ZEROED = 0x1000,
D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0x00,
D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS = 0xc0,
D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES = 0x44,
D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES = 0x84,
} D3D12_HEAP_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_HEAP_FLAGS);")
typedef struct D3D12_HEAP_DESC
{
@ -701,7 +628,6 @@ typedef enum D3D12_RESOURCE_BARRIER_FLAGS
D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY = 0x1,
D3D12_RESOURCE_BARRIER_FLAG_END_ONLY = 0x2,
} D3D12_RESOURCE_BARRIER_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RESOURCE_BARRIER_FLAGS);")
typedef struct D3D12_RESOURCE_TRANSITION_BARRIER
{
@ -711,7 +637,7 @@ typedef struct D3D12_RESOURCE_TRANSITION_BARRIER
D3D12_RESOURCE_STATES StateAfter;
} D3D12_RESOURCE_TRANSITION_BARRIER;
typedef struct D3D12_RESOURCE_ALIASING_BARRIER
typedef struct D3D12_RESOURCE_ALIASING_BARRIER_ALIASING
{
ID3D12Resource *pResourceBefore;
ID3D12Resource *pResourceAfter;
@ -778,36 +704,12 @@ typedef struct D3D12_RESOURCE_DESC
D3D12_RESOURCE_FLAGS Flags;
} D3D12_RESOURCE_DESC;
typedef struct D3D12_MIP_REGION
{
UINT Width;
UINT Height;
UINT Depth;
} D3D12_MIP_REGION;
typedef struct D3D12_RESOURCE_DESC1
{
D3D12_RESOURCE_DIMENSION Dimension;
UINT64 Alignment;
UINT64 Width;
UINT Height;
UINT16 DepthOrArraySize;
UINT16 MipLevels;
DXGI_FORMAT Format;
DXGI_SAMPLE_DESC SampleDesc;
D3D12_TEXTURE_LAYOUT Layout;
D3D12_RESOURCE_FLAGS Flags;
D3D12_MIP_REGION SamplerFeedbackMipRegion;
} D3D12_RESOURCE_DESC1;
typedef enum D3D12_RESOLVE_MODE
{
D3D12_RESOLVE_MODE_DECOMPRESS = 0,
D3D12_RESOLVE_MODE_MIN = 1,
D3D12_RESOLVE_MODE_MAX = 2,
D3D12_RESOLVE_MODE_AVERAGE = 3,
D3D12_RESOLVE_MODE_ENCODE_SAMPLER_FEEDBACK = 4,
D3D12_RESOLVE_MODE_DECODE_SAMPLER_FEEDBACK = 5,
} D3D12_RESOLVE_MODE;
typedef struct D3D12_SAMPLE_POSITION
@ -821,7 +723,6 @@ typedef enum D3D12_VIEW_INSTANCING_FLAGS
D3D12_VIEW_INSTANCING_FLAG_NONE = 0,
D3D12_VIEW_INSTANCING_FLAG_ENABLE_VIEW_INSTANCE_MASKING = 0x1,
} D3D12_VIEW_INSTANCING_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_VIEW_INSTANCING_FLAGS);")
typedef struct D3D12_VIEW_INSTANCE_LOCATION
{
@ -894,7 +795,6 @@ typedef enum D3D12_DESCRIPTOR_RANGE_FLAGS
D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8,
D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 0x10000,
} D3D12_DESCRIPTOR_RANGE_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_DESCRIPTOR_RANGE_FLAGS);")
typedef struct D3D12_DESCRIPTOR_RANGE1
{
@ -938,7 +838,6 @@ typedef enum D3D12_ROOT_DESCRIPTOR_FLAGS
D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC = 0x8,
} D3D12_ROOT_DESCRIPTOR_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_ROOT_DESCRIPTOR_FLAGS);")
typedef struct D3D12_ROOT_DESCRIPTOR1
{
@ -964,8 +863,6 @@ typedef enum D3D12_SHADER_VISIBILITY
D3D12_SHADER_VISIBILITY_DOMAIN = 3,
D3D12_SHADER_VISIBILITY_GEOMETRY = 4,
D3D12_SHADER_VISIBILITY_PIXEL = 5,
D3D12_SHADER_VISIBILITY_AMPLIFICATION = 6,
D3D12_SHADER_VISIBILITY_MESH = 7,
} D3D12_SHADER_VISIBILITY;
typedef struct D3D12_ROOT_PARAMETER
@ -1134,12 +1031,7 @@ typedef enum D3D12_ROOT_SIGNATURE_FLAGS
D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS = 0x20,
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT = 0x40,
D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE = 0x80,
D3D12_ROOT_SIGNATURE_FLAG_DENY_AMPLIFICATION_SHADER_ROOT_ACCESS = 0x100,
D3D12_ROOT_SIGNATURE_FLAG_DENY_MESH_SHADER_ROOT_ACCESS = 0x200,
D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED = 0x400,
D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED = 0x800,
} D3D12_ROOT_SIGNATURE_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_ROOT_SIGNATURE_FLAGS);")
typedef struct D3D12_ROOT_SIGNATURE_DESC
{
@ -1190,7 +1082,6 @@ typedef enum D3D12_DESCRIPTOR_HEAP_FLAGS
D3D12_DESCRIPTOR_HEAP_FLAG_NONE = 0x0,
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE = 0x1,
} D3D12_DESCRIPTOR_HEAP_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_DESCRIPTOR_HEAP_FLAGS);")
typedef struct D3D12_DESCRIPTOR_HEAP_DESC
{
@ -1229,7 +1120,6 @@ typedef enum D3D12_BUFFER_SRV_FLAGS
D3D12_BUFFER_SRV_FLAG_NONE = 0x0,
D3D12_BUFFER_SRV_FLAG_RAW = 0x1,
} D3D12_BUFFER_SRV_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_BUFFER_SRV_FLAGS);")
typedef enum D3D12_SHADER_COMPONENT_MAPPING
{
@ -1371,7 +1261,6 @@ typedef enum D3D12_BUFFER_UAV_FLAGS
D3D12_BUFFER_UAV_FLAG_NONE = 0x0,
D3D12_BUFFER_UAV_FLAG_RAW = 0x1,
} D3D12_BUFFER_UAV_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_BUFFER_UAV_FLAGS);")
typedef struct D3D12_BUFFER_UAV
{
@ -1842,7 +1731,6 @@ typedef enum D3D12_PIPELINE_STATE_FLAGS
D3D12_PIPELINE_STATE_FLAG_NONE = 0x0,
D3D12_PIPELINE_STATE_FLAG_DEBUG = 0x1,
} D3D12_PIPELINE_STATE_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_PIPELINE_STATE_FLAGS);")
typedef struct D3D12_GRAPHICS_PIPELINE_STATE_DESC
{
@ -1891,8 +1779,7 @@ typedef enum D3D12_COMMAND_LIST_TYPE
D3D12_COMMAND_LIST_TYPE_COMPUTE = 2,
D3D12_COMMAND_LIST_TYPE_COPY = 3,
D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE = 4,
D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS = 5,
D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE = 6,
D3D12_COMMAND_LIST_TYPE_VIDEO_PROVESS = 5,
} D3D12_COMMAND_LIST_TYPE;
typedef enum D3D12_COMMAND_QUEUE_PRIORITY
@ -1907,7 +1794,6 @@ typedef enum D3D12_COMMAND_QUEUE_FLAGS
D3D12_COMMAND_QUEUE_FLAG_NONE = 0x0,
D3D12_COMMAND_QUEUE_FLAG_DISABLE_GPU_TIMEOUT = 0x1,
} D3D12_COMMAND_QUEUE_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_COMMAND_QUEUE_FLAGS);")
typedef enum D3D12_SHADER_CACHE_SUPPORT_FLAGS
{
@ -1917,7 +1803,6 @@ typedef enum D3D12_SHADER_CACHE_SUPPORT_FLAGS
D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_INPROC_CACHE = 0x4,
D3D12_SHADER_CACHE_SUPPORT_AUTOMATIC_DISK_CACHE = 0x8,
} D3D12_SHADER_CACHE_SUPPORT_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_SHADER_CACHE_SUPPORT_FLAGS);")
typedef struct D3D12_COMMAND_QUEUE_DESC
{
@ -1988,8 +1873,6 @@ typedef enum D3D_SHADER_MODEL
D3D_SHADER_MODEL_6_2 = 0x62,
D3D_SHADER_MODEL_6_3 = 0x63,
D3D_SHADER_MODEL_6_4 = 0x64,
D3D_SHADER_MODEL_6_5 = 0x65,
D3D_SHADER_MODEL_6_6 = 0x66,
} D3D_SHADER_MODEL;
typedef struct D3D12_FEATURE_DATA_SHADER_MODEL
@ -2022,13 +1905,6 @@ typedef enum D3D12_FEATURE
D3D12_FEATURE_D3D12_OPTIONS5 = 27,
D3D12_FEATURE_D3D12_OPTIONS6 = 30,
D3D12_FEATURE_QUERY_META_COMMAND = 31,
D3D12_FEATURE_D3D12_OPTIONS7 = 32,
D3D12_FEATURE_PROTECTED_RESOURCE_SESSION_TYPE_COUNT = 33,
D3D12_FEATURE_PROTECTED_RESOURCE_SESSION_TYPES = 34,
D3D12_FEATURE_D3D12_OPTIONS8 = 36,
D3D12_FEATURE_D3D12_OPTIONS9 = 37,
D3D12_FEATURE_D3D12_OPTIONS10 = 39,
D3D12_FEATURE_D3D12_OPTIONS11 = 40,
} D3D12_FEATURE;
typedef struct D3D12_MEMCPY_DEST
@ -2158,15 +2034,6 @@ interface ID3D12Resource1 : ID3D12Resource
{
HRESULT GetProtectedResourceSession(REFIID riid, void **protected_session);
}
[
uuid(be36ec3b-ea85-4aeb-a45a-e9d76404a495),
object,
local,
pointer_default(unique)
]
interface ID3D12Resource2 : ID3D12Resource1 {
D3D12_RESOURCE_DESC1 GetDesc1();
}
[
uuid(7116d91c-e7e4-47ce-b8c6-ec8168f437e5),
@ -2186,7 +2053,6 @@ typedef enum D3D12_TILE_COPY_FLAGS
D3D12_TILE_COPY_FLAG_LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE = 0x2,
D3D12_TILE_COPY_FLAG_SWIZZLED_TILED_RESOURCE_TO_LINEAR_BUFFER = 0x4,
} D3D12_TILE_COPY_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_TILE_COPY_FLAGS);")
typedef struct D3D12_INDEX_BUFFER_VIEW
{
@ -2303,13 +2169,11 @@ typedef enum D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS
D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG_NONE = 0,
D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG_SUPPORTED = 0x1,
} D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS);")
typedef enum D3D12_PROTECTED_RESOURCE_SESSION_FLAGS
{
D3D12_PROTECTED_RESOURCE_SESSION_FLAG_NONE = 0,
} D3D12_PROTECTED_RESOURCE_SESSION_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_PROTECTED_RESOURCE_SESSION_FLAGS);")
typedef enum D3D12_PROTECTED_SESSION_STATUS
{
@ -2353,37 +2217,6 @@ interface ID3D12ProtectedResourceSession : ID3D12ProtectedSession
D3D12_PROTECTED_RESOURCE_SESSION_DESC GetDesc();
}
typedef struct D3D12_FEATURE_DATA_PROTECTED_RESOURCE_SESSION_TYPE_COUNT
{
UINT NodeIndex;
UINT Count;
} D3D12_FEATURE_DATA_PROTECTED_RESOURCE_SESSION_TYPE_COUNT;
typedef struct D3D12_FEATURE_DATA_PROTECTED_RESOURCE_SESSION_TYPES
{
UINT NodeIndex;
UINT Count;
GUID *pTypes;
} D3D12_FEATURE_DATA_PROTECTED_RESOURCE_SESSION_TYPES;
typedef struct D3D12_PROTECTED_RESOURCE_SESSION_DESC1
{
UINT NodeMask;
D3D12_PROTECTED_RESOURCE_SESSION_FLAGS Flags;
GUID ProtectionType;
} D3D12_PROTECTED_RESOURCE_SESSION_DESC1;
[
uuid(D6F12DD6-76FB-406E-8961-4296EEFC0409),
object,
local,
pointer_default(unique)
]
interface ID3D12ProtectedResourceSession1 : ID3D12ProtectedResourceSession
{
D3D12_PROTECTED_RESOURCE_SESSION_DESC1 GetDesc1();
}
typedef enum D3D12_PIPELINE_STATE_SUBOBJECT_TYPE
{
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE = 0,
@ -2409,9 +2242,7 @@ typedef enum D3D12_PIPELINE_STATE_SUBOBJECT_TYPE
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS = 20,
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1 = 21,
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VIEW_INSTANCING = 22,
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_AS = 24,
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MS = 25,
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID = 26,
D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MAX_VALID = 23,
} D3D12_PIPELINE_STATE_SUBOBJECT_TYPE;
typedef struct D3D12_PIPELINE_STATE_STREAM_DESC
@ -2480,7 +2311,6 @@ typedef enum D3D12_META_COMMAND_PARAMETER_FLAGS
D3D12_META_COMMAND_PARAMETER_FLAG_INPUT = 0x1,
D3D12_META_COMMAND_PARAMETER_FLAG_OUTPUT = 0x2,
} D3D12_META_COMMAND_PARAMETER_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_META_COMMAND_PARAMETER_FLAGS);")
typedef enum D3D12_META_COMMAND_PARAMETER_STAGE
{
@ -2519,7 +2349,6 @@ typedef enum D3D12_GRAPHICS_STATES
D3D12_GRAPHICS_STATE_SAMPLE_POSITIONS = 0x8000,
D3D12_GRAPHICS_STATE_VIEW_INSTANCE_MASK = 0x10000,
} D3D12_GRAPHICS_STATES;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_GRAPHICS_STATES);")
typedef struct D3D12_META_COMMAND_DESC
{
@ -2570,8 +2399,6 @@ typedef enum D3D12_STATE_SUBOBJECT_TYPE
D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG = 9,
D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG = 10,
D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP = 11,
D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG1 = 12,
D3D12_STATE_SUBOBJECT_TYPE_MAX_VALID = 13,
} D3D12_STATE_SUBOBJECT_TYPE;
typedef struct D3D12_STATE_SUBOBJECT
@ -2585,9 +2412,7 @@ typedef enum D3D12_STATE_OBJECT_FLAGS
D3D12_STATE_OBJECT_FLAG_NONE = 0,
D3D12_STATE_OBJECT_FLAG_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITIONS = 0x1,
D3D12_STATE_OBJECT_FLAG_ALLOW_EXTERNAL_DEPENDENCIES_ON_LOCAL_DEFINITIONS = 0x2,
D3D12_STATE_OBJECT_FLAG_ALLOW_STATE_OBJECT_ADDITIONS = 0x4,
} D3D12_STATE_OBJECT_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_STATE_OBJECT_FLAGS);")
typedef struct D3D12_STATE_OBJECT_CONFIG
{
@ -2613,7 +2438,6 @@ typedef enum D3D12_EXPORT_FLAGS
{
D3D12_EXPORT_FLAG_NONE = 0,
} D3D12_EXPORT_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_EXPORT_FLAGS);")
typedef struct D3D12_EXPORT_DESC
{
@ -2643,13 +2467,6 @@ typedef struct D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION
LPCWSTR *pExports;
} D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION;
typedef struct D3D12_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION
{
LPCWSTR SubobjectToAssociate;
UINT NumExports;
LPCWSTR *pExports;
} D3D12_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION;
typedef enum D3D12_HIT_GROUP_TYPE
{
D3D12_HIT_GROUP_TYPE_TRIANGLES = 0,
@ -2671,20 +2488,6 @@ typedef struct D3D12_RAYTRACING_SHADER_CONFIG
UINT MaxAttributeSizeInBytes;
} D3D12_RAYTRACING_SHADER_CONFIG;
typedef enum D3D12_RAYTRACING_PIPELINE_FLAGS
{
D3D12_RAYTRACING_PIPELINE_FLAG_NONE = 0x0,
D3D12_RAYTRACING_PIPELINE_FLAG_SKIP_TRIANGLES = 0x100,
D3D12_RAYTRACING_PIPELINE_FLAG_SKIP_PROCEDURAL_PRIMITIVES = 0x200,
} D3D12_RAYTRACING_PIPELINE_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RAYTRACING_PIPELINE_FLAGS);")
typedef struct D3D12_RAYTRACING_PIPELINE_CONFIG1
{
UINT MaxTraceRecursionDepth;
D3D12_RAYTRACING_PIPELINE_FLAGS Flags;
} D3D12_RAYTRACING_PIPELINE_CONFIG1;
typedef struct D3D12_RAYTRACING_PIPELINE_CONFIG
{
UINT MaxTraceRecursionDepth;
@ -2709,7 +2512,6 @@ typedef enum D3D12_RAYTRACING_GEOMETRY_FLAGS
D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE = 0x1,
D3D12_RAYTRACING_GEOMETRY_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION = 0x2,
} D3D12_RAYTRACING_GEOMETRY_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RAYTRACING_GEOMETRY_FLAGS);")
typedef enum D3D12_RAYTRACING_GEOMETRY_TYPE
{
@ -2725,7 +2527,6 @@ typedef enum D3D12_RAYTRACING_INSTANCE_FLAGS
D3D12_RAYTRACING_INSTANCE_FLAG_FORCE_OPAQUE = 0x4,
D3D12_RAYTRACING_INSTANCE_FLAG_FORCE_NON_OPAQUE = 0x8,
} D3D12_RAYTRACING_INSTANCE_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RAYTRACING_INSTANCE_FLAGS);")
typedef struct D3D12_GPU_VIRTUAL_ADDRESS_AND_STRIDE
{
@ -2783,7 +2584,6 @@ typedef enum D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_MINIMIZE_MEMORY = 0x10,
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PERFORM_UPDATE = 0x20,
} D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS);")
typedef enum D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE
{
@ -2936,10 +2736,7 @@ typedef enum D3D12_RAY_FLAGS
D3D12_RAY_FLAG_CULL_FRONT_FACING_TRIANGLES = 0x20,
D3D12_RAY_FLAG_CULL_OPAQUE = 0x40,
D3D12_RAY_FLAG_CULL_NON_OPAQUE = 0x80,
D3D12_RAY_FLAG_SKIP_TRIANGLES = 0x100,
D3D12_RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES = 0x200,
} D3D12_RAY_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RAY_FLAGS);")
typedef enum D3D12_HIT_KIND
{
@ -2962,19 +2759,16 @@ typedef enum D3D12_COMMAND_LIST_FLAGS
{
D3D12_COMMAND_LIST_FLAG_NONE = 0,
} D3D12_COMMAND_LIST_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_COMMAND_LIST_FLAGS);")
typedef enum D3D12_COMMAND_POOL_FLAGS
{
D3D12_COMMAND_POOL_FLAG_NONE = 0,
} D3D12_COMMAND_POOL_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_COMMAND_POOL_FLAGS);")
typedef enum D3D12_COMMAND_RECORDER_FLAGS
{
D3D12_COMMAND_RECORDER_FLAG_NONE = 0,
} D3D12_COMMAND_RECORDER_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_COMMAND_RECORDER_FLAGS);")
typedef enum D3D12_AUTO_BREADCRUMB_OP
{
@ -3018,17 +2812,14 @@ typedef enum D3D12_AUTO_BREADCRUMB_OP
D3D12_AUTO_BREADCRUMB_OP_ESTIMATEMOTION = 37,
D3D12_AUTO_BREADCRUMB_OP_RESOLVEMOTIONVECTORHEAP = 38,
D3D12_AUTO_BREADCRUMB_OP_SETPIPELINESTATE1 = 39,
D3D12_AUTO_BREADCRUMB_OP_INITIALIZEEXTENSIONCOMMAND = 40,
D3D12_AUTO_BREADCRUMB_OP_EXECUTEEXTENSIONCOMMAND = 41,
D3D12_AUTO_BREADCRUMB_OP_DISPATCHMESH = 42,
} D3D12_AUTO_BREADCRUMB_OP;
typedef struct D3D12_AUTO_BREADCRUMB_NODE
{
const char *pCommandListDebugNameA;
const WCHAR *pCommandListDebugNameW;
const wchar_t *pCommandListDebugNameW;
const char *pCommandQueueDebugNameA;
const WCHAR *pCommandQueueDebugNameW;
const wchar_t *pCommandQueueDebugNameW;
ID3D12GraphicsCommandList *pCommandList;
ID3D12CommandQueue *pCommandQueue;
UINT32 BreadcrumbCount;
@ -3037,33 +2828,9 @@ typedef struct D3D12_AUTO_BREADCRUMB_NODE
struct D3D12_AUTO_BREADCRUMB_NODE *pNext;
} D3D12_AUTO_BREADCRUMB_NODE;
typedef struct D3D12_DRED_BREADCRUMB_CONTEXT
{
UINT BreadcrumbIndex;
const WCHAR *pContextString;
} D3D12_DRED_BREADCRUMB_CONTEXT;
typedef struct D3D12_AUTO_BREADCRUMB_NODE1
{
const char *pCommandListDebugNameA;
const WCHAR *pCommandListDebugNameW;
const char *pCommandQueueDebugNameA;
const WCHAR *pCommandQueueDebugNameW;
ID3D12GraphicsCommandList *pCommandList;
ID3D12CommandQueue *pCommandQueue;
UINT BreadcrumbCount;
const UINT *pLastBreadcrumbValue;
const D3D12_AUTO_BREADCRUMB_OP *pCommandHistory;
const struct D3D12_AUTO_BREADCRUMB_NODE1 *pNext;
UINT BreadcrumbContextsCount;
D3D12_DRED_BREADCRUMB_CONTEXT *pBreadcrumbContexts;
} D3D12_AUTO_BREADCRUMB_NODE1;
typedef enum D3D12_DRED_VERSION
{
D3D12_DRED_VERSION_1_0 = 1,
D3D12_DRED_VERSION_1_1 = 2,
D3D12_DRED_VERSION_1_2 = 3,
D3D12_DRED_VERSION_1_0 = 1,
} D3D12_DRED_VERSION;
typedef enum D3D12_DRED_FLAGS
@ -3072,14 +2839,6 @@ typedef enum D3D12_DRED_FLAGS
D3D12_DRED_FLAG_FORCE_ENABLE = 0x1,
D3D12_DRED_FLAG_AUTOBREADCRUMBS = 0x2,
} D3D12_DRED_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_DRED_FLAGS);")
typedef enum D3D12_DRED_ENABLEMENT
{
D3D12_DRED_ENABLEMENT_SYSTEM_CONTROLLED = 0,
D3D12_DRED_ENABLEMENT_FORCED_OFF = 1,
D3D12_DRED_ENABLEMENT_FORCED_ON = 2,
} D3D12_DRED_ENABLEMENT;
typedef struct D3D12_DEVICE_REMOVED_EXTENDED_DATA
{
@ -3087,92 +2846,6 @@ typedef struct D3D12_DEVICE_REMOVED_EXTENDED_DATA
D3D12_AUTO_BREADCRUMB_NODE *pHeadAutoBreadcrumbNode;
} D3D12_DEVICE_REMOVED_EXTENDED_DATA;
typedef enum D3D12_DRED_ALLOCATION_TYPE
{
D3D12_DRED_ALLOCATION_TYPE_COMMAND_QUEUE = 19,
D3D12_DRED_ALLOCATION_TYPE_COMMAND_ALLOCATOR = 20,
D3D12_DRED_ALLOCATION_TYPE_PIPELINE_STATE = 21,
D3D12_DRED_ALLOCATION_TYPE_COMMAND_LIST = 22,
D3D12_DRED_ALLOCATION_TYPE_FENCE = 23,
D3D12_DRED_ALLOCATION_TYPE_DESCRIPTOR_HEAP = 24,
D3D12_DRED_ALLOCATION_TYPE_HEAP = 25,
D3D12_DRED_ALLOCATION_TYPE_QUERY_HEAP = 27,
D3D12_DRED_ALLOCATION_TYPE_COMMAND_SIGNATURE = 28,
D3D12_DRED_ALLOCATION_TYPE_PIPELINE_LIBRARY = 29,
D3D12_DRED_ALLOCATION_TYPE_VIDEO_DECODER = 30,
D3D12_DRED_ALLOCATION_TYPE_VIDEO_PROCESSOR = 32,
D3D12_DRED_ALLOCATION_TYPE_RESOURCE = 34,
D3D12_DRED_ALLOCATION_TYPE_PASS = 35,
D3D12_DRED_ALLOCATION_TYPE_CRYPTOSESSION = 36,
D3D12_DRED_ALLOCATION_TYPE_CRYPTOSESSIONPOLICY = 37,
D3D12_DRED_ALLOCATION_TYPE_PROTECTEDRESOURCESESSION = 38,
D3D12_DRED_ALLOCATION_TYPE_VIDEO_DECODER_HEAP = 39,
D3D12_DRED_ALLOCATION_TYPE_COMMAND_POOL = 40,
D3D12_DRED_ALLOCATION_TYPE_COMMAND_RECORDER = 41,
D3D12_DRED_ALLOCATION_TYPE_STATE_OBJECT = 42,
D3D12_DRED_ALLOCATION_TYPE_METACOMMAND = 43,
D3D12_DRED_ALLOCATION_TYPE_SCHEDULINGGROUP = 44,
D3D12_DRED_ALLOCATION_TYPE_VIDEO_MOTION_ESTIMATOR = 45,
D3D12_DRED_ALLOCATION_TYPE_VIDEO_MOTION_VECTOR_HEAP = 46,
D3D12_DRED_ALLOCATION_TYPE_VIDEO_EXTENSION_COMMAND = 47,
D3D12_DRED_ALLOCATION_TYPE_INVALID = 0xffffffff,
} D3D12_DRED_ALLOCATION_TYPE;
typedef struct D3D12_DRED_ALLOCATION_NODE
{
const char *ObjectNameA;
const WCHAR *ObjectNameW;
D3D12_DRED_ALLOCATION_TYPE AllocationType;
const struct D3D12_DRED_ALLOCATION_NODE *pNext;
} D3D12_DRED_ALLOCATION_NODE;
typedef struct D3D12_DRED_ALLOCATION_NODE1
{
const char *ObjectNameA;
const WCHAR *ObjectNameW;
D3D12_DRED_ALLOCATION_TYPE AllocationType;
const struct D3D12_DRED_ALLOCATION_NODE1 *pNext;
const IUnknown *pObject;
} D3D12_DRED_ALLOCATION_NODE1;
typedef struct D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT
{
const D3D12_AUTO_BREADCRUMB_NODE *pHeadAutoBreadcrumbNode;
} D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT;
typedef struct D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT1
{
const D3D12_AUTO_BREADCRUMB_NODE1 *pHeadAutoBreadcrumbNode;
} D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT1;
typedef struct D3D12_DRED_PAGE_FAULT_OUTPUT
{
D3D12_GPU_VIRTUAL_ADDRESS PageFaultVA;
const D3D12_DRED_ALLOCATION_NODE *pHeadExistingAllocationNode;
const D3D12_DRED_ALLOCATION_NODE *pHeadRecentFreedAllocationNode;
} D3D12_DRED_PAGE_FAULT_OUTPUT;
typedef struct D3D12_DRED_PAGE_FAULT_OUTPUT1
{
D3D12_GPU_VIRTUAL_ADDRESS PageFaultVA;
const D3D12_DRED_ALLOCATION_NODE1 *pHeadExistingAllocationNode;
const D3D12_DRED_ALLOCATION_NODE1 *pHeadRecentFreedAllocationNode;
} D3D12_DRED_PAGE_FAULT_OUTPUT1;
typedef struct D3D12_DEVICE_REMOVED_EXTENDED_DATA1
{
HRESULT DeviceRemovedReason;
D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT AutoBreadcrumbsOutput;
D3D12_DRED_PAGE_FAULT_OUTPUT PageFaultOutput;
} D3D12_DEVICE_REMOVED_EXTENDED_DATA1;
typedef struct D3D12_DEVICE_REMOVED_EXTENDED_DATA2
{
HRESULT DeviceRemovedReason;
D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT1 AutoBreadcrumbsOutput;
D3D12_DRED_PAGE_FAULT_OUTPUT1 PageFaultOutput;
} D3D12_DEVICE_REMOVED_EXTENDED_DATA2;
typedef struct D3D12_VERSIONED_DEVICE_REMOVED_EXTENDED_DATA
{
D3D12_DRED_VERSION Version;
@ -3205,7 +2878,6 @@ typedef enum D3D12_RENDER_PASS_FLAGS
D3D12_RENDER_PASS_FLAG_SUSPENDING_PASS = 0x2,
D3D12_RENDER_PASS_FLAG_RESUMING_PASS = 0x4,
} D3D12_RENDER_PASS_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RENDER_PASS_FLAGS);")
typedef enum D3D12_AXIS_SHADING_RATE
{
@ -3315,52 +2987,6 @@ typedef struct D3D12_RENDER_PASS_DEPTH_STENCIL_DESC
D3D12_RENDER_PASS_ENDING_ACCESS StencilEndingAccess;
} D3D12_RENDER_PASS_DEPTH_STENCIL_DESC;
typedef struct D3D12_DISPATCH_MESH_ARGUMENTS
{
UINT ThreadGroupCountX;
UINT ThreadGroupCountY;
UINT ThreadGroupCountZ;
} D3D12_DISPATCH_MESH_ARGUMENTS;
typedef enum D3D12_SHADER_CACHE_MODE
{
D3D12_SHADER_CACHE_MODE_MEMORY = 0,
D3D12_SHADER_CACHE_MODE_DISK = 1,
} D3D12_SHADER_CACHE_MODE;
typedef enum D3D12_SHADER_CACHE_FLAGS
{
D3D12_SHADER_CACHE_FLAG_NONE = 0,
D3D12_SHADER_CACHE_FLAG_DRIVER_VERSIONED = 0x1,
D3D12_SHADER_CACHE_FLAG_USE_WORKING_DIR = 0x2,
} D3D12_SHADER_CACHE_FLAGS;
typedef struct D3D12_SHADER_CACHE_SESSION_DESC
{
GUID Identifier;
D3D12_SHADER_CACHE_MODE Mode;
D3D12_SHADER_CACHE_FLAGS Flags;
UINT MaximumInMemoryCacheSizeBytes;
UINT MaximumInMemoryCacheEntries;
UINT MaximumValueFileSizeBytes;
UINT64 Version;
} D3D12_SHADER_CACHE_SESSION_DESC;
typedef enum D3D12_SHADER_CACHE_KIND_FLAGS
{
D3D12_SHADER_CACHE_KIND_FLAG_IMPLICIT_D3D_CACHE_FOR_DRIVER = 0x1,
D3D12_SHADER_CACHE_KIND_FLAG_IMPLICIT_D3D_CONVERSIONS = 0x2,
D3D12_SHADER_CACHE_KIND_FLAG_IMPLICIT_DRIVER_MANAGED = 0x4,
D3D12_SHADER_CACHE_KIND_FLAG_APPLICATION_MANAGED = 0x8,
} D3D12_SHADER_CACHE_KIND_FLAGS;
typedef enum D3D12_SHADER_CACHE_CONTROL_FLAGS
{
D3D12_SHADER_CACHE_CONTROL_FLAG_DISABLE = 0x1,
D3D12_SHADER_CACHE_CONTROL_FLAG_ENABLE = 0x2,
D3D12_SHADER_CACHE_CONTROL_FLAG_CLEAR = 0x4,
} D3D12_SHADER_CACHE_CONTROL_FLAGS;
[
uuid(dbb84c27-36ce-4fc9-b801-f048c46ac570),
object,
@ -3398,7 +3024,7 @@ interface ID3D12GraphicsCommandList : ID3D12CommandList
HRESULT Reset(ID3D12CommandAllocator *allocator, ID3D12PipelineState *initial_state);
void ClearState(ID3D12PipelineState *pipeline_state);
HRESULT ClearState(ID3D12PipelineState *pipeline_state);
void DrawInstanced(UINT vertex_count_per_instance, UINT instance_count,
UINT start_vertex_location, UINT start_instance_location);
@ -3604,17 +3230,6 @@ interface ID3D12GraphicsCommandList5 : ID3D12GraphicsCommandList4
void RSSetShadingRateImage(ID3D12Resource *image);
}
[
uuid(c3827890-e548-4cfa-96cf-5689a9370f80),
object,
local,
pointer_default(unique)
]
interface ID3D12GraphicsCommandList6 : ID3D12GraphicsCommandList5
{
void DispatchMesh(UINT x, UINT y, UINT z);
}
typedef enum D3D12_TILE_RANGE_FLAGS
{
D3D12_TILE_RANGE_FLAG_NONE = 0x0,
@ -3628,7 +3243,6 @@ typedef enum D3D12_TILE_MAPPING_FLAGS
D3D12_TILE_MAPPING_FLAG_NONE = 0x0,
D3D12_TILE_MAPPING_FLAG_NO_HAZARD = 0x1,
} D3D12_TILE_MAPPING_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_TILE_MAPPING_FLAGS);")
[
uuid(0ec870a6-5d7e-4c22-8cfc-5baae07616ed),
@ -3644,8 +3258,8 @@ interface ID3D12CommandQueue : ID3D12Pageable
ID3D12Heap *heap,
UINT range_count,
const D3D12_TILE_RANGE_FLAGS *range_flags,
const UINT *heap_range_offsets,
const UINT *range_tile_counts,
UINT *heap_range_offsets,
UINT *range_tile_counts,
D3D12_TILE_MAPPING_FLAGS flags);
void CopyTileMappings(ID3D12Resource *dst_resource,
@ -3676,9 +3290,7 @@ typedef enum D3D12_FENCE_FLAGS
D3D12_FENCE_FLAG_NONE = 0x0,
D3D12_FENCE_FLAG_SHARED = 0x1,
D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER = 0x2,
D3D12_FENCE_FLAG_NON_MONITORED = 0x4,
} D3D12_FENCE_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_FENCE_FLAGS);")
typedef enum D3D12_QUERY_HEAP_TYPE
{
@ -3695,7 +3307,6 @@ typedef enum D3D12_RESIDENCY_FLAGS
D3D12_RESIDENCY_FLAG_NONE = 0,
D3D12_RESIDENCY_FLAG_DENY_OVERBUDGET = 0,
} D3D12_RESIDENCY_FLAGS;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(D3D12_RESIDENCY_FLAGS);")
typedef struct D3D12_QUERY_HEAP_DESC
{
@ -3715,8 +3326,6 @@ typedef enum D3D12_INDIRECT_ARGUMENT_TYPE
D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW,
D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW,
D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW,
D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH_RAYS,
D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH_MESH,
} D3D12_INDIRECT_ARGUMENT_TYPE;
typedef struct D3D12_INDIRECT_ARGUMENT_DESC
@ -4102,67 +3711,6 @@ interface ID3D12Device6 : ID3D12Device5
D3D12_MEASUREMENTS_ACTION action, HANDLE event, BOOL further_measurements);
}
[
uuid(5c014b53-68a1-4b9b-8bd1-dd6046b9358b),
object,
local,
pointer_default(unique)
]
interface ID3D12Device7 : ID3D12Device6
{
HRESULT AddToStateObject(const D3D12_STATE_OBJECT_DESC *addition,
ID3D12StateObject *state_object, REFIID riid, void **new_state_object);
HRESULT CreateProtectedResourceSession1(
const D3D12_PROTECTED_RESOURCE_SESSION_DESC1 *desc,
REFIID riid, void **session);
}
[
uuid(9218e6bb-f944-4f7e-a75c-b1b2c7b701f3),
object,
local,
pointer_default(unique)
]
interface ID3D12Device8 : ID3D12Device7
{
D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo2(UINT visible_mask,
UINT resource_desc_count, const D3D12_RESOURCE_DESC1 *resource_descs,
D3D12_RESOURCE_ALLOCATION_INFO1 *resource_allocation_infos);
HRESULT CreateCommittedResource2(const D3D12_HEAP_PROPERTIES *heap_properties,
D3D12_HEAP_FLAGS heap_flags, const D3D12_RESOURCE_DESC1 *resource_desc,
D3D12_RESOURCE_STATES initial_state, const D3D12_CLEAR_VALUE *optimized_clear_value,
ID3D12ProtectedResourceSession *protected_session, REFIID riid, void **resource);
HRESULT CreatePlacedResource1(ID3D12Heap *heap, UINT64 heap_offset,
const D3D12_RESOURCE_DESC1 *resource_desc, D3D12_RESOURCE_STATES initial_state,
const D3D12_CLEAR_VALUE *optimized_clear_value, REFIID riid, void **resource);
void CreateSamplerFeedbackUnorderedAccessView(ID3D12Resource *target_resource,
ID3D12Resource *feedback_resource, D3D12_CPU_DESCRIPTOR_HANDLE descriptor);
void GetCopyableFootprints1(const D3D12_RESOURCE_DESC1 *resource_desc,
UINT first_sub_resource, UINT sub_resource_count, UINT64 base_offset,
D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts, UINT *row_count,
UINT64 *row_size, UINT64 *total_bytes);
}
[
uuid(4c80e962-f032-4f60-bc9e-ebc2cfa1d83c),
object,
local,
pointer_default(unique)
]
interface ID3D12Device9 : ID3D12Device8
{
HRESULT CreateShaderCacheSession(const D3D12_SHADER_CACHE_SESSION_DESC *desc,
REFIID riid, void **session);
HRESULT ShaderCacheControl(D3D12_SHADER_CACHE_KIND_FLAGS kinds,
D3D12_SHADER_CACHE_CONTROL_FLAGS control);
HRESULT CreateCommandQueue1(const D3D12_COMMAND_QUEUE_DESC *desc,
REFIID creator_id, REFIID riid, void **command_queue);
}
[
uuid(34ab647b-3cc8-46ac-841b-c0965645c046),
object,
@ -4217,13 +3765,3 @@ typedef HRESULT (__stdcall *PFN_D3D12_CREATE_DEVICE)(IUnknown *adapter,
typedef HRESULT (__stdcall *PFN_D3D12_GET_DEBUG_INTERFACE)(REFIID iid, void **debug);
[local] HRESULT __stdcall D3D12GetDebugInterface(REFIID iid, void **debug);
cpp_quote("DEFINE_GUID(D3D12ExperimentalShaderModels, 0x76f5573e, 0xf13a, 0x40f5, 0xb2, 0x97, 0x81, 0xce, 0x9e, 0x18, 0x93, 0x3f );")
cpp_quote("DEFINE_GUID(D3D12TiledResourceTier4, 0xc9c4725f, 0xa81a, 0x4f56, 0x8c, 0x5b, 0xc5, 0x10, 0x39, 0xd6, 0x94, 0xfb );")
cpp_quote("DEFINE_GUID(D3D12MetaCommand, 0xc734c97e, 0x8077, 0x48c8, 0x9f, 0xdc, 0xd9, 0xd1, 0xdd, 0x31, 0xdd, 0x77 );")
typedef HRESULT (__stdcall *PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(UINT num_features,
const IID *iids, void *config_structs, UINT *config_struct_sizes);
[local] HRESULT __stdcall D3D12EnableExperimentalFeatures(UINT num_features,
const IID *iids, void *config_structs, UINT *config_struct_sizes);

View File

@ -77,7 +77,6 @@ typedef enum D3D_FEATURE_LEVEL
D3D_FEATURE_LEVEL_11_1 = 0xb100,
D3D_FEATURE_LEVEL_12_0 = 0xc000,
D3D_FEATURE_LEVEL_12_1 = 0xc100,
D3D_FEATURE_LEVEL_12_2 = 0xc200,
} D3D_FEATURE_LEVEL;
[
@ -94,7 +93,3 @@ interface ID3D10Blob : IUnknown
typedef ID3D10Blob ID3DBlob;
cpp_quote("#define IID_ID3DBlob IID_ID3D10Blob")
cpp_quote("DEFINE_GUID(WKPDID_D3DDebugObjectName,0x429b8c22,0x9188,0x4b0c,0x87,0x42,0xac,0xb0,0xbf,0x85,0xc2,0x00);")
cpp_quote("DEFINE_GUID(WKPDID_D3DDebugObjectNameW,0x4cca5fd8,0x921f,0x42c8,0x85,0x66,0x70,0xca,0xf2,0xa9,0xb7,0x41);")
cpp_quote("DEFINE_GUID(WKPDID_CommentStringW,0xd0149dc0,0x90e8,0x4ec8,0x81,0x44,0xe9,0x00,0xad,0x26,0x6b,0xb2);")

View File

@ -1,37 +0,0 @@
/*
* * Copyright 2021 NVIDIA Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
import "vkd3d_d3d12.idl";
import "vkd3d_vk_includes.h";
[
uuid(11ea7a1a-0f6a-49bf-b612-3e30f8e201dd),
object,
local,
pointer_default(unique)
]
interface ID3D12DeviceExt : IUnknown
{
HRESULT GetVulkanHandles(VkInstance *vk_instance, VkPhysicalDevice *vk_physical_device, VkDevice *vk_device);
BOOL GetExtensionSupport(D3D12_VK_EXTENSION extension);
HRESULT CreateCubinComputeShaderWithName(const void *cubin_data, UINT32 cubin_size, UINT32 block_x, UINT32 block_y, UINT32 block_z, const char *shader_name, D3D12_CUBIN_DATA_HANDLE **handle);
HRESULT DestroyCubinComputeShader(D3D12_CUBIN_DATA_HANDLE *handle);
HRESULT GetCudaTextureObject(D3D12_CPU_DESCRIPTOR_HANDLE srv_handle, D3D12_CPU_DESCRIPTOR_HANDLE sampler_handle, UINT32 *cuda_texture_handle);
HRESULT GetCudaSurfaceObject(D3D12_CPU_DESCRIPTOR_HANDLE uav_handle, UINT32 *cuda_surface_handle);
HRESULT CaptureUAVInfo(D3D12_UAV_INFO *uav_info);
}

View File

@ -135,12 +135,5 @@ typedef enum DXGI_FORMAT
DXGI_FORMAT_A8P8 = 0x72,
DXGI_FORMAT_B4G4R4A4_UNORM = 0x73,
DXGI_FORMAT_P208 = 0x82,
DXGI_FORMAT_V208 = 0x83,
DXGI_FORMAT_V408 = 0x84,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE = 0xbd,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE = 0xbe,
DXGI_FORMAT_FORCE_UINT = 0xffffffff,
} DXGI_FORMAT;

View File

@ -22,15 +22,24 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <hashmap.h>
#include <vkd3d_types.h>
#include <vkd3d_d3d12.h>
#include <vkd3d.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
enum vkd3d_shader_structure_type
{
/* 1.2 */
VKD3D_SHADER_STRUCTURE_TYPE_SHADER_INTERFACE_INFO,
VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_ARGUMENTS,
VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO,
VKD3D_SHADER_STRUCTURE_TYPE_TRANSFORM_FEEDBACK_INFO,
VKD3D_SHADER_STRUCTURE_TYPE_DOMAIN_SHADER_COMPILE_ARGUMENTS,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE),
};
enum vkd3d_shader_compiler_option
{
VKD3D_SHADER_STRIP_DEBUG = 0x00000001,
@ -54,22 +63,11 @@ enum vkd3d_shader_visibility
typedef uint64_t vkd3d_shader_hash_t;
enum vkd3d_shader_meta_flags
{
VKD3D_SHADER_META_FLAG_REPLACED = 1 << 0,
VKD3D_SHADER_META_FLAG_USES_SUBGROUP_SIZE = 1 << 1,
VKD3D_SHADER_META_FLAG_USES_NATIVE_16BIT_OPERATIONS = 1 << 2,
};
struct vkd3d_shader_meta
{
vkd3d_shader_hash_t hash;
unsigned int cs_workgroup_size[3]; /* Only contains valid data if uses_subgroup_size is true. */
unsigned int patch_vertex_count; /* Relevant for HS. May be 0, in which case the patch vertex count is not known. */
unsigned int cs_required_wave_size; /* If non-zero, force a specific CS subgroup size. */
uint32_t flags; /* vkd3d_shader_meta_flags */
bool replaced;
};
STATIC_ASSERT(sizeof(struct vkd3d_shader_meta) == 32);
struct vkd3d_shader_code
{
@ -78,8 +76,6 @@ struct vkd3d_shader_code
struct vkd3d_shader_meta meta;
};
vkd3d_shader_hash_t vkd3d_shader_hash(const struct vkd3d_shader_code *shader);
enum vkd3d_shader_descriptor_type
{
VKD3D_SHADER_DESCRIPTOR_TYPE_UNKNOWN,
@ -99,12 +95,11 @@ struct vkd3d_shader_descriptor_binding
enum vkd3d_shader_binding_flag
{
VKD3D_SHADER_BINDING_FLAG_BUFFER = 0x00000001,
VKD3D_SHADER_BINDING_FLAG_IMAGE = 0x00000002,
VKD3D_SHADER_BINDING_FLAG_AUX_BUFFER = 0x00000004,
VKD3D_SHADER_BINDING_FLAG_BINDLESS = 0x00000008,
VKD3D_SHADER_BINDING_FLAG_RAW_VA = 0x00000010,
VKD3D_SHADER_BINDING_FLAG_RAW_SSBO = 0x00000020,
VKD3D_SHADER_BINDING_FLAG_BUFFER = 0x00000001,
VKD3D_SHADER_BINDING_FLAG_IMAGE = 0x00000002,
VKD3D_SHADER_BINDING_FLAG_COUNTER = 0x00000004,
VKD3D_SHADER_BINDING_FLAG_BINDLESS = 0x00000008,
VKD3D_SHADER_BINDING_FLAG_RAW_VA = 0x00000010,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_BINDING_FLAG),
};
@ -191,15 +186,13 @@ enum vkd3d_shader_interface_flag
{
VKD3D_SHADER_INTERFACE_PUSH_CONSTANTS_AS_UNIFORM_BUFFER = 0x00000001u,
VKD3D_SHADER_INTERFACE_BINDLESS_CBV_AS_STORAGE_BUFFER = 0x00000002u,
VKD3D_SHADER_INTERFACE_SSBO_OFFSET_BUFFER = 0x00000004u,
VKD3D_SHADER_INTERFACE_TYPED_OFFSET_BUFFER = 0x00000008u,
VKD3D_SHADER_INTERFACE_DESCRIPTOR_QA_BUFFER = 0x00000010u
};
struct vkd3d_shader_interface_info
{
enum vkd3d_shader_structure_type type;
const void *next;
unsigned int flags; /* vkd3d_shader_interface_flags */
unsigned int min_ssbo_alignment;
struct vkd3d_shader_descriptor_table_buffer descriptor_tables;
const struct vkd3d_shader_resource_binding *bindings;
@ -210,60 +203,6 @@ struct vkd3d_shader_interface_info
/* Ignored unless VKD3D_SHADER_INTERFACE_PUSH_CONSTANTS_AS_UNIFORM_BUFFER is set */
const struct vkd3d_shader_descriptor_binding *push_constant_ubo_binding;
/* Ignored unless VKD3D_SHADER_INTERFACE_SSBO_OFFSET_BUFFER or TYPED_OFFSET_BUFFER is set */
const struct vkd3d_shader_descriptor_binding *offset_buffer_binding;
#ifdef VKD3D_ENABLE_DESCRIPTOR_QA
/* Ignored unless VKD3D_SHADER_INTERFACE_DESCRIPTOR_QA_BUFFER is set. */
const struct vkd3d_shader_descriptor_binding *descriptor_qa_global_binding;
/* Ignored unless VKD3D_SHADER_INTERFACE_DESCRIPTOR_QA_BUFFER is set. */
const struct vkd3d_shader_descriptor_binding *descriptor_qa_heap_binding;
#endif
VkShaderStageFlagBits stage;
const struct vkd3d_shader_transform_feedback_info *xfb_info;
};
struct vkd3d_shader_descriptor_table
{
uint32_t table_index;
uint32_t binding_count;
struct vkd3d_shader_resource_binding *first_binding;
};
struct vkd3d_shader_root_constant
{
uint32_t constant_index;
uint32_t constant_count;
};
struct vkd3d_shader_root_descriptor
{
struct vkd3d_shader_resource_binding *binding;
uint32_t raw_va_root_descriptor_index;
};
struct vkd3d_shader_root_parameter
{
D3D12_ROOT_PARAMETER_TYPE parameter_type;
union
{
struct vkd3d_shader_root_constant constant;
struct vkd3d_shader_root_descriptor descriptor;
struct vkd3d_shader_descriptor_table descriptor_table;
};
};
struct vkd3d_shader_interface_local_info
{
const struct vkd3d_shader_root_parameter *local_root_parameters;
unsigned int local_root_parameter_count;
const struct vkd3d_shader_push_constant_buffer *shader_record_constant_buffers;
unsigned int shader_record_buffer_count;
const struct vkd3d_shader_resource_binding *bindings;
unsigned int binding_count;
uint32_t descriptor_size;
};
struct vkd3d_shader_transform_feedback_element
@ -276,8 +215,12 @@ struct vkd3d_shader_transform_feedback_element
uint8_t output_slot;
};
/* Extends vkd3d_shader_interface_info. */
struct vkd3d_shader_transform_feedback_info
{
enum vkd3d_shader_structure_type type;
const void *next;
const struct vkd3d_shader_transform_feedback_element *elements;
unsigned int element_count;
const unsigned int *buffer_strides;
@ -297,63 +240,13 @@ enum vkd3d_shader_target_extension
VKD3D_SHADER_TARGET_EXTENSION_NONE,
VKD3D_SHADER_TARGET_EXTENSION_SPV_EXT_DEMOTE_TO_HELPER_INVOCATION,
VKD3D_SHADER_TARGET_EXTENSION_READ_STORAGE_IMAGE_WITHOUT_FORMAT,
VKD3D_SHADER_TARGET_EXTENSION_SPV_KHR_INTEGER_DOT_PRODUCT,
VKD3D_SHADER_TARGET_EXTENSION_RAY_TRACING_PRIMITIVE_CULLING,
VKD3D_SHADER_TARGET_EXTENSION_SCALAR_BLOCK_LAYOUT,
/* When using scalar block layout with a vec3 array on a byte address buffer,
* there is diverging behavior across hardware.
* On AMD, robustness is checked per component, which means we can implement ByteAddressBuffer
* without further hackery. On NVIDIA, robustness does not seem to work this way, so it's either
* all in range, or all out of range. We can implement structured buffer vectorization of vec3,
* but not byte address buffer. */
VKD3D_SHADER_TARGET_EXTENSION_ASSUME_PER_COMPONENT_SSBO_ROBUSTNESS,
VKD3D_SHADER_TARGET_EXTENSION_BARYCENTRIC_KHR,
VKD3D_SHADER_TARGET_EXTENSION_MIN_PRECISION_IS_NATIVE_16BIT,
VKD3D_SHADER_TARGET_EXTENSION_COUNT,
};
enum vkd3d_shader_quirk
{
/* If sample or sample_b is used in control flow, force LOD 0.0 (which game should expect anyway).
* Works around specific, questionable shaders which rely on this to give sensible results,
* since LOD can become garbage on certain implementations, and even on native drivers
* the result is implementation defined.
* Outside of making this edge case well-defined in Vulkan or hacking driver compilers,
* this is the pragmatic solution.
* Hoisting gradients is not possible in all cases,
* and would not be worth it until it's a widespread problem. */
VKD3D_SHADER_QUIRK_FORCE_EXPLICIT_LOD_IN_CONTROL_FLOW = (1 << 0),
/* After every write to group shared memory, force a memory barrier.
* This works around buggy games which forget to use barrier(). */
VKD3D_SHADER_QUIRK_FORCE_TGSM_BARRIERS = (1 << 1),
/* For Position builtins in Output storage class, emit Invariant decoration.
* Normally, games have to emit Precise math for position, but if they forget ... */
VKD3D_SHADER_QUIRK_INVARIANT_POSITION = (1 << 2),
};
struct vkd3d_shader_quirk_hash
{
vkd3d_shader_hash_t shader_hash;
uint32_t quirks;
};
struct vkd3d_shader_quirk_info
{
const struct vkd3d_shader_quirk_hash *hashes;
unsigned int num_hashes;
uint32_t default_quirks;
/* Quirks which are ORed in with the other masks (including default_quirks).
* Used mostly for additional overrides from VKD3D_CONFIG. */
uint32_t global_quirks;
};
struct vkd3d_shader_compile_arguments
{
enum vkd3d_shader_structure_type type;
const void *next;
enum vkd3d_shader_target target;
unsigned int target_extension_count;
@ -365,8 +258,6 @@ struct vkd3d_shader_compile_arguments
bool dual_source_blending;
const unsigned int *output_swizzles;
unsigned int output_swizzle_count;
const struct vkd3d_shader_quirk_info *quirks;
};
enum vkd3d_tessellator_output_primitive
@ -385,6 +276,16 @@ enum vkd3d_tessellator_partitioning
VKD3D_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4,
};
/* Extends vkd3d_shader_compile_arguments. */
struct vkd3d_shader_domain_shader_compile_arguments
{
enum vkd3d_shader_structure_type type;
const void *next;
enum vkd3d_tessellator_output_primitive output_primitive;
enum vkd3d_tessellator_partitioning partitioning;
};
/* root signature 1.0 */
enum vkd3d_filter
{
@ -579,7 +480,6 @@ enum vkd3d_descriptor_range_flags
VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2,
VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8,
VKD3D_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 0x10000
};
struct vkd3d_descriptor_range1
@ -644,24 +544,23 @@ struct vkd3d_versioned_root_signature_desc
};
};
/* FIXME: Add support for 64 UAV bind slots. */
#define VKD3D_SHADER_MAX_UNORDERED_ACCESS_VIEWS 64
enum vkd3d_shader_uav_flag
{
VKD3D_SHADER_UAV_FLAG_READ_ACCESS = 0x00000001,
VKD3D_SHADER_UAV_FLAG_ATOMIC_COUNTER = 0x00000002,
VKD3D_SHADER_UAV_FLAG_ATOMIC_ACCESS = 0x00000004,
};
struct vkd3d_shader_scan_info
{
struct hash_map register_map;
bool use_vocp;
enum vkd3d_shader_structure_type type;
void *next;
bool early_fragment_tests;
bool has_side_effects;
bool needs_late_zs;
bool discards;
bool has_uav_counter;
unsigned int patch_vertex_count;
unsigned int uav_flags[VKD3D_SHADER_MAX_UNORDERED_ACCESS_VIEWS]; /* vkd3d_shader_uav_flags */
unsigned int sampler_comparison_mode_mask; /* 16 */
bool use_vocp;
};
enum vkd3d_component_type
@ -671,7 +570,6 @@ enum vkd3d_component_type
VKD3D_TYPE_INT = 2,
VKD3D_TYPE_FLOAT = 3,
VKD3D_TYPE_BOOL,
VKD3D_TYPE_DOUBLE,
VKD3D_TYPE_COUNT,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_COMPONENT_TYPE),
@ -754,11 +652,7 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code);
int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_versioned_root_signature_desc *root_signature,
vkd3d_shader_hash_t *compatibility_hash);
int vkd3d_shader_parse_root_signature_raw(const char *data, unsigned int data_size,
struct vkd3d_versioned_root_signature_desc *desc,
vkd3d_shader_hash_t *compatibility_hash);
struct vkd3d_versioned_root_signature_desc *root_signature);
void vkd3d_shader_free_root_signature(struct vkd3d_versioned_root_signature_desc *root_signature);
/* FIXME: Add support for returning error messages (ID3DBlob). */
@ -771,90 +665,18 @@ int vkd3d_shader_convert_root_signature(struct vkd3d_versioned_root_signature_de
int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_scan_info *scan_info);
/* If value cannot be determined, *patch_vertex_count returns 0. */
int vkd3d_shader_scan_patch_vertex_count(const struct vkd3d_shader_code *dxbc,
unsigned int *patch_vertex_count);
int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_signature *signature);
int vkd3d_shader_parse_output_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_signature *signature);
struct vkd3d_shader_signature_element *vkd3d_shader_find_signature_element(
const struct vkd3d_shader_signature *signature, const char *semantic_name,
unsigned int semantic_index, unsigned int stream_index);
void vkd3d_shader_free_shader_signature(struct vkd3d_shader_signature *signature);
/* For DXR, use special purpose entry points since there's a lot of special purpose reflection required. */
struct vkd3d_shader_library_entry_point
{
unsigned int identifier;
VkShaderStageFlagBits stage;
WCHAR *mangled_entry_point;
WCHAR *plain_entry_point;
char *real_entry_point;
};
enum vkd3d_shader_subobject_kind
{
/* Matches DXIL for simplicity. */
VKD3D_SHADER_SUBOBJECT_KIND_STATE_OBJECT_CONFIG = 0,
VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE = 1,
VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE = 2,
VKD3D_SHADER_SUBOBJECT_KIND_SUBOBJECT_TO_EXPORTS_ASSOCIATION = 8,
VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG = 9,
VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG = 10,
VKD3D_SHADER_SUBOBJECT_KIND_HIT_GROUP = 11,
VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1 = 12,
};
struct vkd3d_shader_library_subobject
{
enum vkd3d_shader_subobject_kind kind;
unsigned int dxil_identifier;
/* All const pointers here point directly to the DXBC blob,
* so they do not need to be freed.
* Fortunately for us, the C strings are zero-terminated in the blob itself. */
/* In the blob, ASCII is used as identifier, where API uses wide strings, sigh ... */
const char *name;
union
{
D3D12_RAYTRACING_PIPELINE_CONFIG1 pipeline_config;
D3D12_RAYTRACING_SHADER_CONFIG shader_config;
D3D12_STATE_OBJECT_CONFIG object_config;
/* Duped strings because API wants wide strings for no good reason. */
D3D12_HIT_GROUP_DESC hit_group;
D3D12_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION association;
struct
{
const void *data;
size_t size;
} payload;
} data;
};
int vkd3d_shader_dxil_append_library_entry_points_and_subobjects(
const D3D12_DXIL_LIBRARY_DESC *library_desc,
unsigned int identifier,
struct vkd3d_shader_library_entry_point **entry_points,
size_t *entry_point_size, size_t *entry_point_count,
struct vkd3d_shader_library_subobject **subobjects,
size_t *subobjects_size, size_t *subobjects_count);
void vkd3d_shader_dxil_free_library_entry_points(struct vkd3d_shader_library_entry_point *entry_points, size_t count);
void vkd3d_shader_dxil_free_library_subobjects(struct vkd3d_shader_library_subobject *subobjects, size_t count);
int vkd3d_shader_compile_dxil_export(const struct vkd3d_shader_code *dxil,
const char *export,
struct vkd3d_shader_code *spirv,
const struct vkd3d_shader_interface_info *shader_interface_info,
const struct vkd3d_shader_interface_local_info *shader_interface_local_info,
const struct vkd3d_shader_compile_arguments *compiler_args);
uint32_t vkd3d_shader_compile_arguments_select_quirks(
const struct vkd3d_shader_compile_arguments *args, vkd3d_shader_hash_t hash);
uint64_t vkd3d_shader_get_revision(void);
int vkd3d_shader_supports_dxil(void);
#endif /* VKD3D_SHADER_NO_PROTOTYPES */
@ -868,8 +690,7 @@ typedef int (*PFN_vkd3d_shader_compile_dxbc)(const struct vkd3d_shader_code *dxb
typedef void (*PFN_vkd3d_shader_free_shader_code)(struct vkd3d_shader_code *code);
typedef int (*PFN_vkd3d_shader_parse_root_signature)(const struct vkd3d_shader_code *dxbc,
struct vkd3d_versioned_root_signature_desc *root_signature,
vkd3d_shader_hash_t *compatibility_hash);
struct vkd3d_versioned_root_signature_desc *root_signature);
typedef void (*PFN_vkd3d_shader_free_root_signature)(struct vkd3d_versioned_root_signature_desc *root_signature);
typedef int (*PFN_vkd3d_shader_serialize_root_signature)(
@ -880,6 +701,8 @@ typedef int (*PFN_vkd3d_shader_convert_root_signature)(struct vkd3d_versioned_ro
typedef int (*PFN_vkd3d_shader_scan_dxbc)(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_scan_info *scan_info);
typedef int (*PFN_vkd3d_shader_scan_patch_vertex_count)(const struct vkd3d_shader_code *dxbc,
unsigned int *patch_vertex_count);
typedef int (*PFN_vkd3d_shader_parse_input_signature)(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_signature *signature);

View File

@ -36,4 +36,4 @@ interface IWineDXGISwapChainFactory : IUnknown
[in] IDXGIOutput *pRestrictToOutput,
[out] IDXGISwapChain1 **ppSwapChain
);
}
}

View File

@ -30,42 +30,22 @@ extern "C" {
#define VKD3D_WAIT_FAILED (~0u)
#define VKD3D_INFINITE (~0u)
#ifdef _WIN32
# ifdef _MSC_VER
# define VKD3D_UTILS_EXPORT
# else
/* We need to specify the __declspec(dllexport) attribute
* on MinGW because otherwise the stdcall aliases/fixups
* don't get exported.
*/
# ifdef VKD3D_UTILS_EXPORTS
# define VKD3D_UTILS_EXPORT __declspec(dllexport)
# else
# define VKD3D_UTILS_EXPORT __declspec(dllimport)
# endif
# endif
#elif defined(__GNUC__)
# define VKD3D_UTILS_EXPORT DECLSPEC_VISIBLE
#else
# define VKD3D_UTILS_EXPORT
#endif
/* 1.0 */
VKD3D_UTILS_EXPORT HANDLE vkd3d_create_event(void);
VKD3D_UTILS_EXPORT HRESULT vkd3d_signal_event(HANDLE event);
VKD3D_UTILS_EXPORT unsigned int vkd3d_wait_event(HANDLE event, unsigned int milliseconds);
VKD3D_UTILS_EXPORT void vkd3d_destroy_event(HANDLE event);
HANDLE vkd3d_create_event(void);
HRESULT vkd3d_signal_event(HANDLE event);
unsigned int vkd3d_wait_event(HANDLE event, unsigned int milliseconds);
void vkd3d_destroy_event(HANDLE event);
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL feature_level, REFIID iid, void **device);
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size, REFIID iid, void **deserializer);
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12GetDebugInterface(REFIID iid, void **debug);
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *desc,
HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL feature_level, REFIID iid, void **device);
HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size, REFIID iid, void **deserializer);
HRESULT WINAPI D3D12GetDebugInterface(REFIID iid, void **debug);
HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *desc,
D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
/* 1.2 */
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateVersionedRootSignatureDeserializer(const void *data,
HRESULT WINAPI D3D12CreateVersionedRootSignatureDeserializer(const void *data,
SIZE_T data_size, REFIID iid, void **deserializer);
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
HRESULT WINAPI D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
ID3DBlob **blob, ID3DBlob **error_blob);
#ifdef __cplusplus

View File

@ -1,58 +0,0 @@
/*
* * Copyright 2021 NVIDIA Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __VKD3D_VK_INCLUDES_H
#define __VKD3D_VK_INCLUDES_H
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
typedef struct VkCuFunctionNVX_T *VkCuFunctionNVX;
typedef struct VkCuModuleNVX_T *VkCuModuleNVX;
#else
typedef UINT64 VkCuFunctionNVX;
typedef UINT64 VkCuModuleNVX;
#endif
typedef struct VkPhysicalDevice_T *VkPhysicalDevice;
typedef struct VkCommandBuffer_T *VkCommandBuffer;
typedef struct VkInstance_T *VkInstance;
typedef struct VkDevice_T *VkDevice;
typedef enum D3D12_VK_EXTENSION
{
D3D12_VK_NVX_BINARY_IMPORT = 0x1,
D3D12_VK_NVX_IMAGE_VIEW_HANDLE = 0x2
} D3D12_VK_EXTENSION;
typedef struct D3D12_CUBIN_DATA_HANDLE
{
VkCuFunctionNVX vkCuFunction;
VkCuModuleNVX vkCuModule;
UINT32 blockX;
UINT32 blockY;
UINT32 blockZ;
} D3D12_CUBIN_DATA_HANDLE;
typedef struct D3D12_UAV_INFO
{
UINT32 version;
UINT32 surfaceHandle;
UINT64 gpuVAStart;
UINT64 gpuVASize;
} D3D12_UAV_INFO;
#endif // __VKD3D_VK_INCLUDES_H

View File

@ -42,20 +42,8 @@
#define WIDL_C_INLINE_WRAPPERS
#include <vkd3d_windows.h>
/* Vulkan headers include static const declarations. Enable static keyword for
* them.
*/
#ifdef __MINGW32__
# undef static
#endif
#define VK_USE_PLATFORM_WIN32_KHR
#include <vulkan/vulkan.h>
#include "private/vulkan_private_extensions.h"
#ifdef __MINGW32__
# define static
#endif
#include <dxgi1_6.h>
@ -69,8 +57,6 @@
#define __vkd3d_dxgi1_4_h__
#include <vkd3d_swapchain_factory.h>
#include <vkd3d_command_list_vkd3d_ext.h>
#include <vkd3d_device_vkd3d_ext.h>
#include <vkd3d_d3d12.h>
#include <vkd3d_d3d12sdklayers.h>
@ -83,4 +69,4 @@
#define VKD3D_NO_VULKAN_H
#include <vkd3d.h>
#endif
#endif

View File

@ -77,7 +77,6 @@ typedef unsigned long UINT64;
typedef long long DECLSPEC_ALIGN(8) INT64;
typedef unsigned long long DECLSPEC_ALIGN(8) UINT64;
# endif
typedef INT64 LONG64;
typedef long LONG_PTR;
typedef unsigned long ULONG_PTR;
@ -88,9 +87,6 @@ typedef void *HANDLE;
typedef const WCHAR* LPCWSTR;
#define _fseeki64(a, b, c) fseeko64(a, b, c)
#define _ftelli64(a) ftello64(a)
/* GUID */
# ifdef __WIDL__
typedef struct
@ -115,18 +111,18 @@ typedef GUID IID;
# ifdef INITGUID
# ifndef __cplusplus
# define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
const GUID name; \
const GUID name DECLSPEC_HIDDEN; \
const GUID name = \
{ l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 }}
# else
# define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name; \
EXTERN_C const GUID name DECLSPEC_HIDDEN; \
EXTERN_C const GUID name = \
{ l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 }}
# endif
# else
# define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name;
EXTERN_C const GUID name DECLSPEC_HIDDEN;
# endif /* INITGUID */
/* __uuidof emulation */
@ -225,6 +221,18 @@ typedef struct SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES;
#endif /* _WIN32 */
/* Define DECLSPEC_HIDDEN */
#ifndef DECLSPEC_HIDDEN
# if defined(__MINGW32__)
# define DECLSPEC_HIDDEN
# elif defined(__GNUC__)
# define DECLSPEC_HIDDEN __attribute__((visibility("hidden")))
# else
# define DECLSPEC_HIDDEN
# endif
#endif /* DECLSPEC_HIDDEN */
/* Define min() & max() macros */
#ifndef NOMINMAX
# ifndef min

View File

@ -3,9 +3,9 @@ LIBRARY d3d12.dll
EXPORTS
D3D12CreateDevice @101
D3D12GetDebugInterface @102
D3D12CreateRootSignatureDeserializer
D3D12CreateVersionedRootSignatureDeserializer
D3D12CreateRootSignatureDeserializer @107
D3D12CreateVersionedRootSignatureDeserializer @108
D3D12EnableExperimentalFeatures
D3D12SerializeRootSignature
D3D12SerializeVersionedRootSignature
D3D12EnableExperimentalFeatures @110
D3D12SerializeRootSignature @115
D3D12SerializeVersionedRootSignature @116

View File

@ -159,10 +159,44 @@ done:
return hr;
}
static VkPhysicalDevice d3d12_find_physical_device(struct vkd3d_instance *instance,
static BOOL check_vk_instance_extension(VkInstance vk_instance,
PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr, const char *name)
{
PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties;
VkExtensionProperties *properties;
BOOL ret = FALSE;
unsigned int i;
uint32_t count;
pfn_vkEnumerateInstanceExtensionProperties
= (void *)pfn_vkGetInstanceProcAddr(vk_instance, "vkEnumerateInstanceExtensionProperties");
if (pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL) < 0)
return FALSE;
if (!(properties = calloc(count, sizeof(*properties))))
return FALSE;
if (pfn_vkEnumerateInstanceExtensionProperties(NULL, &count, properties) >= 0)
{
for (i = 0; i < count; ++i)
{
if (!strcmp(properties[i].extensionName, name))
{
ret = TRUE;
break;
}
}
}
free(properties);
return ret;
}
static VkPhysicalDevice d3d12_get_vk_physical_device(struct vkd3d_instance *instance,
PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr, struct DXGI_ADAPTER_DESC *adapter_desc)
{
PFN_vkGetPhysicalDeviceProperties2 pfn_vkGetPhysicalDeviceProperties2;
PFN_vkGetPhysicalDeviceProperties2 pfn_vkGetPhysicalDeviceProperties2 = NULL;
PFN_vkGetPhysicalDeviceProperties pfn_vkGetPhysicalDeviceProperties;
PFN_vkEnumeratePhysicalDevices pfn_vkEnumeratePhysicalDevices;
VkPhysicalDevice vk_physical_device = VK_NULL_HANDLE;
@ -177,8 +211,10 @@ static VkPhysicalDevice d3d12_find_physical_device(struct vkd3d_instance *instan
vk_instance = vkd3d_instance_get_vk_instance(instance);
pfn_vkEnumeratePhysicalDevices = (void *)pfn_vkGetInstanceProcAddr(vk_instance, "vkEnumeratePhysicalDevices");
pfn_vkGetPhysicalDeviceProperties = (void *)pfn_vkGetInstanceProcAddr(vk_instance, "vkGetPhysicalDeviceProperties");
pfn_vkGetPhysicalDeviceProperties2 = (void *)pfn_vkGetInstanceProcAddr(vk_instance, "vkGetPhysicalDeviceProperties2");
if (check_vk_instance_extension(vk_instance, pfn_vkGetInstanceProcAddr, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
pfn_vkGetPhysicalDeviceProperties2 = (void *)pfn_vkGetInstanceProcAddr(vk_instance, "vkGetPhysicalDeviceProperties2KHR");
if ((vr = pfn_vkEnumeratePhysicalDevices(vk_instance, &count, NULL)) < 0)
{
@ -197,51 +233,42 @@ static VkPhysicalDevice d3d12_find_physical_device(struct vkd3d_instance *instan
if ((vr = pfn_vkEnumeratePhysicalDevices(vk_instance, &count, vk_physical_devices)) < 0)
goto done;
TRACE("Matching adapters by LUIDs.\n");
if (pfn_vkGetPhysicalDeviceProperties2)
{
TRACE("Matching adapters by LUIDs.\n");
for (i = 0; i < count; ++i)
{
memset(&id_properties, 0, sizeof(id_properties));
id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
properties2.pNext = &id_properties;
pfn_vkGetPhysicalDeviceProperties2(vk_physical_devices[i], &properties2);
if (!memcmp(id_properties.deviceLUID, &adapter_desc->AdapterLuid, VK_LUID_SIZE))
{
vk_physical_device = vk_physical_devices[i];
break;
}
}
}
TRACE("Matching adapters by PCI IDs.\n");
for (i = 0; i < count; ++i)
{
pfn_vkGetPhysicalDeviceProperties(vk_physical_devices[i], &properties2.properties);
/* Skip over physical devices below our minimum API version */
if (properties2.properties.apiVersion < VKD3D_MIN_API_VERSION)
{
WARN("Skipped adapter %s as it is below our minimum API version.", properties2.properties.deviceName);
continue;
}
id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
id_properties.pNext = NULL;
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
properties2.pNext = &id_properties;
pfn_vkGetPhysicalDeviceProperties2(vk_physical_devices[i], &properties2);
if (id_properties.deviceLUIDValid && !memcmp(id_properties.deviceLUID, &adapter_desc->AdapterLuid, VK_LUID_SIZE))
if (properties2.properties.deviceID == adapter_desc->DeviceId &&
properties2.properties.vendorID == adapter_desc->VendorId)
{
vk_physical_device = vk_physical_devices[i];
break;
}
}
if (!vk_physical_device)
{
TRACE("Matching adapters by PCI IDs.\n");
for (i = 0; i < count; ++i)
{
pfn_vkGetPhysicalDeviceProperties(vk_physical_devices[i], &properties2.properties);
if (properties2.properties.deviceID == adapter_desc->DeviceId &&
properties2.properties.vendorID == adapter_desc->VendorId)
{
vk_physical_device = vk_physical_devices[i];
break;
}
}
}
if (!vk_physical_device)
{
FIXME("Could not find Vulkan physical device for DXGI adapter.\n");
@ -257,6 +284,7 @@ done:
HRESULT WINAPI DLLEXPORT D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL minimum_feature_level,
REFIID iid, void **device)
{
struct vkd3d_optional_instance_extensions_info optional_extensions_info;
struct vkd3d_instance_create_info instance_create_info;
PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr;
struct vkd3d_device_create_info device_create_info;
@ -270,6 +298,10 @@ HRESULT WINAPI DLLEXPORT D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
};
static const char * const optional_instance_extensions[] =
{
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
};
static const char * const device_extensions[] =
{
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
@ -293,14 +325,20 @@ HRESULT WINAPI DLLEXPORT D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL
goto done;
}
optional_extensions_info.type = VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO;
optional_extensions_info.next = NULL;
optional_extensions_info.extensions = optional_instance_extensions;
optional_extensions_info.extension_count = ARRAYSIZE(optional_instance_extensions);
instance_create_info.type = VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_create_info.next = &optional_extensions_info;
instance_create_info.pfn_signal_event = d3d12_signal_event;
instance_create_info.pfn_create_thread = d3d12_create_thread;
instance_create_info.pfn_join_thread = d3d12_join_thread;
instance_create_info.wchar_size = sizeof(WCHAR);
instance_create_info.pfn_vkGetInstanceProcAddr = pfn_vkGetInstanceProcAddr;
instance_create_info.instance_extensions = instance_extensions;
instance_create_info.instance_extension_count = ARRAYSIZE(instance_extensions);
instance_create_info.optional_instance_extensions = NULL;
instance_create_info.optional_instance_extension_count = 0;
if (FAILED(hr = vkd3d_create_instance(&instance_create_info, &instance)))
{
@ -308,14 +346,14 @@ HRESULT WINAPI DLLEXPORT D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL
goto done;
}
device_create_info.type = VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.next = NULL;
device_create_info.minimum_feature_level = minimum_feature_level;
device_create_info.instance = instance;
device_create_info.instance_create_info = NULL;
device_create_info.vk_physical_device = d3d12_find_physical_device(instance, pfn_vkGetInstanceProcAddr, &adapter_desc);
device_create_info.vk_physical_device = d3d12_get_vk_physical_device(instance, pfn_vkGetInstanceProcAddr, &adapter_desc);
device_create_info.device_extensions = device_extensions;
device_create_info.device_extension_count = ARRAYSIZE(device_extensions);
device_create_info.optional_device_extensions = NULL;
device_create_info.optional_device_extension_count = 0;
device_create_info.parent = (IUnknown *)dxgi_adapter;
memcpy(&device_create_info.adapter_luid, &adapter_desc.AdapterLuid, VK_LUID_SIZE);

View File

@ -2,15 +2,15 @@ d3d12_src = [
'main.c'
]
d3d12_lib = shared_library('d3d12', d3d12_src,
d3d12_lib = shared_library('d3d12', d3d12_src, vkd3d_headers,
name_prefix : '', # libd3d12.dll -> d3d12.dll
dependencies : [ vkd3d_dep, lib_dxgi ],
include_directories : vkd3d_private_includes,
install : true,
objects : not vkd3d_is_msvc ? 'd3d12.def' : [],
objects : not vkd3d_msvc ? 'd3d12.def' : [],
vs_module_defs : 'd3d12.def',
override_options : [ 'c_std='+vkd3d_c_std ])
d3d12_dep = declare_dependency(
link_with : d3d12_lib,
include_directories : vkd3d_public_includes)
include_directories : vkd3d_public_includes)

View File

@ -2,6 +2,6 @@ subdir('vkd3d-common')
subdir('vkd3d-shader')
subdir('vkd3d')
subdir('vkd3d-utils')
if enable_d3d12
if enable_standalone_d3d12
subdir('d3d12')
endif
endif

View File

@ -20,8 +20,6 @@
#include "vkd3d_debug.h"
#include "vkd3d_threads.h"
#include "vkd3d_platform.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
@ -41,7 +39,6 @@ static const char *debug_level_names[] =
/* VKD3D_DBG_LEVEL_UNKNOWN */ NULL,
/* VKD3D_DBG_LEVEL_NONE */ "none",
/* VKD3D_DBG_LEVEL_ERR */ "err",
/* VKD3D_DBG_LEVEL_INFO */ "info",
/* VKD3D_DBG_LEVEL_FIXME */ "fixme",
/* VKD3D_DBG_LEVEL_WARN */ "warn",
/* VKD3D_DBG_LEVEL_TRACE */ "trace",
@ -60,13 +57,13 @@ static FILE *vkd3d_log_file;
static void vkd3d_dbg_init_once(void)
{
char vkd3d_debug[VKD3D_PATH_MAX];
const char *vkd3d_debug;
unsigned int channel, i;
for (channel = 0; channel < VKD3D_DBG_CHANNEL_COUNT; channel++)
{
if (!vkd3d_get_env_var(env_for_channel[channel], vkd3d_debug, sizeof(vkd3d_debug)))
strncpy(vkd3d_debug, "", VKD3D_PATH_MAX);
if (!(vkd3d_debug = getenv(env_for_channel[channel])))
vkd3d_debug = "";
for (i = 1; i < ARRAY_SIZE(debug_level_names); ++i)
if (!strcmp(debug_level_names[i], vkd3d_debug))
@ -77,7 +74,7 @@ static void vkd3d_dbg_init_once(void)
vkd3d_dbg_level[channel] = VKD3D_DBG_LEVEL_FIXME;
}
if (vkd3d_get_env_var("VKD3D_LOG_FILE", vkd3d_debug, sizeof(vkd3d_debug)))
if ((vkd3d_debug = getenv("VKD3D_LOG_FILE")))
{
vkd3d_log_file = fopen(vkd3d_debug, "w");
if (!vkd3d_log_file)
@ -123,7 +120,7 @@ void vkd3d_dbg_printf(enum vkd3d_dbg_channel channel, enum vkd3d_dbg_level level
va_start(args, fmt);
spinlock_acquire(&spin);
fprintf(log_file, "%04x:%s:%s: ", tid, debug_level_names[level], function);
fprintf(log_file, "%u:%s:%s: ", tid, debug_level_names[level], function);
vfprintf(log_file, fmt, args);
spinlock_release(&spin);
va_end(args);
@ -221,10 +218,10 @@ const char *debugstr_a(const char *str)
return buffer;
}
const char *debugstr_w(const WCHAR *wstr)
static const char *debugstr_w16(const uint16_t *wstr)
{
char *buffer, *ptr;
WCHAR c;
uint16_t c;
if (!wstr)
return "(null)";
@ -281,13 +278,80 @@ const char *debugstr_w(const WCHAR *wstr)
return buffer;
}
static const char *debugstr_w32(const uint32_t *wstr)
{
char *buffer, *ptr;
uint32_t c;
if (!wstr)
return "(null)";
ptr = buffer = get_buffer();
*ptr++ = '"';
while ((c = *wstr++) && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 10)
{
int escape_char;
switch (c)
{
case '"':
case '\\':
case '\n':
case '\r':
case '\t':
escape_char = c;
break;
default:
escape_char = 0;
break;
}
if (escape_char)
{
*ptr++ = '\\';
*ptr++ = escape_char;
continue;
}
if (isprint(c))
{
*ptr++ = c;
}
else
{
*ptr++ = '\\';
sprintf(ptr, "%04x", c);
ptr += 4;
}
}
*ptr++ = '"';
if (c)
{
*ptr++ = '.';
*ptr++ = '.';
*ptr++ = '.';
}
*ptr = '\0';
return buffer;
}
const char *debugstr_w(const WCHAR *wstr, size_t wchar_size)
{
if (wchar_size == 2)
return debugstr_w16((const uint16_t *)wstr);
return debugstr_w32((const uint32_t *)wstr);
}
unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value)
{
char value[VKD3D_PATH_MAX];
const char *value = getenv(name);
unsigned long r;
char *end_ptr;
if (vkd3d_get_env_var(name, value, sizeof(value)) && strlen(value) > 0)
if (value)
{
errno = 0;
r = strtoul(value, &end_ptr, 0);

View File

@ -1,188 +0,0 @@
/*
* Copyright 2022 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_file_utils.h"
#include "vkd3d_debug.h"
/* For disk cache. */
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#else
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#endif
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
bool vkd3d_file_rename_overwrite(const char *from_path, const char *to_path)
{
#ifdef _WIN32
DWORD code = ERROR_SUCCESS;
if (!MoveFileA(from_path, to_path))
{
code = GetLastError();
if (code == ERROR_ALREADY_EXISTS)
{
code = ERROR_SUCCESS;
if (!ReplaceFileA(to_path, from_path, NULL, 0, NULL, NULL))
code = GetLastError();
}
}
return code == ERROR_SUCCESS;
#else
return rename(from_path, to_path) == 0;
#endif
}
bool vkd3d_file_rename_no_replace(const char *from_path, const char *to_path)
{
#ifdef _WIN32
DWORD code = ERROR_SUCCESS;
if (!MoveFileA(from_path, to_path))
code = GetLastError();
return code == ERROR_SUCCESS;
#else
return renameat2(AT_FDCWD, from_path, AT_FDCWD, to_path, RENAME_NOREPLACE) == 0;
#endif
}
bool vkd3d_file_delete(const char *path)
{
#ifdef _WIN32
DWORD code = ERROR_SUCCESS;
if (!DeleteFileA(path))
code = GetLastError();
return code == ERROR_SUCCESS;
#else
return unlink(path) == 0;
#endif
}
FILE *vkd3d_file_open_exclusive_write(const char *path)
{
#ifdef _WIN32
/* From Fossilize. AFAIK, there is no direct way to make this work with FILE interface, so have to roundtrip
* through jank POSIX layer.
* wbx kinda works, but Wine warns about it, despite it working anyways.
* Older MSVC runtimes do not support wbx. */
FILE *file = NULL;
int fd;
fd = _open(path, _O_BINARY | _O_WRONLY | _O_CREAT | _O_EXCL | _O_TRUNC | _O_SEQUENTIAL,
_S_IWRITE | _S_IREAD);
if (fd >= 0)
{
file = _fdopen(fd, "wb");
/* _fdopen takes ownership. */
if (!file)
_close(fd);
}
return file;
#else
return fopen(path, "wbx");
#endif
}
void vkd3d_file_unmap(struct vkd3d_memory_mapped_file *file)
{
if (file->mapped)
{
#ifdef _WIN32
UnmapViewOfFile(file->mapped);
#else
munmap(file->mapped, file->mapped_size);
#endif
}
memset(file, 0, sizeof(*file));
}
bool vkd3d_file_map_read_only(const char *path, struct vkd3d_memory_mapped_file *file)
{
#ifdef _WIN32
DWORD size_hi, size_lo;
HANDLE file_mapping;
HANDLE handle;
#else
struct stat stat_buf;
int fd;
#endif
file->mapped = NULL;
file->mapped_size = 0;
#ifdef _WIN32
handle = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
INVALID_HANDLE_VALUE);
if (handle == INVALID_HANDLE_VALUE)
goto out;
size_lo = GetFileSize(handle, &size_hi);
file->mapped_size = size_lo | (((uint64_t)size_hi) << 32);
file_mapping = CreateFileMappingA(handle, NULL, PAGE_READONLY, 0, 0, NULL);
if (file_mapping == INVALID_HANDLE_VALUE)
goto out;
file->mapped = MapViewOfFile(file_mapping, FILE_MAP_READ, 0, 0, file->mapped_size);
CloseHandle(file_mapping);
file_mapping = INVALID_HANDLE_VALUE;
if (!file->mapped)
{
ERR("Failed to MapViewOfFile for %s.\n", path);
goto out;
}
out:
if (handle != INVALID_HANDLE_VALUE)
CloseHandle(handle);
#else
fd = open(path, O_RDONLY);
if (fd < 0)
goto out;
if (fstat(fd, &stat_buf) < 0)
{
ERR("Failed to fstat pipeline cache.\n");
goto out;
}
/* Map private to make sure we get CoW behavior in case someone clobbers
* the cache while in flight. We need to read data directly out of the cache. */
file->mapped = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (file->mapped != MAP_FAILED)
file->mapped_size = stat_buf.st_size;
else
goto out;
out:
if (fd >= 0)
close(fd);
#endif
if (!file->mapped)
file->mapped_size = 0;
return file->mapped != NULL;
}

View File

@ -2,16 +2,13 @@ vkd3d_common_src = [
'debug.c',
'memory.c',
'utf8.c',
'profiling.c',
'string.c',
'file_utils.c',
'platform.c',
'profiling.c'
]
vkd3d_common_lib = static_library('vkd3d_common', vkd3d_common_src, vkd3d_header_files,
vkd3d_common_lib = static_library('vkd3d_common', vkd3d_common_src,
include_directories : vkd3d_private_includes,
override_options : [ 'c_std='+vkd3d_c_std ])
vkd3d_common_dep = declare_dependency(
link_with : vkd3d_common_lib,
include_directories : [ vkd3d_public_includes, vkd3d_common_lib.private_dir_include() ])
include_directories : vkd3d_public_includes)

View File

@ -21,7 +21,6 @@
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_profiling.h"
#include "vkd3d_platform.h"
#include "vkd3d_threads.h"
#include "vkd3d_debug.h"
#include <stdlib.h>
@ -125,10 +124,8 @@ static void vkd3d_init_profiling_path(const char *path)
static void vkd3d_init_profiling_once(void)
{
char path[VKD3D_PATH_MAX];
vkd3d_get_env_var("VKD3D_PROFILE_PATH", path, sizeof(path));
if (strlen(path) > 0)
const char *path = getenv("VKD3D_PROFILE_PATH");
if (path)
vkd3d_init_profiling_path(path);
}

View File

@ -1,176 +0,0 @@
/*
* Copyright 2021 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_string.h"
#include "vkd3d_memory.h"
STATIC_ASSERT(sizeof(WCHAR) == sizeof(uint16_t));
char *vkd3d_strdup(const char *str)
{
/* strdup() is actually not standard. */
char *duped;
size_t len;
len = strlen(str) + 1;
duped = vkd3d_malloc(len);
if (duped)
memcpy(duped, str, len);
return duped;
}
char *vkd3d_strdup_n(const char *str, size_t n)
{
char *duped;
size_t len;
len = strnlen(str, n);
duped = vkd3d_malloc(len + 1);
if (duped)
{
memcpy(duped, str, len);
duped[len] = '\0';
}
return duped;
}
WCHAR *vkd3d_wstrdup(const WCHAR *str)
{
WCHAR *duped;
size_t len;
len = vkd3d_wcslen(str) + 1;
duped = vkd3d_malloc(len * sizeof(WCHAR));
if (duped)
memcpy(duped, str, len * sizeof(WCHAR));
return duped;
}
bool vkd3d_export_strequal(const WCHAR *a, const WCHAR *b)
{
if (!a || !b)
return false;
while (*a != '\0' && *b != '\0')
{
if (*a != *b)
return false;
a++;
b++;
}
return *a == *b;
}
bool vkd3d_export_strequal_mixed(const WCHAR *a, const char *b)
{
if (!a || !b)
return false;
while (*a != '\0' && *b != '\0')
{
if (*a != *b)
return false;
a++;
b++;
}
return *a == *b;
}
bool vkd3d_export_strequal_substr(const WCHAR *a, size_t expected_n, const WCHAR *b)
{
size_t n = 0;
if (!a || !b)
return false;
while (*a != '\0' && *b != '\0' && n < expected_n)
{
if (*a != *b)
return false;
a++;
b++;
n++;
}
return n == expected_n && *b == '\0';
}
WCHAR *vkd3d_dup_entry_point(const char *str)
{
return vkd3d_dup_entry_point_n(str, strlen(str));
}
WCHAR *vkd3d_dup_entry_point_n(const char *str, size_t len)
{
WCHAR *duped;
size_t i;
duped = vkd3d_malloc((len + 1) * sizeof(WCHAR));
if (!duped)
return NULL;
for (i = 0; i < len; i++)
duped[i] = (unsigned char)str[i];
duped[len] = 0;
return duped;
}
static bool is_valid_identifier_character(char v)
{
return (v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z') || v == '_' || (v >= '0' && v <= '9');
}
static const char *vkd3d_manged_entry_point_scan(const char *entry, const char **out_end_entry)
{
const char *end_entry;
while (*entry != '\0' && !is_valid_identifier_character(*entry))
entry++;
end_entry = entry;
while (*end_entry != '\0' && is_valid_identifier_character(*end_entry))
end_entry++;
if (entry == end_entry)
return NULL;
*out_end_entry = end_entry;
return entry;
}
WCHAR *vkd3d_dup_demangled_entry_point(const char *entry)
{
const char *end_entry;
if (!(entry = vkd3d_manged_entry_point_scan(entry, &end_entry)))
return NULL;
return vkd3d_dup_entry_point_n(entry, end_entry - entry);
}
char *vkd3d_dup_demangled_entry_point_ascii(const char *entry)
{
const char *end_entry;
if (!(entry = vkd3d_manged_entry_point_scan(entry, &end_entry)))
return NULL;
return vkd3d_strdup_n(entry, end_entry - entry);
}

View File

@ -84,9 +84,9 @@ static void vkd3d_utf8_append(char **dst, uint32_t c)
*dst += 4;
}
static uint32_t vkd3d_utf16_read(const WCHAR **src)
static uint32_t vkd3d_utf16_read(const uint16_t **src)
{
const WCHAR *s = *src;
const uint16_t *s = *src;
if (s[0] < 0xd800 || s[0] > 0xdfff) /* Not a surrogate pair. */
{
@ -105,15 +105,21 @@ static uint32_t vkd3d_utf16_read(const WCHAR **src)
return 0x10000 + ((s[0] & 0x3ff) << 10) + (s[1] & 0x3ff);
}
static inline bool vkd3d_string_should_loop_u16(ptrdiff_t max_elements, const WCHAR* src, const WCHAR* wstr)
static inline bool vkd3d_string_should_loop_u16(ptrdiff_t max_elements, const uint16_t* src, const uint16_t* wstr)
{
ptrdiff_t cursor_pos = src - wstr;
return (!max_elements || cursor_pos < max_elements) && *src;
}
char *vkd3d_strdup_w_utf8(const WCHAR *wstr, size_t max_elements)
static inline bool vkd3d_string_should_loop_u32(ptrdiff_t max_elements, const uint32_t* src, const uint32_t* wstr)
{
const WCHAR *src = wstr;
ptrdiff_t cursor_pos = src - wstr;
return (!max_elements || cursor_pos < max_elements) && *src;
}
static char *vkd3d_strdup_w16_utf8(const uint16_t *wstr, size_t max_elements)
{
const uint16_t *src = wstr;
size_t dst_size = 0;
char *dst, *utf8;
uint32_t c;
@ -137,7 +143,36 @@ char *vkd3d_strdup_w_utf8(const WCHAR *wstr, size_t max_elements)
continue;
vkd3d_utf8_append(&utf8, c);
}
*utf8 = '\0';
*utf8 = 0;
return dst;
}
static char *vkd3d_strdup_w32_utf8(const uint32_t *wstr, size_t max_elements)
{
const uint32_t *src = wstr;
size_t dst_size = 0;
char *dst, *utf8;
while (vkd3d_string_should_loop_u32(max_elements, src, wstr))
dst_size += vkd3d_utf8_len(*src++);
++dst_size;
if (!(dst = vkd3d_malloc(dst_size)))
return NULL;
utf8 = dst;
src = wstr;
while (vkd3d_string_should_loop_u32(max_elements, src, wstr))
vkd3d_utf8_append(&utf8, *src++);
*utf8 = 0;
return dst;
}
char *vkd3d_strdup_w_utf8(const WCHAR *wstr, size_t wchar_size, size_t max_elements)
{
if (wchar_size == 2)
return vkd3d_strdup_w16_utf8((const uint16_t *)wstr, max_elements);
return vkd3d_strdup_w32_utf8((const uint32_t *)wstr, max_elements);
}

View File

@ -123,8 +123,6 @@ enum vkd3d_sm4_opcode
VKD3D_SM4_OP_AND = 0x01,
VKD3D_SM4_OP_BREAK = 0x02,
VKD3D_SM4_OP_BREAKC = 0x03,
VKD3D_SM4_OP_CALL = 0x04,
VKD3D_SM4_OP_CALL_C = 0x05,
VKD3D_SM4_OP_CASE = 0x06,
VKD3D_SM4_OP_CONTINUE = 0x07,
VKD3D_SM4_OP_CONTINUEC = 0x08,
@ -139,7 +137,6 @@ enum vkd3d_sm4_opcode
VKD3D_SM4_OP_DP4 = 0x11,
VKD3D_SM4_OP_ELSE = 0x12,
VKD3D_SM4_OP_EMIT = 0x13,
VKD3D_SM4_OP_EMIT_THEN_CUT = 0x14,
VKD3D_SM4_OP_ENDIF = 0x15,
VKD3D_SM4_OP_ENDLOOP = 0x16,
VKD3D_SM4_OP_ENDSWITCH = 0x17,
@ -201,7 +198,6 @@ enum vkd3d_sm4_opcode
VKD3D_SM4_OP_ULT = 0x4f,
VKD3D_SM4_OP_UGE = 0x50,
VKD3D_SM4_OP_UMUL = 0x51,
VKD3D_SM4_OP_UMAD = 0x52,
VKD3D_SM4_OP_UMAX = 0x53,
VKD3D_SM4_OP_UMIN = 0x54,
VKD3D_SM4_OP_USHR = 0x55,
@ -221,24 +217,20 @@ enum vkd3d_sm4_opcode
VKD3D_SM4_OP_DCL_INPUT_PS_SGV = 0x63,
VKD3D_SM4_OP_DCL_INPUT_PS_SIV = 0x64,
VKD3D_SM4_OP_DCL_OUTPUT = 0x65,
VKD3D_SM4_OP_DCL_OUTPUT_SGV = 0x66,
VKD3D_SM4_OP_DCL_OUTPUT_SIV = 0x67,
VKD3D_SM4_OP_DCL_TEMPS = 0x68,
VKD3D_SM4_OP_DCL_INDEXABLE_TEMP = 0x69,
VKD3D_SM4_OP_DCL_GLOBAL_FLAGS = 0x6a,
VKD3D_SM4_OP_LOD = 0x6c,
VKD3D_SM4_OP_GATHER4 = 0x6d,
VKD3D_SM4_OP_SAMPLE_POS = 0x6e,
VKD3D_SM4_OP_SAMPLE_INFO = 0x6f,
VKD3D_SM5_OP_HS_DECLS = 0x71,
VKD3D_SM5_OP_HS_CONTROL_POINT_PHASE = 0x72,
VKD3D_SM5_OP_HS_FORK_PHASE = 0x73,
VKD3D_SM5_OP_HS_JOIN_PHASE = 0x74,
VKD3D_SM5_OP_EMIT_STREAM = 0x75,
VKD3D_SM5_OP_CUT_STREAM = 0x76,
VKD3D_SM5_OP_EMIT_THEN_CUT_STREAM = 0x77,
VKD3D_SM5_OP_FCALL = 0x78,
VKD3D_SM5_OP_BUFINFO = 0x79,
VKD3D_SM5_OP_DERIV_RTX_COARSE = 0x7a,
@ -251,8 +243,6 @@ enum vkd3d_sm4_opcode
VKD3D_SM5_OP_RCP = 0x81,
VKD3D_SM5_OP_F32TOF16 = 0x82,
VKD3D_SM5_OP_F16TOF32 = 0x83,
VKD3D_SM5_OP_UADDC = 0x84,
VKD3D_SM5_OP_USUBB = 0x85,
VKD3D_SM5_OP_COUNTBITS = 0x86,
VKD3D_SM5_OP_FIRSTBIT_HI = 0x87,
VKD3D_SM5_OP_FIRSTBIT_LO = 0x88,
@ -310,34 +300,9 @@ enum vkd3d_sm4_opcode
VKD3D_SM5_OP_IMM_ATOMIC_UMAX = 0xbc,
VKD3D_SM5_OP_IMM_ATOMIC_UMIN = 0xbd,
VKD3D_SM5_OP_SYNC = 0xbe,
VKD3D_SM5_OP_DADD = 0xbf,
VKD3D_SM5_OP_DMAX = 0xc0,
VKD3D_SM5_OP_DMIN = 0xc1,
VKD3D_SM5_OP_DMUL = 0xc2,
VKD3D_SM5_OP_DEQ = 0xc3,
VKD3D_SM5_OP_DGE = 0xc4,
VKD3D_SM5_OP_DLT = 0xc5,
VKD3D_SM5_OP_DNE = 0xc6,
VKD3D_SM5_OP_DMOV = 0xc7,
VKD3D_SM5_OP_DMOVC = 0xc8,
VKD3D_SM5_OP_DTOF = 0xc9,
VKD3D_SM5_OP_FTOD = 0xca,
VKD3D_SM5_OP_EVAL_SNAPPED = 0xcb,
VKD3D_SM5_OP_EVAL_SAMPLE_INDEX = 0xcc,
VKD3D_SM5_OP_EVAL_CENTROID = 0xcd,
VKD3D_SM5_OP_DCL_GS_INSTANCES = 0xce,
VKD3D_SM5_OP_ABORT = 0xcf,
VKD3D_SM5_OP_DEBUG_BREAK = 0xd0,
VKD3D_SM5_OP_DDIV = 0xd2,
VKD3D_SM5_OP_DFMA = 0xd3,
VKD3D_SM5_OP_DRCP = 0xd4,
VKD3D_SM5_OP_MSAD = 0xd5,
VKD3D_SM5_OP_DTOI = 0xd6,
VKD3D_SM5_OP_DTOU = 0xd7,
VKD3D_SM5_OP_ITOD = 0xd8,
VKD3D_SM5_OP_UTOD = 0xd9,
VKD3D_SM5_OP_GATHER4_FEEDBACK = 0xdb,
VKD3D_SM5_OP_GATHER4_C_FEEDBACK = 0xdc,
VKD3D_SM5_OP_GATHER4_PO_FEEDBACK = 0xdd,
@ -363,7 +328,6 @@ enum vkd3d_sm4_register_type
VKD3D_SM4_RT_OUTPUT = 0x02,
VKD3D_SM4_RT_INDEXABLE_TEMP = 0x03,
VKD3D_SM4_RT_IMMCONST = 0x04,
VKD3D_SM4_RT_IMMCONST64 = 0x05,
VKD3D_SM4_RT_SAMPLER = 0x06,
VKD3D_SM4_RT_RESOURCE = 0x07,
VKD3D_SM4_RT_CONSTBUFFER = 0x08,
@ -455,7 +419,6 @@ enum vkd3d_sm4_immconst_type
{
VKD3D_SM4_IMMCONST_SCALAR = 0x1,
VKD3D_SM4_IMMCONST_VEC4 = 0x2,
VKD3D_SM4_IMMCONST_DVEC2 = VKD3D_SM4_IMMCONST_VEC4,
};
enum vkd3d_sm4_resource_type
@ -479,7 +442,6 @@ enum vkd3d_sm4_data_type
VKD3D_SM4_DATA_INT = 0x3,
VKD3D_SM4_DATA_UINT = 0x4,
VKD3D_SM4_DATA_FLOAT = 0x5,
VKD3D_SM4_DATA_DOUBLE = 0x6,
};
enum vkd3d_sm4_sampler_mode
@ -570,7 +532,6 @@ static const enum vkd3d_data_type data_type_table[] =
/* VKD3D_SM4_DATA_INT */ VKD3D_DATA_INT,
/* VKD3D_SM4_DATA_UINT */ VKD3D_DATA_UINT,
/* VKD3D_SM4_DATA_FLOAT */ VKD3D_DATA_FLOAT,
/* VKD3D_SM4_DATA_DOUBLE */ VKD3D_DATA_DOUBLE,
};
static bool shader_is_sm_5_1(const struct vkd3d_sm4_data *priv)
@ -1026,7 +987,6 @@ static void shader_sm5_read_sync(struct vkd3d_shader_instruction *ins,
* R -> VKD3D_DATA_RESOURCE
* S -> VKD3D_DATA_SAMPLER
* U -> VKD3D_DATA_UAV
* d -> VKD3D_DATA_DOUBLE
*/
static const struct vkd3d_sm4_opcode_info opcode_table[] =
{
@ -1043,7 +1003,7 @@ static const struct vkd3d_sm4_opcode_info opcode_table[] =
{VKD3D_SM4_OP_DEFAULT, VKD3DSIH_DEFAULT, "", ""},
{VKD3D_SM4_OP_DERIV_RTX, VKD3DSIH_DSX, "f", "f"},
{VKD3D_SM4_OP_DERIV_RTY, VKD3DSIH_DSY, "f", "f"},
{VKD3D_SM4_OP_DISCARD, VKD3DSIH_DISCARD, "", "u",
{VKD3D_SM4_OP_DISCARD, VKD3DSIH_TEXKILL, "", "u",
shader_sm4_read_conditional_op},
{VKD3D_SM4_OP_DIV, VKD3DSIH_DIV, "f", "ff"},
{VKD3D_SM4_OP_DP2, VKD3DSIH_DP2, "f", "ff"},
@ -1051,7 +1011,6 @@ static const struct vkd3d_sm4_opcode_info opcode_table[] =
{VKD3D_SM4_OP_DP4, VKD3DSIH_DP4, "f", "ff"},
{VKD3D_SM4_OP_ELSE, VKD3DSIH_ELSE, "", ""},
{VKD3D_SM4_OP_EMIT, VKD3DSIH_EMIT, "", ""},
{VKD3D_SM4_OP_EMIT_THEN_CUT, VKD3DSIH_EMIT_THEN_CUT, "", ""},
{VKD3D_SM4_OP_ENDIF, VKD3DSIH_ENDIF, "", ""},
{VKD3D_SM4_OP_ENDLOOP, VKD3DSIH_ENDLOOP, "", ""},
{VKD3D_SM4_OP_ENDSWITCH, VKD3DSIH_ENDSWITCH, "", ""},
@ -1116,7 +1075,6 @@ static const struct vkd3d_sm4_opcode_info opcode_table[] =
{VKD3D_SM4_OP_ULT, VKD3DSIH_ULT, "u", "uu"},
{VKD3D_SM4_OP_UGE, VKD3DSIH_UGE, "u", "uu"},
{VKD3D_SM4_OP_UMUL, VKD3DSIH_UMUL, "uu", "uu"},
{VKD3D_SM4_OP_UMAD, VKD3DSIH_UMAD, "u", "uuu"},
{VKD3D_SM4_OP_UMAX, VKD3DSIH_UMAX, "u", "uu"},
{VKD3D_SM4_OP_UMIN, VKD3DSIH_UMIN, "u", "uu"},
{VKD3D_SM4_OP_USHR, VKD3DSIH_USHR, "u", "uu"},
@ -1168,7 +1126,6 @@ static const struct vkd3d_sm4_opcode_info opcode_table[] =
{VKD3D_SM5_OP_HS_JOIN_PHASE, VKD3DSIH_HS_JOIN_PHASE, "", ""},
{VKD3D_SM5_OP_EMIT_STREAM, VKD3DSIH_EMIT_STREAM, "", "f"},
{VKD3D_SM5_OP_CUT_STREAM, VKD3DSIH_CUT_STREAM, "", "f"},
{VKD3D_SM5_OP_EMIT_THEN_CUT_STREAM, VKD3DSIH_EMIT_THEN_CUT_STREAM, "", "f"},
{VKD3D_SM5_OP_FCALL, VKD3DSIH_FCALL, "", "O",
shader_sm5_read_fcall},
{VKD3D_SM5_OP_BUFINFO, VKD3DSIH_BUFINFO, "i", "U"},
@ -1260,7 +1217,6 @@ static const struct vkd3d_sm4_opcode_info opcode_table[] =
{VKD3D_SM5_OP_SYNC, VKD3DSIH_SYNC, "", "",
shader_sm5_read_sync},
{VKD3D_SM5_OP_EVAL_SAMPLE_INDEX, VKD3DSIH_EVAL_SAMPLE_INDEX, "f", "fi"},
{VKD3D_SM5_OP_EVAL_SNAPPED, VKD3DSIH_EVAL_SNAPPED, "f", "fi"},
{VKD3D_SM5_OP_EVAL_CENTROID, VKD3DSIH_EVAL_CENTROID, "f", "f"},
{VKD3D_SM5_OP_DCL_GS_INSTANCES, VKD3DSIH_DCL_GS_INSTANCES, "", "",
shader_sm4_read_declaration_count},
@ -1280,26 +1236,6 @@ static const struct vkd3d_sm4_opcode_info opcode_table[] =
{VKD3D_SM5_OP_SAMPLE_D_CLAMP_FEEDBACK, VKD3DSIH_SAMPLE_GRAD_FEEDBACK, "fu", "fRSfff"},
{VKD3D_SM5_OP_SAMPLE_C_CLAMP_FEEDBACK, VKD3DSIH_SAMPLE_C_FEEDBACK, "fu", "fRSff"},
{VKD3D_SM5_OP_CHECK_ACCESS_FULLY_MAPPED, VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED, "u", "u"},
{VKD3D_SM5_OP_DADD, VKD3DSIH_DADD, "d", "dd"},
{VKD3D_SM5_OP_DMAX, VKD3DSIH_DMAX, "d", "dd"},
{VKD3D_SM5_OP_DMIN, VKD3DSIH_DMIN, "d", "dd"},
{VKD3D_SM5_OP_DMUL, VKD3DSIH_DMUL, "d", "dd"},
{VKD3D_SM5_OP_DEQ, VKD3DSIH_DEQ, "u", "dd"},
{VKD3D_SM5_OP_DGE, VKD3DSIH_DGE, "u", "dd"},
{VKD3D_SM5_OP_DLT, VKD3DSIH_DLT, "u", "dd"},
{VKD3D_SM5_OP_DNE, VKD3DSIH_DNE, "u", "dd"},
{VKD3D_SM5_OP_DMOV, VKD3DSIH_DMOV, "d", "d"},
{VKD3D_SM5_OP_DMOVC, VKD3DSIH_DMOVC, "d", "udd"},
{VKD3D_SM5_OP_DTOF, VKD3DSIH_DTOF, "f", "d"},
{VKD3D_SM5_OP_FTOD, VKD3DSIH_FTOD, "d", "f"},
{VKD3D_SM5_OP_DDIV, VKD3DSIH_DDIV, "d", "dd"},
{VKD3D_SM5_OP_DFMA, VKD3DSIH_DFMA, "d", "ddd"},
{VKD3D_SM5_OP_DRCP, VKD3DSIH_DRCP, "d", "d"},
{VKD3D_SM5_OP_DTOI, VKD3DSIH_DTOI, "i", "d"},
{VKD3D_SM5_OP_DTOU, VKD3DSIH_DTOU, "u", "d"},
{VKD3D_SM5_OP_ITOD, VKD3DSIH_ITOD, "d", "i"},
{VKD3D_SM5_OP_UTOD, VKD3DSIH_UTOD, "d", "u"},
};
static const enum vkd3d_shader_register_type register_type_table[] =
@ -1309,7 +1245,7 @@ static const enum vkd3d_shader_register_type register_type_table[] =
/* VKD3D_SM4_RT_OUTPUT */ VKD3DSPR_OUTPUT,
/* VKD3D_SM4_RT_INDEXABLE_TEMP */ VKD3DSPR_IDXTEMP,
/* VKD3D_SM4_RT_IMMCONST */ VKD3DSPR_IMMCONST,
/* VKD3D_SM4_RT_IMMCONST64 */ VKD3DSPR_IMMCONST64,
/* UNKNOWN */ ~0u,
/* VKD3D_SM4_RT_SAMPLER */ VKD3DSPR_SAMPLER,
/* VKD3D_SM4_RT_RESOURCE */ VKD3DSPR_RESOURCE,
/* VKD3D_SM4_RT_CONSTBUFFER */ VKD3DSPR_CONSTBUFFER,
@ -1346,7 +1282,6 @@ static const enum vkd3d_shader_register_type register_type_table[] =
/* VKD3D_SM5_RT_DEPTHOUT_LESS_EQUAL */ VKD3DSPR_DEPTHOUTLE,
/* UNKNOWN */ ~0u,
/* VKD3D_SM5_RT_STENCILREFOUT */ VKD3DSPR_STENCILREFOUT,
/* VKD3D_SM5_RT_INNERCOVERAGE */ VKD3DSPR_INNERCOVERAGE,
};
static const struct vkd3d_sm4_opcode_info *get_opcode_info(enum vkd3d_sm4_opcode opcode)
@ -1404,8 +1339,6 @@ static enum vkd3d_data_type map_data_type(char t)
return VKD3D_DATA_SAMPLER;
case 'U':
return VKD3D_DATA_UAV;
case 'd':
return VKD3D_DATA_DOUBLE;
default:
ERR("Invalid data type '%c'.\n", t);
return VKD3D_DATA_FLOAT;
@ -1713,40 +1646,6 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr
break;
}
}
else if (register_type == VKD3D_SM4_RT_IMMCONST64)
{
enum vkd3d_sm4_immconst_type immconst_type =
(token & VKD3D_SM4_IMMCONST_TYPE_MASK) >> VKD3D_SM4_IMMCONST_TYPE_SHIFT;
switch (immconst_type)
{
case VKD3D_SM4_IMMCONST_SCALAR:
param->immconst_type = VKD3D_IMMCONST_SCALAR;
if (end - *ptr < VKD3D_DOUBLE_DWORD_SIZE)
{
WARN("Invalid ptr %p, end %p.\n", *ptr, end);
return false;
}
memcpy(param->immconst_uint64, *ptr, VKD3D_DOUBLE_DWORD_SIZE * sizeof(DWORD));
*ptr += VKD3D_DOUBLE_DWORD_SIZE;
break;
case VKD3D_SM4_IMMCONST_DVEC2:
param->immconst_type = VKD3D_IMMCONST_VEC4;
if (end - *ptr < VKD3D_DVEC2_DWORD_SIZE)
{
WARN("Invalid ptr %p, end %p.\n", *ptr, end);
return false;
}
memcpy(param->immconst_uint64, *ptr, VKD3D_DVEC2_DWORD_SIZE * sizeof(DWORD));
*ptr += VKD3D_DVEC2_DWORD_SIZE;
break;
default:
FIXME("Unhandled immediate constant type %#x.\n", immconst_type);
break;
}
}
map_register(priv, param);
@ -1857,6 +1756,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_sm4_data *priv, const DWORD *
if (!dst_param->write_mask && shader_sm4_is_scalar_register(&dst_param->reg))
dst_param->write_mask = VKD3DSP_WRITEMASK_0;
dst_param->modifiers = 0;
dst_param->shift = 0;
return true;
}
@ -2249,21 +2149,6 @@ static int isgn_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
return shader_parse_signature(tag, data, data_size, is);
}
static int osgn_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
{
struct vkd3d_shader_signature *is = ctx;
if (tag != TAG_OSGN && tag != TAG_OSG1)
return VKD3D_OK;
if (is->elements)
{
FIXME("Multiple input signatures.\n");
vkd3d_shader_free_shader_signature(is);
}
return shader_parse_signature(tag, data, data_size, is);
}
int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
struct vkd3d_shader_signature *signature)
{
@ -2275,17 +2160,6 @@ int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
return ret;
}
int shader_parse_output_signature(const void *dxbc, size_t dxbc_length,
struct vkd3d_shader_signature *signature)
{
int ret;
memset(signature, 0, sizeof(*signature));
if ((ret = parse_dxbc(dxbc, dxbc_length, osgn_handler, signature)) < 0)
ERR("Failed to parse output signature.\n");
return ret;
}
static int dxil_handler(const char *data, DWORD data_size, DWORD tag, void *context)
{
switch (tag)
@ -2453,8 +2327,7 @@ static void shader_validate_descriptor_range1(const struct vkd3d_descriptor_rang
| VKD3D_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE
| VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE
| VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE
| VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_STATIC
| VKD3D_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS);
| VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_STATIC);
if (unknown_flags)
FIXME("Unknown descriptor range flags %#x.\n", unknown_flags);
@ -2755,9 +2628,8 @@ static int shader_parse_static_samplers(struct root_signature_parser_context *co
return VKD3D_OK;
}
int vkd3d_shader_parse_root_signature_raw(const char *data, unsigned int data_size,
struct vkd3d_versioned_root_signature_desc *desc,
vkd3d_shader_hash_t *compatibility_hash)
static int shader_parse_root_signature(const char *data, unsigned int data_size,
struct vkd3d_versioned_root_signature_desc *desc)
{
struct vkd3d_root_signature_desc *v_1_0 = &desc->v_1_0;
struct root_signature_parser_context context;
@ -2765,8 +2637,6 @@ int vkd3d_shader_parse_root_signature_raw(const char *data, unsigned int data_si
const char *ptr = data;
int ret;
memset(desc, 0, sizeof(*desc));
context.data = data;
context.data_size = data_size;
@ -2838,46 +2708,28 @@ int vkd3d_shader_parse_root_signature_raw(const char *data, unsigned int data_si
read_uint32(&ptr, &v_1_0->flags);
TRACE("Flags %#x.\n", v_1_0->flags);
if (compatibility_hash)
{
struct vkd3d_shader_code code = { data, data_size };
*compatibility_hash = vkd3d_shader_hash(&code);
}
return VKD3D_OK;
}
static int rts0_handler(const char *data, DWORD data_size, DWORD tag, void *context)
{
struct vkd3d_shader_code *payload = context;
struct vkd3d_versioned_root_signature_desc *desc = context;
if (tag != TAG_RTS0)
return VKD3D_OK;
payload->code = data;
payload->size = data_size;
return VKD3D_OK;
return shader_parse_root_signature(data, data_size, desc);
}
int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_versioned_root_signature_desc *root_signature,
vkd3d_shader_hash_t *compatibility_hash)
struct vkd3d_versioned_root_signature_desc *root_signature)
{
struct vkd3d_shader_code raw_payload;
int ret;
TRACE("dxbc {%p, %zu}, root_signature %p.\n", dxbc->code, dxbc->size, root_signature);
memset(&raw_payload, 0, sizeof(raw_payload));
if ((ret = parse_dxbc(dxbc->code, dxbc->size, rts0_handler, &raw_payload)) < 0)
return ret;
if (!raw_payload.code)
return VKD3D_ERROR;
if ((ret = vkd3d_shader_parse_root_signature_raw(raw_payload.code, raw_payload.size,
root_signature, compatibility_hash)) < 0)
memset(root_signature, 0, sizeof(*root_signature));
if ((ret = parse_dxbc(dxbc->code, dxbc->size, rts0_handler, root_signature)) < 0)
{
vkd3d_shader_free_root_signature(root_signature);
return ret;

File diff suppressed because it is too large Load Diff

View File

@ -7,12 +7,11 @@ vkd3d_shader_src = [
'vkd3d_shader_main.c',
]
vkd3d_shader_lib = static_library('vkd3d-shader', vkd3d_shader_src,
vkd3d_shader_lib = static_library('vkd3d-shader', vkd3d_shader_src, vkd3d_headers,
dependencies : [ vkd3d_common_dep, dxil_spirv_dep ],
include_directories : vkd3d_private_includes,
override_options : [ 'c_std='+vkd3d_c_std ])
vkd3d_shader_dep = declare_dependency(
link_with : vkd3d_shader_lib,
dependencies : vkd3d_common_dep,
include_directories : vkd3d_public_includes)
include_directories : vkd3d_public_includes)

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,7 @@ struct vkd3d_string_buffer
static const char * const shader_opcode_names[] =
{
/* VKD3DSIH_ABS */ "abs",
/* VKD3DSIH_ADD */ "add",
/* VKD3DSIH_AND */ "and",
/* VKD3DSIH_ATOMIC_AND */ "atomic_and",
@ -59,9 +60,12 @@ static const char * const shader_opcode_names[] =
/* VKD3DSIH_CALL */ "call",
/* VKD3DSIH_CALLNZ */ "callnz",
/* VKD3DSIH_CASE */ "case",
/* VKD3DSIH_CMP */ "cmp",
/* VKD3DSIH_CND */ "cnd",
/* VKD3DSIH_CONTINUE */ "continue",
/* VKD3DSIH_CONTINUEP */ "continuec",
/* VKD3DSIH_COUNTBITS */ "countbits",
/* VKD3DSIH_CRS */ "crs",
/* VKD3DSIH_CUT */ "cut",
/* VKD3DSIH_CUT_STREAM */ "cut_stream",
/* VKD3DSIH_DCL */ "dcl",
@ -104,11 +108,16 @@ static const char * const shader_opcode_names[] =
/* VKD3DSIH_DCL_UAV_STRUCTURED */ "dcl_uav_structured",
/* VKD3DSIH_DCL_UAV_TYPED */ "dcl_uav_typed",
/* VKD3DSIH_DCL_VERTICES_OUT */ "dcl_maxOutputVertexCount",
/* VKD3DSIH_DEF */ "def",
/* VKD3DSIH_DEFAULT */ "default",
/* VKD3DSIH_DEFB */ "defb",
/* VKD3DSIH_DEFI */ "defi",
/* VKD3DSIH_DIV */ "div",
/* VKD3DSIH_DP2 */ "dp2",
/* VKD3DSIH_DP2ADD */ "dp2add",
/* VKD3DSIH_DP3 */ "dp3",
/* VKD3DSIH_DP4 */ "dp4",
/* VKD3DSIH_DST */ "dst",
/* VKD3DSIH_DSX */ "dsx",
/* VKD3DSIH_DSX_COARSE */ "deriv_rtx_coarse",
/* VKD3DSIH_DSX_FINE */ "deriv_rtx_fine",
@ -117,17 +126,16 @@ static const char * const shader_opcode_names[] =
/* VKD3DSIH_DSY_FINE */ "deriv_rty_fine",
/* VKD3DSIH_ELSE */ "else",
/* VKD3DSIH_EMIT */ "emit",
/* VKD3DSIH_EMIT_THEN_CUT */ "emit_then_cut",
/* VKD3DSIH_EMIT_STREAM */ "emit_stream",
/* VKD3DSIH_EMIT_THEN_CUT_STREAM */ "emit_then_cut_stream",
/* VKD3DSIH_ENDIF */ "endif",
/* VKD3DSIH_ENDLOOP */ "endloop",
/* VKD3DSIH_ENDREP */ "endrep",
/* VKD3DSIH_ENDSWITCH */ "endswitch",
/* VKD3DSIH_EQ */ "eq",
/* VKD3DSIH_EVAL_CENTROID */ "eval_centroid",
/* VKD3DSIH_EVAL_SAMPLE_INDEX */ "eval_sample_index",
/* VKD3DSIH_EVAL_SNAPPED */ "eval_snapped",
/* VKD3DSIH_EXP */ "exp",
/* VKD3DSIH_EXPP */ "expp",
/* VKD3DSIH_F16TOF32 */ "f16tof32",
/* VKD3DSIH_F32TOF16 */ "f32tof16",
/* VKD3DSIH_FCALL */ "fcall",
@ -180,23 +188,34 @@ static const char * const shader_opcode_names[] =
/* VKD3DSIH_LD_RAW */ "ld_raw",
/* VKD3DSIH_LD_STRUCTURED */ "ld_structured",
/* VKD3DSIH_LD_UAV_TYPED */ "ld_uav_typed",
/* VKD3DSIH_LIT */ "lit",
/* VKD3DSIH_LOD */ "lod",
/* VKD3DSIH_LOG */ "log",
/* VKD3DSIH_LOGP */ "logp",
/* VKD3DSIH_LOOP */ "loop",
/* VKD3DSIH_LRP */ "lrp",
/* VKD3DSIH_LT */ "lt",
/* VKD3DSIH_M3x2 */ "m3x2",
/* VKD3DSIH_M3x3 */ "m3x3",
/* VKD3DSIH_M3x4 */ "m3x4",
/* VKD3DSIH_M4x3 */ "m4x3",
/* VKD3DSIH_M4x4 */ "m4x4",
/* VKD3DSIH_MAD */ "mad",
/* VKD3DSIH_MAX */ "max",
/* VKD3DSIH_MIN */ "min",
/* VKD3DSIH_MOV */ "mov",
/* VKD3DSIH_MOVA */ "mova",
/* VKD3DSIH_MOVC */ "movc",
/* VKD3DSIH_MUL */ "mul",
/* VKD3DSIH_NE */ "ne",
/* VKD3DSIH_NOP */ "nop",
/* VKD3DSIH_NOT */ "not",
/* VKD3DSIH_NRM */ "nrm",
/* VKD3DSIH_OR */ "or",
/* VKD3DSIH_PHASE */ "phase",
/* VKD3DSIH_POW */ "pow",
/* VKD3DSIH_RCP */ "rcp",
/* VKD3DSIH_REP */ "rep",
/* VKD3DSIH_RESINFO */ "resinfo",
/* VKD3DSIH_RET */ "ret",
/* VKD3DSIH_RETP */ "retp",
@ -213,6 +232,7 @@ static const char * const shader_opcode_names[] =
/* VKD3DSIH_SAMPLE_INFO */ "sample_info",
/* VKD3DSIH_SAMPLE_LOD */ "sample_l",
/* VKD3DSIH_SAMPLE_POS */ "sample_pos",
/* VKD3DSIH_SETP */ "setp",
/* VKD3DSIH_SGE */ "sge",
/* VKD3DSIH_SGN */ "sgn",
/* VKD3DSIH_SINCOS */ "sincos",
@ -225,7 +245,28 @@ static const char * const shader_opcode_names[] =
/* VKD3DSIH_SWAPC */ "swapc",
/* VKD3DSIH_SWITCH */ "switch",
/* VKD3DSIH_SYNC */ "sync",
/* VKD3DSIH_DISCARD */ "discard",
/* VKD3DSIH_TEX */ "texld",
/* VKD3DSIH_TEXBEM */ "texbem",
/* VKD3DSIH_TEXBEML */ "texbeml",
/* VKD3DSIH_TEXCOORD */ "texcrd",
/* VKD3DSIH_TEXDEPTH */ "texdepth",
/* VKD3DSIH_TEXDP3 */ "texdp3",
/* VKD3DSIH_TEXDP3TEX */ "texdp3tex",
/* VKD3DSIH_TEXKILL */ "texkill",
/* VKD3DSIH_TEXLDD */ "texldd",
/* VKD3DSIH_TEXLDL */ "texldl",
/* VKD3DSIH_TEXM3x2DEPTH */ "texm3x2depth",
/* VKD3DSIH_TEXM3x2PAD */ "texm3x2pad",
/* VKD3DSIH_TEXM3x2TEX */ "texm3x2tex",
/* VKD3DSIH_TEXM3x3 */ "texm3x3",
/* VKD3DSIH_TEXM3x3DIFF */ "texm3x3diff",
/* VKD3DSIH_TEXM3x3PAD */ "texm3x3pad",
/* VKD3DSIH_TEXM3x3SPEC */ "texm3x3spec",
/* VKD3DSIH_TEXM3x3TEX */ "texm3x3tex",
/* VKD3DSIH_TEXM3x3VSPEC */ "texm3x3vspec",
/* VKD3DSIH_TEXREG2AR */ "texreg2ar",
/* VKD3DSIH_TEXREG2GB */ "texreg2gb",
/* VKD3DSIH_TEXREG2RGB */ "texreg2rgb",
/* VKD3DSIH_UBFE */ "ubfe",
/* VKD3DSIH_UDIV */ "udiv",
/* VKD3DSIH_UGE */ "uge",
@ -233,7 +274,6 @@ static const char * const shader_opcode_names[] =
/* VKD3DSIH_UMAX */ "umax",
/* VKD3DSIH_UMIN */ "umin",
/* VKD3DSIH_UMUL */ "umul",
/* VKD3DSIH_UMAD */ "umad",
/* VKD3DSIH_USHR */ "ushr",
/* VKD3DSIH_UTOF */ "utof",
/* VKD3DSIH_XOR */ "xor",
@ -343,6 +383,22 @@ static int shader_addline(struct vkd3d_string_buffer *buffer, const char *format
}
}
/* Convert floating point offset relative to a register file to an absolute
* offset for float constants. */
static unsigned int shader_get_float_offset(enum vkd3d_shader_register_type register_type, UINT register_idx)
{
switch (register_type)
{
case VKD3DSPR_CONST: return register_idx;
case VKD3DSPR_CONST2: return 2048 + register_idx;
case VKD3DSPR_CONST3: return 4096 + register_idx;
case VKD3DSPR_CONST4: return 6144 + register_idx;
default:
FIXME("Unsupported register type: %u.\n", register_type);
return register_idx;
}
}
static void shader_dump_global_flags(struct vkd3d_string_buffer *buffer, DWORD global_flags)
{
unsigned int i;
@ -358,8 +414,6 @@ static void shader_dump_global_flags(struct vkd3d_string_buffer *buffer, DWORD g
{VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL, "forceEarlyDepthStencil"},
{VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS, "enableRawAndStructuredBuffers"},
{VKD3DSGF_ENABLE_MINIMUM_PRECISION, "enableMinimumPrecision"},
{VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS, "enableDoublePrecisionFloatOps"},
{VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS, "enable11_1DoubleExtensions"},
};
for (i = 0; i < ARRAY_SIZE(global_flag_info); ++i)
@ -538,7 +592,7 @@ static void shader_dump_decl_usage(struct vkd3d_string_buffer *buffer,
break;
}
}
else // if (semantic->reg.reg.type == VKD3DSPR_RESOURCE || semantic->reg.reg.type == VKD3DSPR_UAV)
else if (semantic->reg.reg.type == VKD3DSPR_RESOURCE || semantic->reg.reg.type == VKD3DSPR_UAV)
{
if (semantic->reg.reg.type == VKD3DSPR_RESOURCE)
shader_addline(buffer, "_resource_");
@ -619,6 +673,80 @@ static void shader_dump_decl_usage(struct vkd3d_string_buffer *buffer,
break;
}
}
else
{
/* Pixel shaders 3.0 don't have usage semantics. */
if (shader_version->major < 3 && shader_version->type == VKD3D_SHADER_TYPE_PIXEL)
return;
else
shader_addline(buffer, "_");
switch (semantic->usage)
{
case VKD3D_DECL_USAGE_POSITION:
shader_addline(buffer, "position%u", semantic->usage_idx);
break;
case VKD3D_DECL_USAGE_BLEND_INDICES:
shader_addline(buffer, "blend");
break;
case VKD3D_DECL_USAGE_BLEND_WEIGHT:
shader_addline(buffer, "weight");
break;
case VKD3D_DECL_USAGE_NORMAL:
shader_addline(buffer, "normal%u", semantic->usage_idx);
break;
case VKD3D_DECL_USAGE_PSIZE:
shader_addline(buffer, "psize");
break;
case VKD3D_DECL_USAGE_COLOR:
if (!semantic->usage_idx)
shader_addline(buffer, "color");
else
shader_addline(buffer, "specular%u", (semantic->usage_idx - 1));
break;
case VKD3D_DECL_USAGE_TEXCOORD:
shader_addline(buffer, "texture%u", semantic->usage_idx);
break;
case VKD3D_DECL_USAGE_TANGENT:
shader_addline(buffer, "tangent");
break;
case VKD3D_DECL_USAGE_BINORMAL:
shader_addline(buffer, "binormal");
break;
case VKD3D_DECL_USAGE_TESS_FACTOR:
shader_addline(buffer, "tessfactor");
break;
case VKD3D_DECL_USAGE_POSITIONT:
shader_addline(buffer, "positionT%u", semantic->usage_idx);
break;
case VKD3D_DECL_USAGE_FOG:
shader_addline(buffer, "fog");
break;
case VKD3D_DECL_USAGE_DEPTH:
shader_addline(buffer, "depth");
break;
case VKD3D_DECL_USAGE_SAMPLE:
shader_addline(buffer, "sample");
break;
default:
shader_addline(buffer, "<unknown_semantic(%#x)>", semantic->usage);
FIXME("Unrecognised semantic usage %#x.\n", semantic->usage);
}
}
}
static void shader_dump_src_param(struct vkd3d_string_buffer *buffer,
@ -627,6 +755,8 @@ static void shader_dump_src_param(struct vkd3d_string_buffer *buffer,
static void shader_dump_register(struct vkd3d_string_buffer *buffer,
const struct vkd3d_shader_register *reg, const struct vkd3d_shader_version *shader_version)
{
static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"};
static const char * const misctype_reg_names[] = {"vPos", "vFace"};
unsigned int offset = reg->idx[0].offset;
switch (reg->type)
@ -639,6 +769,22 @@ static void shader_dump_register(struct vkd3d_string_buffer *buffer,
shader_addline(buffer, "v");
break;
case VKD3DSPR_CONST:
case VKD3DSPR_CONST2:
case VKD3DSPR_CONST3:
case VKD3DSPR_CONST4:
shader_addline(buffer, "c");
offset = shader_get_float_offset(reg->type, offset);
break;
case VKD3DSPR_TEXTURE: /* vs: case VKD3DSPR_ADDR */
shader_addline(buffer, "%c", shader_version->type == VKD3D_SHADER_TYPE_PIXEL ? 't' : 'a');
break;
case VKD3DSPR_RASTOUT:
shader_addline(buffer, "%s", rastout_reg_names[offset]);
break;
case VKD3DSPR_COLOROUT:
shader_addline(buffer, "oC");
break;
@ -655,20 +801,57 @@ static void shader_dump_register(struct vkd3d_string_buffer *buffer,
shader_addline(buffer, "oDepthLE");
break;
case VKD3DSPR_OUTPUT:
shader_addline(buffer, "o");
case VKD3DSPR_ATTROUT:
shader_addline(buffer, "oD");
break;
case VKD3DSPR_TEXCRDOUT:
/* Vertex shaders >= 3.0 use general purpose output registers
* (VKD3DSPR_OUTPUT), which can include an address token. */
if (shader_version->major >= 3)
shader_addline(buffer, "o");
else
shader_addline(buffer, "oT");
break;
case VKD3DSPR_CONSTINT:
shader_addline(buffer, "i");
break;
case VKD3DSPR_CONSTBOOL:
shader_addline(buffer, "b");
break;
case VKD3DSPR_LABEL:
shader_addline(buffer, "l");
break;
case VKD3DSPR_LOOP:
shader_addline(buffer, "aL");
break;
case VKD3DSPR_SAMPLER:
shader_addline(buffer, "s");
break;
case VKD3DSPR_IMMCONST:
shader_addline(buffer, "l");
case VKD3DSPR_MISCTYPE:
if (offset > 1)
{
FIXME("Unhandled misctype register %u.\n", offset);
shader_addline(buffer, "<unhandled misctype %#x>", offset);
}
else
{
shader_addline(buffer, "%s", misctype_reg_names[offset]);
}
break;
case VKD3DSPR_IMMCONST64:
shader_addline(buffer, "d");
case VKD3DSPR_PREDICATE:
shader_addline(buffer, "p");
break;
case VKD3DSPR_IMMCONST:
shader_addline(buffer, "l");
break;
case VKD3DSPR_CONSTBUFFER:
@ -837,43 +1020,9 @@ static void shader_dump_register(struct vkd3d_string_buffer *buffer,
}
shader_addline(buffer, ")");
}
else if (reg->type == VKD3DSPR_IMMCONST64)
{
shader_addline(buffer, "(");
switch (reg->immconst_type)
{
case VKD3D_IMMCONST_SCALAR:
switch (reg->data_type)
{
case VKD3D_DATA_DOUBLE:
shader_addline(buffer, "%f", reg->immconst_double[0]);
break;
default:
shader_addline(buffer, "<unhandled data type %#x>", reg->data_type);
break;
}
break;
case VKD3D_IMMCONST_DVEC2:
switch (reg->data_type)
{
case VKD3D_DATA_DOUBLE:
shader_addline(buffer, "%f, %f",
reg->immconst_double[0], reg->immconst_double[1]);
break;
default:
shader_addline(buffer, "<unhandled data type %#x>", reg->data_type);
break;
}
break;
default:
shader_addline(buffer, "<unhandled immconst_type %#x>", reg->immconst_type);
break;
}
shader_addline(buffer, ")");
}
else if (reg->type != VKD3DSPR_NULL)
else if (reg->type != VKD3DSPR_RASTOUT
&& reg->type != VKD3DSPR_MISCTYPE
&& reg->type != VKD3DSPR_NULL)
{
if (offset != ~0u)
{
@ -942,8 +1091,16 @@ static void shader_dump_src_param(struct vkd3d_string_buffer *buffer,
enum vkd3d_shader_src_modifier src_modifier = param->modifiers;
DWORD swizzle = param->swizzle;
if (src_modifier == VKD3DSPSM_NEG || src_modifier == VKD3DSPSM_ABSNEG)
if (src_modifier == VKD3DSPSM_NEG
|| src_modifier == VKD3DSPSM_BIASNEG
|| src_modifier == VKD3DSPSM_SIGNNEG
|| src_modifier == VKD3DSPSM_X2NEG
|| src_modifier == VKD3DSPSM_ABSNEG)
shader_addline(buffer, "-");
else if (src_modifier == VKD3DSPSM_COMP)
shader_addline(buffer, "1-");
else if (src_modifier == VKD3DSPSM_NOT)
shader_addline(buffer, "!");
if (src_modifier == VKD3DSPSM_ABS || src_modifier == VKD3DSPSM_ABSNEG)
shader_addline(buffer, "abs(");
@ -954,6 +1111,16 @@ static void shader_dump_src_param(struct vkd3d_string_buffer *buffer,
{
case VKD3DSPSM_NONE: break;
case VKD3DSPSM_NEG: break;
case VKD3DSPSM_NOT: break;
case VKD3DSPSM_BIAS: shader_addline(buffer, "_bias"); break;
case VKD3DSPSM_BIASNEG: shader_addline(buffer, "_bias"); break;
case VKD3DSPSM_SIGN: shader_addline(buffer, "_bx2"); break;
case VKD3DSPSM_SIGNNEG: shader_addline(buffer, "_bx2"); break;
case VKD3DSPSM_COMP: break;
case VKD3DSPSM_X2: shader_addline(buffer, "_x2"); break;
case VKD3DSPSM_X2NEG: shader_addline(buffer, "_x2"); break;
case VKD3DSPSM_DZ: shader_addline(buffer, "_dz"); break;
case VKD3DSPSM_DW: shader_addline(buffer, "_dw"); break;
case VKD3DSPSM_ABSNEG: shader_addline(buffer, ")"); break;
case VKD3DSPSM_ABS: shader_addline(buffer, ")"); break;
default: shader_addline(buffer, "_unknown_modifier(%#x)", src_modifier);
@ -986,9 +1153,23 @@ static void shader_dump_ins_modifiers(struct vkd3d_string_buffer *buffer,
{
DWORD mmask = dst->modifiers;
if (mmask & VKD3DSPDM_SATURATE) shader_addline(buffer, "_sat");
switch (dst->shift)
{
case 0: break;
case 13: shader_addline(buffer, "_d8"); break;
case 14: shader_addline(buffer, "_d4"); break;
case 15: shader_addline(buffer, "_d2"); break;
case 1: shader_addline(buffer, "_x2"); break;
case 2: shader_addline(buffer, "_x4"); break;
case 3: shader_addline(buffer, "_x8"); break;
default: shader_addline(buffer, "_unhandled_shift(%d)", dst->shift); break;
}
mmask &= ~(VKD3DSPDM_SATURATE);
if (mmask & VKD3DSPDM_SATURATE) shader_addline(buffer, "_sat");
if (mmask & VKD3DSPDM_PARTIALPRECISION) shader_addline(buffer, "_pp");
if (mmask & VKD3DSPDM_MSAMPCENTROID) shader_addline(buffer, "_centroid");
mmask &= ~(VKD3DSPDM_SATURATE | VKD3DSPDM_PARTIALPRECISION | VKD3DSPDM_MSAMPCENTROID);
if (mmask) FIXME("Unrecognised modifier %#x.\n", mmask);
}
@ -1108,7 +1289,7 @@ static void shader_dump_instruction_flags(struct vkd3d_string_buffer *buffer,
case VKD3DSIH_CONTINUEP:
case VKD3DSIH_IF:
case VKD3DSIH_RETP:
case VKD3DSIH_DISCARD:
case VKD3DSIH_TEXKILL:
switch (ins->flags)
{
case VKD3D_SHADER_CONDITIONAL_OP_NZ: shader_addline(buffer, "_nz"); break;
@ -1154,6 +1335,11 @@ static void shader_dump_instruction_flags(struct vkd3d_string_buffer *buffer,
shader_dump_sync_flags(buffer, ins->flags);
break;
case VKD3DSIH_TEX:
if (shader_version->major >= 2 && (ins->flags & VKD3DSI_TEXLD_PROJECT))
shader_addline(buffer, "p");
break;
default:
shader_dump_precise_flags(buffer, ins->flags);
break;
@ -1366,6 +1552,24 @@ static void shader_dump_instruction(struct vkd3d_string_buffer *buffer,
shader_dump_register_space(buffer, ins->declaration.structured_resource.register_space, shader_version);
break;
case VKD3DSIH_DEF:
shader_addline(buffer, "def c%u = %.8e, %.8e, %.8e, %.8e",
shader_get_float_offset(ins->dst[0].reg.type, ins->dst[0].reg.idx[0].offset),
ins->src[0].reg.immconst_float[0], ins->src[0].reg.immconst_float[1],
ins->src[0].reg.immconst_float[2], ins->src[0].reg.immconst_float[3]);
break;
case VKD3DSIH_DEFI:
shader_addline(buffer, "defi i%u = %d, %d, %d, %d", ins->dst[0].reg.idx[0].offset,
ins->src[0].reg.immconst_uint[0], ins->src[0].reg.immconst_uint[1],
ins->src[0].reg.immconst_uint[2], ins->src[0].reg.immconst_uint[3]);
break;
case VKD3DSIH_DEFB:
shader_addline(buffer, "defb b%u = %s",
ins->dst[0].reg.idx[0].offset, ins->src[0].reg.immconst_uint[0] ? "true" : "false");
break;
default:
if (ins->predicate)
{

View File

@ -0,0 +1,14 @@
LIBRARY vkd3d-shader
EXPORTS
vkd3d_shader_compile_dxbc
vkd3d_shader_convert_root_signature
vkd3d_shader_find_signature_element
vkd3d_shader_free_root_signature
vkd3d_shader_free_shader_code
vkd3d_shader_free_shader_signature
vkd3d_shader_parse_input_signature
vkd3d_shader_parse_root_signature
vkd3d_shader_scan_dxbc
vkd3d_shader_serialize_root_signature
vkd3d_shader_supports_dxil
vkd3d_shader_scan_patch_vertex_count

View File

@ -0,0 +1,18 @@
VKD3D_1_0
{
global:
vkd3d_shader_compile_dxbc;
vkd3d_shader_convert_root_signature;
vkd3d_shader_find_signature_element;
vkd3d_shader_free_root_signature;
vkd3d_shader_free_shader_code;
vkd3d_shader_free_shader_signature;
vkd3d_shader_parse_input_signature;
vkd3d_shader_parse_root_signature;
vkd3d_shader_scan_dxbc;
vkd3d_shader_serialize_root_signature;
vkd3d_shader_supports_dxil;
vkd3d_shader_scan_patch_vertex_count;
local: *;
};

View File

@ -20,8 +20,6 @@
#include "vkd3d_shader_private.h"
#include "vkd3d_platform.h"
#include <stdio.h>
#include <inttypes.h>
@ -32,8 +30,6 @@ static void vkd3d_shader_dump_blob(const char *path, vkd3d_shader_hash_t hash, c
snprintf(filename, ARRAY_SIZE(filename), "%s/%016"PRIx64".%s", path, hash, ext);
INFO("Dumping blob to %s.\n", filename);
/* Exclusive open to avoid multiple threads spamming out the same shader module, and avoids race condition. */
if ((f = fopen(filename, "wbx")))
{
@ -44,12 +40,25 @@ static void vkd3d_shader_dump_blob(const char *path, vkd3d_shader_hash_t hash, c
}
}
static bool vkd3d_shader_replace_path(const char *filename, vkd3d_shader_hash_t hash, const void **data, size_t *size)
bool vkd3d_shader_replace(vkd3d_shader_hash_t hash, const void **data, size_t *size)
{
static bool enabled = true;
char filename[1024];
void *buffer = NULL;
const char *path;
FILE *f = NULL;
size_t len;
if (!enabled)
return false;
if (!(path = getenv("VKD3D_SHADER_OVERRIDE")))
{
enabled = false;
return false;
}
snprintf(filename, ARRAY_SIZE(filename), "%s/%016"PRIx64".spv", path, hash);
if ((f = fopen(filename, "rb")))
{
if (fseek(f, 0, SEEK_END) < 0)
@ -69,7 +78,7 @@ static bool vkd3d_shader_replace_path(const char *filename, vkd3d_shader_hash_t
*data = buffer;
*size = len;
INFO("Overriding shader hash %016"PRIx64" with alternative SPIR-V module from %s!\n", hash, filename);
WARN("Overriding shader hash %016"PRIx64" with alternative SPIR-V module!\n", hash);
fclose(f);
return true;
@ -80,53 +89,15 @@ err:
return false;
}
bool vkd3d_shader_replace(vkd3d_shader_hash_t hash, const void **data, size_t *size)
{
static bool enabled = true;
char path[VKD3D_PATH_MAX];
char filename[1024];
if (!enabled)
return false;
if (!vkd3d_get_env_var("VKD3D_SHADER_OVERRIDE", path, sizeof(path)))
{
enabled = false;
return false;
}
snprintf(filename, ARRAY_SIZE(filename), "%s/%016"PRIx64".spv", path, hash);
return vkd3d_shader_replace_path(filename, hash, data, size);
}
bool vkd3d_shader_replace_export(vkd3d_shader_hash_t hash, const void **data, size_t *size, const char *export)
{
static bool enabled = true;
char path[VKD3D_PATH_MAX];
char filename[1024];
if (!enabled)
return false;
if (!vkd3d_get_env_var("VKD3D_SHADER_OVERRIDE", path, sizeof(path)))
{
enabled = false;
return false;
}
snprintf(filename, ARRAY_SIZE(filename), "%s/%016"PRIx64".lib.%s.spv", path, hash, export);
return vkd3d_shader_replace_path(filename, hash, data, size);
}
void vkd3d_shader_dump_shader(vkd3d_shader_hash_t hash, const struct vkd3d_shader_code *shader, const char *ext)
{
static bool enabled = true;
char path[VKD3D_PATH_MAX];
const char *path;
if (!enabled)
return;
if (!vkd3d_get_env_var("VKD3D_SHADER_DUMP_PATH", path, sizeof(path)))
if (!(path = getenv("VKD3D_SHADER_DUMP_PATH")))
{
enabled = false;
return;
@ -138,12 +109,12 @@ void vkd3d_shader_dump_shader(vkd3d_shader_hash_t hash, const struct vkd3d_shade
void vkd3d_shader_dump_spirv_shader(vkd3d_shader_hash_t hash, const struct vkd3d_shader_code *shader)
{
static bool enabled = true;
char path[VKD3D_PATH_MAX];
const char *path;
if (!enabled)
return;
if (!vkd3d_get_env_var("VKD3D_SHADER_DUMP_PATH", path, sizeof(path)))
if (!(path = getenv("VKD3D_SHADER_DUMP_PATH")))
{
enabled = false;
return;
@ -152,26 +123,6 @@ void vkd3d_shader_dump_spirv_shader(vkd3d_shader_hash_t hash, const struct vkd3d
vkd3d_shader_dump_blob(path, hash, shader->code, shader->size, "spv");
}
void vkd3d_shader_dump_spirv_shader_export(vkd3d_shader_hash_t hash, const struct vkd3d_shader_code *shader,
const char *export)
{
static bool enabled = true;
char path[VKD3D_PATH_MAX];
char tag[1024];
if (!enabled)
return;
if (!vkd3d_get_env_var("VKD3D_SHADER_DUMP_PATH", path, sizeof(path)))
{
enabled = false;
return;
}
snprintf(tag, sizeof(tag), "lib.%s.spv", export);
vkd3d_shader_dump_blob(path, hash, shader->code, shader->size, tag);
}
struct vkd3d_shader_parser
{
struct vkd3d_shader_desc shader_desc;
@ -215,6 +166,12 @@ static int vkd3d_shader_validate_compile_args(const struct vkd3d_shader_compile_
if (!compile_args)
return VKD3D_OK;
if (compile_args->type != VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_ARGUMENTS)
{
WARN("Invalid structure type %#x.\n", compile_args->type);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
switch (compile_args->target)
{
case VKD3D_SHADER_TARGET_SPIRV_VULKAN_1_0:
@ -227,100 +184,6 @@ static int vkd3d_shader_validate_compile_args(const struct vkd3d_shader_compile_
return VKD3D_OK;
}
struct vkd3d_shader_scan_key
{
enum vkd3d_shader_register_type register_type;
unsigned int register_id;
};
struct vkd3d_shader_scan_entry
{
struct hash_map_entry entry;
struct vkd3d_shader_scan_key key;
unsigned int flags;
};
static uint32_t vkd3d_shader_scan_entry_hash(const void *key)
{
const struct vkd3d_shader_scan_key *k = key;
return hash_combine(k->register_type, k->register_id);
}
static bool vkd3d_shader_scan_entry_compare(const void *key, const struct hash_map_entry *entry)
{
const struct vkd3d_shader_scan_entry *e = (const struct vkd3d_shader_scan_entry*) entry;
const struct vkd3d_shader_scan_key *k = key;
return e->key.register_type == k->register_type && e->key.register_id == k->register_id;
}
unsigned int vkd3d_shader_scan_get_register_flags(const struct vkd3d_shader_scan_info *scan_info,
enum vkd3d_shader_register_type type, unsigned int id)
{
struct vkd3d_shader_scan_key key;
struct hash_map_entry *e;
key.register_type = type;
key.register_id = id;
e = hash_map_find(&scan_info->register_map, &key);
return e ? e->flags : 0u;
}
static void vkd3d_shader_scan_set_register_flags(struct vkd3d_shader_scan_info *scan_info,
enum vkd3d_shader_register_type type, unsigned int id, unsigned int flags)
{
struct vkd3d_shader_scan_entry entry;
struct vkd3d_shader_scan_key key;
struct hash_map_entry *e;
key.register_type = type;
key.register_id = id;
if ((e = hash_map_find(&scan_info->register_map, &key)))
e->flags |= flags;
else
{
entry.key = key;
entry.flags = flags;
hash_map_insert(&scan_info->register_map, &key, &entry.entry);
}
}
static void vkd3d_shader_scan_init(struct vkd3d_shader_scan_info *scan_info)
{
memset(scan_info, 0, sizeof(*scan_info));
hash_map_init(&scan_info->register_map, &vkd3d_shader_scan_entry_hash,
&vkd3d_shader_scan_entry_compare, sizeof(struct vkd3d_shader_scan_entry));
}
static void vkd3d_shader_scan_destroy(struct vkd3d_shader_scan_info *scan_info)
{
hash_map_clear(&scan_info->register_map);
}
static int vkd3d_shader_validate_shader_type(enum vkd3d_shader_type type, VkShaderStageFlagBits stages)
{
static const VkShaderStageFlagBits table[VKD3D_SHADER_TYPE_COUNT] = {
VK_SHADER_STAGE_FRAGMENT_BIT,
VK_SHADER_STAGE_VERTEX_BIT,
VK_SHADER_STAGE_GEOMETRY_BIT,
VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
VK_SHADER_STAGE_COMPUTE_BIT,
};
if (type >= VKD3D_SHADER_TYPE_COUNT)
return VKD3D_ERROR_INVALID_ARGUMENT;
if (table[type] != stages)
{
ERR("Expected VkShaderStage #%x, but got VkShaderStage #%x.\n", stages, table[type]);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
return 0;
}
int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_code *spirv, unsigned int compiler_options,
const struct vkd3d_shader_interface_info *shader_interface_info,
@ -336,49 +199,42 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x, shader_interface_info %p, compile_args %p.\n",
dxbc->code, dxbc->size, spirv, compiler_options, shader_interface_info, compile_args);
if (shader_interface_info && shader_interface_info->type != VKD3D_SHADER_STRUCTURE_TYPE_SHADER_INTERFACE_INFO)
{
WARN("Invalid structure type %#x.\n", shader_interface_info->type);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
if ((ret = vkd3d_shader_validate_compile_args(compile_args)) < 0)
return ret;
/* DXIL is handled externally through dxil-spirv. */
if (shader_is_dxil(dxbc->code, dxbc->size))
{
#ifdef HAVE_DXIL_SPV
return vkd3d_shader_compile_dxil(dxbc, spirv, shader_interface_info, compile_args);
#else
ERR("DXIL shader found, but DXIL support is not enabled in vkd3d.\n");
return VKD3D_ERROR_INVALID_SHADER;
#endif
}
memset(&spirv->meta, 0, sizeof(spirv->meta));
hash = vkd3d_shader_hash(dxbc);
spirv->meta.replaced = false;
spirv->meta.hash = hash;
if (vkd3d_shader_replace(hash, &spirv->code, &spirv->size))
{
spirv->meta.flags |= VKD3D_SHADER_META_FLAG_REPLACED;
spirv->meta.replaced = true;
return VKD3D_OK;
}
vkd3d_shader_scan_init(&scan_info);
scan_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO;
scan_info.next = NULL;
if ((ret = vkd3d_shader_scan_dxbc(dxbc, &scan_info)) < 0)
{
vkd3d_shader_scan_destroy(&scan_info);
return ret;
}
spirv->meta.patch_vertex_count = scan_info.patch_vertex_count;
if ((ret = vkd3d_shader_parser_init(&parser, dxbc)) < 0)
{
vkd3d_shader_scan_destroy(&scan_info);
return ret;
}
if (shader_interface_info)
{
if ((ret = vkd3d_shader_validate_shader_type(parser.shader_version.type, shader_interface_info->stage)) < 0)
{
vkd3d_shader_scan_destroy(&scan_info);
return ret;
}
}
vkd3d_shader_dump_shader(hash, dxbc, "dxbc");
@ -386,11 +242,9 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
vkd3d_shader_trace(parser.data);
if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&parser.shader_version,
&parser.shader_desc, compiler_options, shader_interface_info, compile_args, &scan_info,
spirv->meta.hash)))
&parser.shader_desc, compiler_options, shader_interface_info, compile_args, &scan_info)))
{
ERR("Failed to create DXBC compiler.\n");
vkd3d_shader_scan_destroy(&scan_info);
vkd3d_shader_parser_destroy(&parser);
return VKD3D_ERROR;
}
@ -403,7 +257,6 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
{
WARN("Encountered unrecognized or invalid instruction.\n");
vkd3d_dxbc_compiler_destroy(spirv_compiler);
vkd3d_shader_scan_destroy(&scan_info);
vkd3d_shader_parser_destroy(&parser);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@ -419,7 +272,6 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
vkd3d_shader_dump_spirv_shader(hash, spirv);
vkd3d_dxbc_compiler_destroy(spirv_compiler);
vkd3d_shader_scan_destroy(&scan_info);
vkd3d_shader_parser_destroy(&parser);
return ret;
}
@ -434,36 +286,11 @@ static bool vkd3d_shader_instruction_is_uav_read(const struct vkd3d_shader_instr
|| ((handler_idx == VKD3DSIH_LD_STRUCTURED || handler_idx == VKD3DSIH_LD_STRUCTURED_FEEDBACK) && instruction->src[2].reg.type == VKD3DSPR_UAV);
}
static bool vkd3d_shader_instruction_is_uav_write(const struct vkd3d_shader_instruction *instruction)
{
enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx = instruction->handler_idx;
return (VKD3DSIH_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_ATOMIC_XOR)
|| (VKD3DSIH_IMM_ATOMIC_ALLOC <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR)
|| handler_idx == VKD3DSIH_STORE_UAV_TYPED
|| handler_idx == VKD3DSIH_STORE_RAW
|| handler_idx == VKD3DSIH_STORE_STRUCTURED;
}
static bool vkd3d_shader_instruction_is_uav_atomic(const struct vkd3d_shader_instruction *instruction)
{
enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx = instruction->handler_idx;
return ((VKD3DSIH_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_ATOMIC_XOR) ||
(VKD3DSIH_IMM_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR)) &&
handler_idx != VKD3DSIH_IMM_ATOMIC_CONSUME;
}
static void vkd3d_shader_scan_record_uav_read(struct vkd3d_shader_scan_info *scan_info,
const struct vkd3d_shader_register *reg)
{
vkd3d_shader_scan_set_register_flags(scan_info, VKD3DSPR_UAV,
reg->idx[0].offset, VKD3D_SHADER_UAV_FLAG_READ_ACCESS);
}
static void vkd3d_shader_scan_record_uav_atomic(struct vkd3d_shader_scan_info *scan_info,
const struct vkd3d_shader_register *reg)
{
vkd3d_shader_scan_set_register_flags(scan_info, VKD3DSPR_UAV,
reg->idx[0].offset, VKD3D_SHADER_UAV_FLAG_ATOMIC_ACCESS);
assert(reg->idx[0].offset < VKD3D_SHADER_MAX_UNORDERED_ACCESS_VIEWS);
scan_info->uav_flags[reg->idx[0].offset] |= VKD3D_SHADER_UAV_FLAG_READ_ACCESS;
}
static bool vkd3d_shader_instruction_is_uav_counter(const struct vkd3d_shader_instruction *instruction)
@ -476,10 +303,8 @@ static bool vkd3d_shader_instruction_is_uav_counter(const struct vkd3d_shader_in
static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_info *scan_info,
const struct vkd3d_shader_register *reg)
{
scan_info->has_side_effects = true;
scan_info->has_uav_counter = true;
vkd3d_shader_scan_set_register_flags(scan_info, VKD3DSPR_UAV,
reg->idx[0].offset, VKD3D_SHADER_UAV_FLAG_ATOMIC_COUNTER);
assert(reg->idx[0].offset < VKD3D_SHADER_MAX_UNORDERED_ACCESS_VIEWS);
scan_info->uav_flags[reg->idx[0].offset] |= VKD3D_SHADER_UAV_FLAG_ATOMIC_COUNTER;
}
static void vkd3d_shader_scan_input_declaration(struct vkd3d_shader_scan_info *scan_info,
@ -491,21 +316,14 @@ static void vkd3d_shader_scan_input_declaration(struct vkd3d_shader_scan_info *s
scan_info->use_vocp = true;
}
static void vkd3d_shader_scan_output_declaration(struct vkd3d_shader_scan_info *scan_info,
static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_info *scan_info,
const struct vkd3d_shader_instruction *instruction)
{
switch (instruction->declaration.dst.reg.type)
unsigned int sampler_index = instruction->declaration.dst.reg.idx[0].offset;
if (instruction->flags & VKD3DSI_SAMPLER_COMPARISON_MODE)
{
case VKD3DSPR_DEPTHOUT:
case VKD3DSPR_DEPTHOUTLE:
case VKD3DSPR_DEPTHOUTGE:
case VKD3DSPR_STENCILREFOUT:
case VKD3DSPR_SAMPLEMASK:
scan_info->needs_late_zs = true;
break;
default:
break;
assert(sampler_index < CHAR_BIT * sizeof(scan_info->sampler_comparison_mode_mask));
scan_info->sampler_comparison_mode_mask |= 1u << sampler_index;
}
}
@ -513,25 +331,14 @@ static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_info *scan_in
const struct vkd3d_shader_instruction *instruction)
{
unsigned int i;
bool is_atomic;
switch (instruction->handler_idx)
{
case VKD3DSIH_DCL_INPUT:
vkd3d_shader_scan_input_declaration(scan_info, instruction);
break;
case VKD3DSIH_DCL_OUTPUT:
vkd3d_shader_scan_output_declaration(scan_info, instruction);
break;
case VKD3DSIH_DISCARD:
scan_info->discards = true;
break;
case VKD3DSIH_DCL_GLOBAL_FLAGS:
if (instruction->flags & VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL)
scan_info->early_fragment_tests = true;
break;
case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT:
scan_info->patch_vertex_count = instruction->declaration.count;
case VKD3DSIH_DCL_SAMPLER:
vkd3d_shader_scan_sampler_declaration(scan_info, instruction);
break;
default:
break;
@ -539,35 +346,65 @@ static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_info *scan_in
if (vkd3d_shader_instruction_is_uav_read(instruction))
{
is_atomic = vkd3d_shader_instruction_is_uav_atomic(instruction);
for (i = 0; i < instruction->dst_count; ++i)
{
if (instruction->dst[i].reg.type == VKD3DSPR_UAV)
{
vkd3d_shader_scan_record_uav_read(scan_info, &instruction->dst[i].reg);
if (is_atomic)
vkd3d_shader_scan_record_uav_atomic(scan_info, &instruction->dst[i].reg);
}
}
for (i = 0; i < instruction->src_count; ++i)
{
if (instruction->src[i].reg.type == VKD3DSPR_UAV)
{
vkd3d_shader_scan_record_uav_read(scan_info, &instruction->src[i].reg);
if (is_atomic)
vkd3d_shader_scan_record_uav_atomic(scan_info, &instruction->src[i].reg);
}
}
}
if (vkd3d_shader_instruction_is_uav_write(instruction))
scan_info->has_side_effects = true;
if (vkd3d_shader_instruction_is_uav_counter(instruction))
vkd3d_shader_scan_record_uav_counter(scan_info, &instruction->src[0].reg);
}
int vkd3d_shader_scan_patch_vertex_count(const struct vkd3d_shader_code *dxbc,
unsigned int *patch_vertex_count)
{
struct vkd3d_shader_instruction instruction;
struct vkd3d_shader_parser parser;
int ret;
if (shader_is_dxil(dxbc->code, dxbc->size))
{
/* TODO */
*patch_vertex_count = 0;
return VKD3D_OK;
}
else
{
if ((ret = vkd3d_shader_parser_init(&parser, dxbc)) < 0)
return ret;
*patch_vertex_count = 0;
while (!shader_sm4_is_end(parser.data, &parser.ptr))
{
shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction);
if (instruction.handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
vkd3d_shader_parser_destroy(&parser);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
if (instruction.handler_idx == VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT)
{
*patch_vertex_count = instruction.declaration.count;
break;
}
}
vkd3d_shader_parser_destroy(&parser);
return VKD3D_OK;
}
}
int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_scan_info *scan_info)
{
@ -577,6 +414,12 @@ int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
TRACE("dxbc {%p, %zu}, scan_info %p.\n", dxbc->code, dxbc->size, scan_info);
if (scan_info->type != VKD3D_SHADER_STRUCTURE_TYPE_SCAN_INFO)
{
WARN("Invalid structure type %#x.\n", scan_info->type);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
if (shader_is_dxil(dxbc->code, dxbc->size))
{
/* There is nothing interesting to scan. DXIL does this internally. */
@ -587,6 +430,8 @@ int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
if ((ret = vkd3d_shader_parser_init(&parser, dxbc)) < 0)
return ret;
memset(scan_info, 0, sizeof(*scan_info));
while (!shader_sm4_is_end(parser.data, &parser.ptr))
{
shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction);
@ -675,14 +520,6 @@ int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
return shader_parse_input_signature(dxbc->code, dxbc->size, signature);
}
int vkd3d_shader_parse_output_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_signature *signature)
{
TRACE("dxbc {%p, %zu}, signature %p.\n", dxbc->code, dxbc->size, signature);
return shader_parse_output_signature(dxbc->code, dxbc->size, signature);
}
struct vkd3d_shader_signature_element *vkd3d_shader_find_signature_element(
const struct vkd3d_shader_signature *signature, const char *semantic_name,
unsigned int semantic_index, unsigned int stream_index)
@ -713,38 +550,23 @@ void vkd3d_shader_free_shader_signature(struct vkd3d_shader_signature *signature
signature->elements = NULL;
}
int vkd3d_shader_supports_dxil(void)
{
#ifdef HAVE_DXIL_SPV
return 1;
#else
return 0;
#endif
}
vkd3d_shader_hash_t vkd3d_shader_hash(const struct vkd3d_shader_code *shader)
{
vkd3d_shader_hash_t h = hash_fnv1_init();
vkd3d_shader_hash_t h = 0xcbf29ce484222325ull;
const uint8_t *code = shader->code;
size_t i, n;
for (i = 0, n = shader->size; i < n; i++)
h = hash_fnv1_iterate_u8(h, code[i]);
h = (h * 0x100000001b3ull) ^ code[i];
return h;
}
uint32_t vkd3d_shader_compile_arguments_select_quirks(
const struct vkd3d_shader_compile_arguments *compile_args, vkd3d_shader_hash_t shader_hash)
{
unsigned int i;
if (compile_args && compile_args->quirks)
{
for (i = 0; i < compile_args->quirks->num_hashes; i++)
if (compile_args->quirks->hashes[i].shader_hash == shader_hash)
return compile_args->quirks->hashes[i].quirks | compile_args->quirks->global_quirks;
return compile_args->quirks->default_quirks | compile_args->quirks->global_quirks;
}
else
return 0;
}
uint64_t vkd3d_shader_get_revision(void)
{
/* This is meant to be bumped every time a change is made to the shader compiler.
* Might get nuked later ...
* It's not immediately useful for invalidating pipeline caches, since that would mostly be covered
* by vkd3d-proton Git hash. */
return 1;
}

View File

@ -58,12 +58,9 @@
#define VKD3D_VEC4_SIZE 4
#define VKD3D_DVEC2_SIZE 2
#define VKD3D_DOUBLE_DWORD_SIZE 2
#define VKD3D_DVEC2_DWORD_SIZE (VKD3D_DOUBLE_DWORD_SIZE * VKD3D_DVEC2_SIZE)
enum VKD3D_SHADER_INSTRUCTION_HANDLER
{
VKD3DSIH_ABS,
VKD3DSIH_ADD,
VKD3DSIH_AND,
VKD3DSIH_ATOMIC_AND,
@ -86,9 +83,12 @@ enum VKD3D_SHADER_INSTRUCTION_HANDLER
VKD3DSIH_CALLNZ,
VKD3DSIH_CASE,
VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED,
VKD3DSIH_CMP,
VKD3DSIH_CND,
VKD3DSIH_CONTINUE,
VKD3DSIH_CONTINUEP,
VKD3DSIH_COUNTBITS,
VKD3DSIH_CRS,
VKD3DSIH_CUT,
VKD3DSIH_CUT_STREAM,
VKD3DSIH_DCL,
@ -131,11 +131,16 @@ enum VKD3D_SHADER_INSTRUCTION_HANDLER
VKD3DSIH_DCL_UAV_STRUCTURED,
VKD3DSIH_DCL_UAV_TYPED,
VKD3DSIH_DCL_VERTICES_OUT,
VKD3DSIH_DEF,
VKD3DSIH_DEFAULT,
VKD3DSIH_DEFB,
VKD3DSIH_DEFI,
VKD3DSIH_DIV,
VKD3DSIH_DP2,
VKD3DSIH_DP2ADD,
VKD3DSIH_DP3,
VKD3DSIH_DP4,
VKD3DSIH_DST,
VKD3DSIH_DSX,
VKD3DSIH_DSX_COARSE,
VKD3DSIH_DSX_FINE,
@ -144,17 +149,16 @@ enum VKD3D_SHADER_INSTRUCTION_HANDLER
VKD3DSIH_DSY_FINE,
VKD3DSIH_ELSE,
VKD3DSIH_EMIT,
VKD3DSIH_EMIT_THEN_CUT,
VKD3DSIH_EMIT_STREAM,
VKD3DSIH_EMIT_THEN_CUT_STREAM,
VKD3DSIH_ENDIF,
VKD3DSIH_ENDLOOP,
VKD3DSIH_ENDREP,
VKD3DSIH_ENDSWITCH,
VKD3DSIH_EQ,
VKD3DSIH_EVAL_CENTROID,
VKD3DSIH_EVAL_SAMPLE_INDEX,
VKD3DSIH_EVAL_SNAPPED,
VKD3DSIH_EXP,
VKD3DSIH_EXPP,
VKD3DSIH_F16TOF32,
VKD3DSIH_F32TOF16,
VKD3DSIH_FCALL,
@ -216,23 +220,34 @@ enum VKD3D_SHADER_INSTRUCTION_HANDLER
VKD3DSIH_LD_STRUCTURED_FEEDBACK,
VKD3DSIH_LD_UAV_TYPED,
VKD3DSIH_LD_UAV_TYPED_FEEDBACK,
VKD3DSIH_LIT,
VKD3DSIH_LOD,
VKD3DSIH_LOG,
VKD3DSIH_LOGP,
VKD3DSIH_LOOP,
VKD3DSIH_LRP,
VKD3DSIH_LT,
VKD3DSIH_M3x2,
VKD3DSIH_M3x3,
VKD3DSIH_M3x4,
VKD3DSIH_M4x3,
VKD3DSIH_M4x4,
VKD3DSIH_MAD,
VKD3DSIH_MAX,
VKD3DSIH_MIN,
VKD3DSIH_MOV,
VKD3DSIH_MOVA,
VKD3DSIH_MOVC,
VKD3DSIH_MUL,
VKD3DSIH_NE,
VKD3DSIH_NOP,
VKD3DSIH_NOT,
VKD3DSIH_NRM,
VKD3DSIH_OR,
VKD3DSIH_PHASE,
VKD3DSIH_POW,
VKD3DSIH_RCP,
VKD3DSIH_REP,
VKD3DSIH_RESINFO,
VKD3DSIH_RET,
VKD3DSIH_RETP,
@ -255,6 +270,7 @@ enum VKD3D_SHADER_INSTRUCTION_HANDLER
VKD3DSIH_SAMPLE_LOD,
VKD3DSIH_SAMPLE_LOD_FEEDBACK,
VKD3DSIH_SAMPLE_POS,
VKD3DSIH_SETP,
VKD3DSIH_SGE,
VKD3DSIH_SGN,
VKD3DSIH_SINCOS,
@ -267,7 +283,28 @@ enum VKD3D_SHADER_INSTRUCTION_HANDLER
VKD3DSIH_SWAPC,
VKD3DSIH_SWITCH,
VKD3DSIH_SYNC,
VKD3DSIH_DISCARD,
VKD3DSIH_TEX,
VKD3DSIH_TEXBEM,
VKD3DSIH_TEXBEML,
VKD3DSIH_TEXCOORD,
VKD3DSIH_TEXDEPTH,
VKD3DSIH_TEXDP3,
VKD3DSIH_TEXDP3TEX,
VKD3DSIH_TEXKILL,
VKD3DSIH_TEXLDD,
VKD3DSIH_TEXLDL,
VKD3DSIH_TEXM3x2DEPTH,
VKD3DSIH_TEXM3x2PAD,
VKD3DSIH_TEXM3x2TEX,
VKD3DSIH_TEXM3x3,
VKD3DSIH_TEXM3x3DIFF,
VKD3DSIH_TEXM3x3PAD,
VKD3DSIH_TEXM3x3SPEC,
VKD3DSIH_TEXM3x3TEX,
VKD3DSIH_TEXM3x3VSPEC,
VKD3DSIH_TEXREG2AR,
VKD3DSIH_TEXREG2GB,
VKD3DSIH_TEXREG2RGB,
VKD3DSIH_UBFE,
VKD3DSIH_UDIV,
VKD3DSIH_UGE,
@ -275,44 +312,38 @@ enum VKD3D_SHADER_INSTRUCTION_HANDLER
VKD3DSIH_UMAX,
VKD3DSIH_UMIN,
VKD3DSIH_UMUL,
VKD3DSIH_UMAD,
VKD3DSIH_USHR,
VKD3DSIH_UTOF,
VKD3DSIH_XOR,
VKD3DSIH_DADD,
VKD3DSIH_DMAX,
VKD3DSIH_DMIN,
VKD3DSIH_DMUL,
VKD3DSIH_DEQ,
VKD3DSIH_DGE,
VKD3DSIH_DLT,
VKD3DSIH_DNE,
VKD3DSIH_DMOV,
VKD3DSIH_DMOVC,
VKD3DSIH_DTOF,
VKD3DSIH_FTOD,
VKD3DSIH_DDIV,
VKD3DSIH_DFMA,
VKD3DSIH_DRCP,
VKD3DSIH_DTOI,
VKD3DSIH_DTOU,
VKD3DSIH_ITOD,
VKD3DSIH_UTOD,
VKD3DSIH_INVALID,
};
enum vkd3d_shader_register_type
{
VKD3DSPR_TEMP,
VKD3DSPR_INPUT,
VKD3DSPR_OUTPUT,
VKD3DSPR_COLOROUT,
VKD3DSPR_DEPTHOUT,
VKD3DSPR_SAMPLER,
VKD3DSPR_TEMP = 0,
VKD3DSPR_INPUT = 1,
VKD3DSPR_CONST = 2,
VKD3DSPR_ADDR = 3,
VKD3DSPR_TEXTURE = 3,
VKD3DSPR_RASTOUT = 4,
VKD3DSPR_ATTROUT = 5,
VKD3DSPR_TEXCRDOUT = 6,
VKD3DSPR_OUTPUT = 6,
VKD3DSPR_CONSTINT = 7,
VKD3DSPR_COLOROUT = 8,
VKD3DSPR_DEPTHOUT = 9,
VKD3DSPR_SAMPLER = 10,
VKD3DSPR_CONST2 = 11,
VKD3DSPR_CONST3 = 12,
VKD3DSPR_CONST4 = 13,
VKD3DSPR_CONSTBOOL = 14,
VKD3DSPR_LOOP = 15,
VKD3DSPR_TEMPFLOAT16 = 16,
VKD3DSPR_MISCTYPE = 17,
VKD3DSPR_LABEL = 18,
VKD3DSPR_PREDICATE = 19,
VKD3DSPR_IMMCONST,
VKD3DSPR_IMMCONST64,
VKD3DSPR_CONSTBUFFER,
VKD3DSPR_IMMCONSTBUFFER,
VKD3DSPR_PRIMID,
@ -342,7 +373,6 @@ enum vkd3d_shader_register_type
VKD3DSPR_DEPTHOUTLE,
VKD3DSPR_RASTERIZER,
VKD3DSPR_STENCILREFOUT,
VKD3DSPR_INNERCOVERAGE,
VKD3DSPR_INVALID = ~0u,
};
@ -373,14 +403,12 @@ enum vkd3d_data_type
VKD3D_DATA_UNORM,
VKD3D_DATA_SNORM,
VKD3D_DATA_OPAQUE,
VKD3D_DATA_DOUBLE,
};
enum vkd3d_immconst_type
{
VKD3D_IMMCONST_SCALAR,
VKD3D_IMMCONST_VEC4,
VKD3D_IMMCONST_DVEC2 = VKD3D_IMMCONST_VEC4,
};
enum vkd3d_shader_register_modifier
@ -393,8 +421,18 @@ enum vkd3d_shader_src_modifier
{
VKD3DSPSM_NONE = 0,
VKD3DSPSM_NEG = 1,
VKD3DSPSM_ABS = 2,
VKD3DSPSM_ABSNEG = 3
VKD3DSPSM_BIAS = 2,
VKD3DSPSM_BIASNEG = 3,
VKD3DSPSM_SIGN = 4,
VKD3DSPSM_SIGNNEG = 5,
VKD3DSPSM_COMP = 6,
VKD3DSPSM_X2 = 7,
VKD3DSPSM_X2NEG = 8,
VKD3DSPSM_DZ = 9,
VKD3DSPSM_DW = 10,
VKD3DSPSM_ABS = 11,
VKD3DSPSM_ABSNEG = 12,
VKD3DSPSM_NOT = 13,
};
#define VKD3DSP_WRITEMASK_0 0x1u /* .x r */
@ -406,7 +444,9 @@ enum vkd3d_shader_src_modifier
enum vkd3d_shader_dst_modifier
{
VKD3DSPDM_NONE = 0,
VKD3DSPDM_SATURATE = 1
VKD3DSPDM_SATURATE = 1,
VKD3DSPDM_PARTIALPRECISION = 2,
VKD3DSPDM_MSAMPCENTROID = 4,
};
enum vkd3d_shader_interpolation_mode
@ -424,11 +464,9 @@ enum vkd3d_shader_interpolation_mode
enum vkd3d_shader_global_flags
{
VKD3DSGF_REFACTORING_ALLOWED = 0x01,
VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS = 0x02,
VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL = 0x04,
VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS = 0x08,
VKD3DSGF_ENABLE_MINIMUM_PRECISION = 0x20,
VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS = 0x40,
VKD3DSGF_ENABLE_MINIMUM_PRECISION = 0x20
};
enum vkd3d_shader_sync_flags
@ -451,6 +489,7 @@ enum vkd3d_tessellator_domain
};
#define VKD3DSI_NONE 0x0
#define VKD3DSI_TEXLD_PROJECT 0x1
#define VKD3DSI_INDEXED_DYNAMIC 0x4
#define VKD3DSI_RESINFO_RCP_FLOAT 0x1
#define VKD3DSI_RESINFO_UINT 0x2
@ -481,6 +520,8 @@ enum vkd3d_shader_conditional_op
VKD3D_SHADER_CONDITIONAL_OP_Z = 1
};
#define VKD3D_SM1_VS 0xfffeu
#define VKD3D_SM1_PS 0xffffu
#define VKD3D_SM4_PS 0x0000u
#define VKD3D_SM4_VS 0x0001u
#define VKD3D_SM4_GS 0x0002u
@ -488,6 +529,10 @@ enum vkd3d_shader_conditional_op
#define VKD3D_SM5_DS 0x0004u
#define VKD3D_SM5_CS 0x0005u
/* Shader version tokens, and shader end tokens */
#define VKD3DPS_VERSION(major, minor) ((VKD3D_SM1_PS << 16) | ((major) << 8) | (minor))
#define VKD3DVS_VERSION(major, minor) ((VKD3D_SM1_VS << 16) | ((major) << 8) | (minor))
#define MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE 4096
#define MAX_REG_OUTPUT 32
@ -542,8 +587,6 @@ struct vkd3d_shader_register
{
uint32_t immconst_uint[VKD3D_VEC4_SIZE];
float immconst_float[VKD3D_VEC4_SIZE];
double immconst_double[VKD3D_DVEC2_SIZE];
uint64_t immconst_uint64[VKD3D_DVEC2_SIZE];
unsigned fp_body_idx;
};
};
@ -553,6 +596,7 @@ struct vkd3d_shader_dst_param
struct vkd3d_shader_register reg;
DWORD write_mask;
DWORD modifiers;
DWORD shift;
};
struct vkd3d_shader_src_param
@ -568,8 +612,28 @@ struct vkd3d_shader_index_range
unsigned int register_count;
};
enum vkd3d_decl_usage
{
VKD3D_DECL_USAGE_POSITION = 0,
VKD3D_DECL_USAGE_BLEND_WEIGHT = 1,
VKD3D_DECL_USAGE_BLEND_INDICES = 2,
VKD3D_DECL_USAGE_NORMAL = 3,
VKD3D_DECL_USAGE_PSIZE = 4,
VKD3D_DECL_USAGE_TEXCOORD = 5,
VKD3D_DECL_USAGE_TANGENT = 6,
VKD3D_DECL_USAGE_BINORMAL = 7,
VKD3D_DECL_USAGE_TESS_FACTOR = 8,
VKD3D_DECL_USAGE_POSITIONT = 9,
VKD3D_DECL_USAGE_COLOR = 10,
VKD3D_DECL_USAGE_FOG = 11,
VKD3D_DECL_USAGE_DEPTH = 12,
VKD3D_DECL_USAGE_SAMPLE = 13
};
struct vkd3d_shader_semantic
{
enum vkd3d_decl_usage usage;
unsigned int usage_idx;
enum vkd3d_shader_resource_type resource_type;
enum vkd3d_data_type resource_data_type;
struct vkd3d_shader_dst_param reg;
@ -761,28 +825,26 @@ static inline bool vkd3d_shader_register_is_output(const struct vkd3d_shader_reg
return reg->type == VKD3DSPR_OUTPUT || reg->type == VKD3DSPR_COLOROUT;
}
void vkd3d_shader_trace(void *data);
void vkd3d_shader_trace(void *data) DECLSPEC_HIDDEN;
const char *shader_get_type_prefix(enum vkd3d_shader_type type);
const char *shader_get_type_prefix(enum vkd3d_shader_type type) DECLSPEC_HIDDEN;
void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size,
const struct vkd3d_shader_signature *output_signature);
void shader_sm4_free(void *data);
const struct vkd3d_shader_signature *output_signature) DECLSPEC_HIDDEN;
void shader_sm4_free(void *data) DECLSPEC_HIDDEN;
void shader_sm4_read_header(void *data, const DWORD **ptr,
struct vkd3d_shader_version *shader_version);
struct vkd3d_shader_version *shader_version) DECLSPEC_HIDDEN;
void shader_sm4_read_instruction(void *data, const DWORD **ptr,
struct vkd3d_shader_instruction *ins);
bool shader_sm4_is_end(void *data, const DWORD **ptr);
struct vkd3d_shader_instruction *ins) DECLSPEC_HIDDEN;
bool shader_sm4_is_end(void *data, const DWORD **ptr) DECLSPEC_HIDDEN;
int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
struct vkd3d_shader_desc *desc);
bool shader_is_dxil(const void *dxbc, size_t dxbc_length);
void free_shader_desc(struct vkd3d_shader_desc *desc);
struct vkd3d_shader_desc *desc) DECLSPEC_HIDDEN;
bool shader_is_dxil(const void *dxbc, size_t dxbc_length) DECLSPEC_HIDDEN;
void free_shader_desc(struct vkd3d_shader_desc *desc) DECLSPEC_HIDDEN;
int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
struct vkd3d_shader_signature *signature);
int shader_parse_output_signature(const void *dxbc, size_t dxbc_length,
struct vkd3d_shader_signature *signature);
struct vkd3d_shader_signature *signature) DECLSPEC_HIDDEN;
struct vkd3d_dxbc_compiler;
@ -790,22 +852,18 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
const struct vkd3d_shader_desc *shader_desc, uint32_t compiler_options,
const struct vkd3d_shader_interface_info *shader_interface_info,
const struct vkd3d_shader_compile_arguments *compile_args,
const struct vkd3d_shader_scan_info *scan_info,
vkd3d_shader_hash_t shader_hash);
const struct vkd3d_shader_scan_info *scan_info) DECLSPEC_HIDDEN;
int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction);
const struct vkd3d_shader_instruction *instruction) DECLSPEC_HIDDEN;
int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
struct vkd3d_shader_code *spirv);
void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler);
struct vkd3d_shader_code *spirv) DECLSPEC_HIDDEN;
void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler) DECLSPEC_HIDDEN;
void vkd3d_compute_dxbc_checksum(const void *dxbc, size_t size, uint32_t checksum[4]);
void vkd3d_compute_dxbc_checksum(const void *dxbc, size_t size, uint32_t checksum[4]) DECLSPEC_HIDDEN;
void vkd3d_shader_dump_spirv_shader(vkd3d_shader_hash_t hash, const struct vkd3d_shader_code *shader);
void vkd3d_shader_dump_spirv_shader_export(vkd3d_shader_hash_t hash, const struct vkd3d_shader_code *shader,
const char *export);
void vkd3d_shader_dump_shader(vkd3d_shader_hash_t hash, const struct vkd3d_shader_code *shader, const char *ext);
bool vkd3d_shader_replace(vkd3d_shader_hash_t hash, const void **data, size_t *size);
bool vkd3d_shader_replace_export(vkd3d_shader_hash_t hash, const void **data, size_t *size, const char *export);
void vkd3d_shader_dump_spirv_shader(vkd3d_shader_hash_t hash, const struct vkd3d_shader_code *shader) DECLSPEC_HIDDEN;
void vkd3d_shader_dump_shader(vkd3d_shader_hash_t hash, const struct vkd3d_shader_code *shader, const char *ext) DECLSPEC_HIDDEN;
bool vkd3d_shader_replace(vkd3d_shader_hash_t hash, const void **data, size_t *size) DECLSPEC_HIDDEN;
static inline enum vkd3d_component_type vkd3d_component_type_from_data_type(
enum vkd3d_data_type data_type)
@ -820,8 +878,6 @@ static inline enum vkd3d_component_type vkd3d_component_type_from_data_type(
return VKD3D_TYPE_UINT;
case VKD3D_DATA_INT:
return VKD3D_TYPE_INT;
case VKD3D_DATA_DOUBLE:
return VKD3D_TYPE_DOUBLE;
default:
FIXME("Unhandled data type %#x.\n", data_type);
return VKD3D_TYPE_UINT;
@ -839,8 +895,6 @@ static inline enum vkd3d_data_type vkd3d_data_type_from_component_type(
return VKD3D_DATA_UINT;
case VKD3D_TYPE_INT:
return VKD3D_DATA_INT;
case VKD3D_TYPE_DOUBLE:
return VKD3D_DATA_DOUBLE;
default:
FIXME("Unhandled component type %#x.\n", component_type);
return VKD3D_DATA_FLOAT;
@ -869,16 +923,6 @@ static inline unsigned int vkd3d_write_mask_component_count(DWORD write_mask)
return count;
}
static inline unsigned int vkd3d_write_mask_component_count_typed(DWORD write_mask,
enum vkd3d_component_type type)
{
unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
if (type == VKD3D_TYPE_DOUBLE)
component_count /= 2;
assert(component_count != 0);
return component_count;
}
static inline unsigned int vkd3d_write_mask_from_component_count(unsigned int component_count)
{
assert(component_count <= VKD3D_VEC4_SIZE);
@ -907,16 +951,36 @@ static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned
return compacted_swizzle;
}
struct vkd3d_struct
{
enum vkd3d_shader_structure_type type;
const void *next;
};
#define vkd3d_find_struct(c, t) vkd3d_find_struct_(c, VKD3D_SHADER_STRUCTURE_TYPE_##t)
static inline const void *vkd3d_find_struct_(const struct vkd3d_struct *chain,
enum vkd3d_shader_structure_type type)
{
while (chain)
{
if (chain->type == type)
return chain;
chain = chain->next;
}
return NULL;
}
#define VKD3D_DXBC_MAX_SOURCE_COUNT 6
#define VKD3D_DXBC_HEADER_SIZE (8 * sizeof(uint32_t))
unsigned int vkd3d_shader_scan_get_register_flags(const struct vkd3d_shader_scan_info *scan_info,
enum vkd3d_shader_register_type type, unsigned int id);
/* DXIL support */
int vkd3d_shader_compile_dxil(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_code *spirv,
const struct vkd3d_shader_interface_info *shader_interface_info,
const struct vkd3d_shader_compile_arguments *compiler_args);
vkd3d_shader_hash_t vkd3d_shader_hash(const struct vkd3d_shader_code *shader) DECLSPEC_HIDDEN;
#endif /* __VKD3D_SHADER_PRIVATE_H */

View File

@ -2,18 +2,13 @@ vkd3d_utils_src = [
'vkd3d_utils_main.c',
]
vkd3d_utils_lib = shared_library('vkd3d-proton-utils', vkd3d_utils_src,
vkd3d_utils_lib = shared_library('vkd3d-utils', vkd3d_utils_src, vkd3d_headers,
dependencies : vkd3d_dep,
include_directories : vkd3d_private_includes,
install : true,
objects : not vkd3d_is_msvc and vkd3d_platform == 'windows'
? 'vkd3d-proton-utils.def'
: [],
vs_module_defs : 'vkd3d-proton-utils.def',
version : '3.0.0',
c_args : '-DVKD3D_UTILS_EXPORTS',
vs_module_defs : 'vkd3d_utils.def',
override_options : [ 'c_std='+vkd3d_c_std ])
vkd3d_utils_dep = declare_dependency(
link_with : vkd3d_utils_lib,
include_directories : vkd3d_public_includes)
include_directories : vkd3d_public_includes)

View File

@ -1,16 +1,13 @@
LIBRARY vkd3d-proton-utils-3.dll
LIBRARY vkd3d-utils
EXPORTS
D3D12CreateDevice @101
D3D12GetDebugInterface @102
D3D12CreateDevice
D3D12CreateRootSignatureDeserializer
D3D12CreateVersionedRootSignatureDeserializer
D3D12EnableExperimentalFeatures
D3D12GetDebugInterface
D3D12SerializeRootSignature
D3D12SerializeVersionedRootSignature
vkd3d_create_event
vkd3d_wait_event
vkd3d_signal_event
vkd3d_destroy_event
vkd3d_signal_event
vkd3d_wait_event

View File

@ -0,0 +1,16 @@
VKD3D_1_0
{
global:
D3D12CreateDevice;
D3D12CreateRootSignatureDeserializer;
D3D12CreateVersionedRootSignatureDeserializer;
D3D12GetDebugInterface;
D3D12SerializeRootSignature;
D3D12SerializeVersionedRootSignature;
vkd3d_create_event;
vkd3d_destroy_event;
vkd3d_signal_event;
vkd3d_wait_event;
local: *;
};

View File

@ -21,16 +21,17 @@
#include "vkd3d_common.h"
#include "vkd3d_utils_private.h"
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12GetDebugInterface(REFIID iid, void **debug)
HRESULT WINAPI D3D12GetDebugInterface(REFIID iid, void **debug)
{
FIXME("iid %s, debug %p stub!\n", debugstr_guid(iid), debug);
return E_NOTIMPL;
}
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter,
HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter,
D3D_FEATURE_LEVEL minimum_feature_level, REFIID iid, void **device)
{
struct vkd3d_optional_instance_extensions_info optional_extensions_info;
struct vkd3d_instance_create_info instance_create_info;
struct vkd3d_device_create_info device_create_info;
@ -54,14 +55,22 @@ VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter,
if (adapter)
FIXME("Ignoring adapter %p.\n", adapter);
memset(&optional_extensions_info, 0, sizeof(optional_extensions_info));
optional_extensions_info.type = VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO;
optional_extensions_info.extensions = optional_instance_extensions;
optional_extensions_info.extension_count = ARRAY_SIZE(optional_instance_extensions);
memset(&instance_create_info, 0, sizeof(instance_create_info));
instance_create_info.type = VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_create_info.next = &optional_extensions_info;
instance_create_info.pfn_signal_event = vkd3d_signal_event;
instance_create_info.wchar_size = sizeof(WCHAR);
instance_create_info.instance_extensions = instance_extensions;
instance_create_info.instance_extension_count = ARRAY_SIZE(instance_extensions);
instance_create_info.optional_instance_extensions = optional_instance_extensions;
instance_create_info.optional_instance_extension_count = ARRAY_SIZE(optional_instance_extensions);
memset(&device_create_info, 0, sizeof(device_create_info));
device_create_info.type = VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.next = NULL;
device_create_info.minimum_feature_level = minimum_feature_level;
device_create_info.instance_create_info = &instance_create_info;
device_create_info.device_extensions = device_extensions;
@ -70,7 +79,7 @@ VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter,
return vkd3d_create_device(&device_create_info, iid, device);
}
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size,
HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size,
REFIID iid, void **deserializer)
{
TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n",
@ -79,7 +88,7 @@ VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const voi
return vkd3d_create_root_signature_deserializer(data, data_size, iid, deserializer);
}
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateVersionedRootSignatureDeserializer(const void *data, SIZE_T data_size,
HRESULT WINAPI D3D12CreateVersionedRootSignatureDeserializer(const void *data, SIZE_T data_size,
REFIID iid,void **deserializer)
{
TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n",
@ -88,16 +97,7 @@ VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12CreateVersionedRootSignatureDeserializer(
return vkd3d_create_versioned_root_signature_deserializer(data, data_size, iid, deserializer);
}
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12EnableExperimentalFeatures(UINT feature_count,
const IID *iids, void *configurations, UINT *configurations_sizes)
{
FIXME("feature_count %u, iids %p, configurations %p, configurations_sizes %p stub!\n",
feature_count, iids, configurations, configurations_sizes);
return E_NOINTERFACE;
}
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *desc,
HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *desc,
D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob)
{
TRACE("desc %p, version %#x, blob %p, error_blob %p.\n", desc, version, blob, error_blob);
@ -105,7 +105,7 @@ VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_S
return vkd3d_serialize_root_signature(desc, version, blob, error_blob);
}
VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
HRESULT WINAPI D3D12SerializeVersionedRootSignature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
ID3DBlob **blob, ID3DBlob **error_blob)
{
TRACE("desc %p, blob %p, error_blob %p.\n", desc, blob, error_blob);
@ -114,7 +114,7 @@ VKD3D_UTILS_EXPORT HRESULT WINAPI D3D12SerializeVersionedRootSignature(const D3D
}
/* Events */
VKD3D_UTILS_EXPORT HANDLE vkd3d_create_event(void)
HANDLE vkd3d_create_event(void)
{
struct vkd3d_event *event;
int rc;
@ -145,7 +145,7 @@ VKD3D_UTILS_EXPORT HANDLE vkd3d_create_event(void)
return event;
}
VKD3D_UTILS_EXPORT unsigned int vkd3d_wait_event(HANDLE event, unsigned int milliseconds)
unsigned int vkd3d_wait_event(HANDLE event, unsigned int milliseconds)
{
struct vkd3d_event *impl = event;
int rc;
@ -188,7 +188,7 @@ VKD3D_UTILS_EXPORT unsigned int vkd3d_wait_event(HANDLE event, unsigned int mill
return VKD3D_WAIT_FAILED;
}
VKD3D_UTILS_EXPORT HRESULT vkd3d_signal_event(HANDLE event)
HRESULT vkd3d_signal_event(HANDLE event)
{
struct vkd3d_event *impl = event;
int rc;
@ -207,7 +207,7 @@ VKD3D_UTILS_EXPORT HRESULT vkd3d_signal_event(HANDLE event)
return S_OK;
}
VKD3D_UTILS_EXPORT void vkd3d_destroy_event(HANDLE event)
void vkd3d_destroy_event(HANDLE event)
{
struct vkd3d_event *impl = event;
int rc;

View File

@ -1,498 +0,0 @@
/*
* Copyright 2021 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_private.h"
#define RT_TRACE TRACE
void vkd3d_acceleration_structure_build_info_cleanup(
struct vkd3d_acceleration_structure_build_info *info)
{
if (info->primitive_counts != info->primitive_counts_stack)
vkd3d_free(info->primitive_counts);
if (info->geometries != info->geometries_stack)
vkd3d_free(info->geometries);
if (info->build_range_ptrs != info->build_range_ptr_stack)
vkd3d_free((void *)info->build_range_ptrs);
if (info->build_ranges != info->build_range_stack)
vkd3d_free(info->build_ranges);
}
static VkBuildAccelerationStructureFlagsKHR d3d12_build_flags_to_vk(
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS flags)
{
VkBuildAccelerationStructureFlagsKHR vk_flags = 0;
if (flags & D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_ALLOW_COMPACTION)
vk_flags |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
if (flags & D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_ALLOW_UPDATE)
vk_flags |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
if (flags & D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_MINIMIZE_MEMORY)
vk_flags |= VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR;
if (flags & D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_BUILD)
vk_flags |= VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR;
if (flags & D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE)
vk_flags |= VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
return vk_flags;
}
static VkGeometryFlagsKHR d3d12_geometry_flags_to_vk(D3D12_RAYTRACING_GEOMETRY_FLAGS flags)
{
VkGeometryFlagsKHR vk_flags = 0;
if (flags & D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE)
vk_flags |= VK_GEOMETRY_OPAQUE_BIT_KHR;
if (flags & D3D12_RAYTRACING_GEOMETRY_FLAG_NO_DUPLICATE_ANYHIT_INVOCATION)
vk_flags |= VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR;
return vk_flags;
}
bool vkd3d_acceleration_structure_convert_inputs(const struct d3d12_device *device,
struct vkd3d_acceleration_structure_build_info *info,
const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS *desc)
{
VkAccelerationStructureGeometryTrianglesDataKHR *triangles;
VkAccelerationStructureBuildGeometryInfoKHR *build_info;
VkAccelerationStructureGeometryAabbsDataKHR *aabbs;
const D3D12_RAYTRACING_GEOMETRY_DESC *geom_desc;
bool have_triangles, have_aabbs;
unsigned int i;
RT_TRACE("Converting inputs.\n");
RT_TRACE("=====================\n");
build_info = &info->build_info;
memset(build_info, 0, sizeof(*build_info));
build_info->sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
if (desc->Type == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL)
{
build_info->type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
RT_TRACE("Top level build.\n");
}
else
{
build_info->type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
RT_TRACE("Bottom level build.\n");
}
build_info->flags = d3d12_build_flags_to_vk(desc->Flags);
if (desc->Flags & D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PERFORM_UPDATE)
{
RT_TRACE("BUILD_FLAG_PERFORM_UPDATE.\n");
build_info->mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR;
}
else
build_info->mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
info->geometries = info->geometries_stack;
info->primitive_counts = info->primitive_counts_stack;
info->build_ranges = info->build_range_stack;
info->build_range_ptrs = info->build_range_ptr_stack;
if (desc->Type == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL)
{
memset(info->geometries, 0, sizeof(*info->geometries));
info->geometries[0].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
info->geometries[0].geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
info->geometries[0].geometry.instances.sType =
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
info->geometries[0].geometry.instances.arrayOfPointers =
desc->DescsLayout == D3D12_ELEMENTS_LAYOUT_ARRAY_OF_POINTERS ? VK_TRUE : VK_FALSE;
info->geometries[0].geometry.instances.data.deviceAddress = desc->InstanceDescs;
info->primitive_counts = info->primitive_counts_stack;
info->primitive_counts[0] = desc->NumDescs;
build_info->geometryCount = 1;
RT_TRACE(" ArrayOfPointers: %u.\n",
desc->DescsLayout == D3D12_ELEMENTS_LAYOUT_ARRAY_OF_POINTERS ? 1 : 0);
RT_TRACE(" NumDescs: %u.\n", info->primitive_counts[0]);
}
else
{
have_triangles = false;
have_aabbs = false;
if (desc->NumDescs <= VKD3D_BUILD_INFO_STACK_COUNT)
{
memset(info->geometries, 0, sizeof(*info->geometries) * desc->NumDescs);
memset(info->primitive_counts, 0, sizeof(*info->primitive_counts) * desc->NumDescs);
}
else
{
info->geometries = vkd3d_calloc(desc->NumDescs, sizeof(*info->geometries));
info->primitive_counts = vkd3d_calloc(desc->NumDescs, sizeof(*info->primitive_counts));
info->build_ranges = vkd3d_malloc(desc->NumDescs * sizeof(*info->build_ranges));
info->build_range_ptrs = vkd3d_malloc(desc->NumDescs * sizeof(*info->build_range_ptrs));
}
build_info->geometryCount = desc->NumDescs;
for (i = 0; i < desc->NumDescs; i++)
{
info->geometries[i].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
RT_TRACE(" Geom %u:\n", i);
if (desc->DescsLayout == D3D12_ELEMENTS_LAYOUT_ARRAY_OF_POINTERS)
{
geom_desc = desc->ppGeometryDescs[i];
RT_TRACE(" ArrayOfPointers\n");
}
else
{
geom_desc = &desc->pGeometryDescs[i];
RT_TRACE(" PointerToArray\n");
}
info->geometries[i].flags = d3d12_geometry_flags_to_vk(geom_desc->Flags);
RT_TRACE(" Flags = #%x\n", geom_desc->Flags);
switch (geom_desc->Type)
{
case D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES:
/* Runtime validates this. */
if (have_aabbs)
{
ERR("Cannot mix and match geometry types in a BLAS.\n");
return false;
}
have_triangles = true;
info->geometries[i].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
triangles = &info->geometries[i].geometry.triangles;
triangles->sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
triangles->indexData.deviceAddress = geom_desc->Triangles.IndexBuffer;
if (geom_desc->Triangles.IndexFormat != DXGI_FORMAT_UNKNOWN)
{
if (!geom_desc->Triangles.IndexBuffer)
WARN("Application is using IndexBuffer = 0 and IndexFormat != UNKNOWN. Likely application bug.\n");
triangles->indexType =
geom_desc->Triangles.IndexFormat == DXGI_FORMAT_R16_UINT ?
VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32;
info->primitive_counts[i] = geom_desc->Triangles.IndexCount / 3;
RT_TRACE(" Indexed : Index count = %u (%u bits)\n",
geom_desc->Triangles.IndexCount,
triangles->indexType == VK_INDEX_TYPE_UINT16 ? 16 : 32);
RT_TRACE(" Vertex count: %u\n", geom_desc->Triangles.VertexCount);
RT_TRACE(" IBO VA: %"PRIx64".\n", geom_desc->Triangles.IndexBuffer);
}
else
{
info->primitive_counts[i] = geom_desc->Triangles.VertexCount / 3;
triangles->indexType = VK_INDEX_TYPE_NONE_KHR;
RT_TRACE(" Triangle list : Vertex count: %u\n", geom_desc->Triangles.VertexCount);
}
triangles->maxVertex = max(1, geom_desc->Triangles.VertexCount) - 1;
triangles->vertexStride = geom_desc->Triangles.VertexBuffer.StrideInBytes;
triangles->vertexFormat = vkd3d_internal_get_vk_format(device, geom_desc->Triangles.VertexFormat);
triangles->vertexData.deviceAddress = geom_desc->Triangles.VertexBuffer.StartAddress;
triangles->transformData.deviceAddress = geom_desc->Triangles.Transform3x4;
RT_TRACE(" Transform3x4: %s\n", geom_desc->Triangles.Transform3x4 ? "on" : "off");
RT_TRACE(" Vertex format: %s\n", debug_dxgi_format(geom_desc->Triangles.VertexFormat));
RT_TRACE(" VBO VA: %"PRIx64"\n", geom_desc->Triangles.VertexBuffer.StartAddress);
RT_TRACE(" Vertex stride: %"PRIu64" bytes\n", geom_desc->Triangles.VertexBuffer.StrideInBytes);
break;
case D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS:
/* Runtime validates this. */
if (have_triangles)
{
ERR("Cannot mix and match geometry types in a BLAS.\n");
return false;
}
have_aabbs = true;
info->geometries[i].geometryType = VK_GEOMETRY_TYPE_AABBS_KHR;
aabbs = &info->geometries[i].geometry.aabbs;
aabbs->sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR;
aabbs->stride = geom_desc->AABBs.AABBs.StrideInBytes;
aabbs->data.deviceAddress = geom_desc->AABBs.AABBs.StartAddress;
info->primitive_counts[i] = geom_desc->AABBs.AABBCount;
RT_TRACE(" AABB stride: %"PRIu64" bytes\n", geom_desc->AABBs.AABBs.StrideInBytes);
break;
default:
FIXME("Unsupported geometry type %u.\n", geom_desc->Type);
return false;
}
RT_TRACE(" Primitive count %u.\n", info->primitive_counts[i]);
}
}
for (i = 0; i < build_info->geometryCount; i++)
{
info->build_range_ptrs[i] = &info->build_ranges[i];
info->build_ranges[i].primitiveCount = info->primitive_counts[i];
info->build_ranges[i].firstVertex = 0;
info->build_ranges[i].primitiveOffset = 0;
info->build_ranges[i].transformOffset = 0;
}
build_info->pGeometries = info->geometries;
RT_TRACE("=====================\n");
return true;
}
static void vkd3d_acceleration_structure_end_barrier(struct d3d12_command_list *list)
{
/* We resolve the query in TRANSFER, but DXR expects UNORDERED_ACCESS. */
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
VkMemoryBarrier barrier;
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.pNext = NULL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = 0;
VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0,
1, &barrier, 0, NULL, 0, NULL));
}
static void vkd3d_acceleration_structure_write_postbuild_info(
struct d3d12_command_list *list,
const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC *desc,
VkDeviceSize desc_offset,
VkAccelerationStructureKHR vk_acceleration_structure)
{
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
const struct vkd3d_unique_resource *resource;
VkQueryPool vk_query_pool;
VkQueryType vk_query_type;
uint32_t vk_query_index;
VkDeviceSize stride;
uint32_t type_index;
VkBuffer vk_buffer;
uint32_t offset;
resource = vkd3d_va_map_deref(&list->device->memory_allocator.va_map, desc->DestBuffer);
if (!resource)
{
ERR("Invalid resource.\n");
return;
}
vk_buffer = resource->vk_buffer;
offset = desc->DestBuffer - resource->va;
offset += desc_offset;
if (desc->InfoType == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_COMPACTED_SIZE)
{
vk_query_type = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR;
type_index = VKD3D_QUERY_TYPE_INDEX_RT_COMPACTED_SIZE;
stride = sizeof(uint64_t);
}
else if (desc->InfoType == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_CURRENT_SIZE &&
list->device->device_info.ray_tracing_maintenance1_features.rayTracingMaintenance1)
{
vk_query_type = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR;
type_index = VKD3D_QUERY_TYPE_INDEX_RT_CURRENT_SIZE;
stride = sizeof(uint64_t);
}
else if (desc->InfoType == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_SERIALIZATION)
{
vk_query_type = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR;
type_index = VKD3D_QUERY_TYPE_INDEX_RT_SERIALIZE_SIZE;
stride = sizeof(uint64_t);
}
else
{
FIXME("Unsupported InfoType %u.\n", desc->InfoType);
/* TODO: CURRENT_SIZE is something we cannot query in Vulkan, so
* we'll need to keep around a buffer to handle this.
* For now, just clear to 0. */
VK_CALL(vkCmdFillBuffer(list->vk_command_buffer, vk_buffer, offset,
sizeof(uint64_t), 0));
return;
}
if (!d3d12_command_allocator_allocate_query_from_type_index(list->allocator,
type_index, &vk_query_pool, &vk_query_index))
{
ERR("Failed to allocate query.\n");
return;
}
d3d12_command_list_reset_query(list, vk_query_pool, vk_query_index);
VK_CALL(vkCmdWriteAccelerationStructuresPropertiesKHR(list->vk_command_buffer,
1, &vk_acceleration_structure, vk_query_type, vk_query_pool, vk_query_index));
VK_CALL(vkCmdCopyQueryPoolResults(list->vk_command_buffer,
vk_query_pool, vk_query_index, 1,
vk_buffer, offset, stride,
VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
if (desc->InfoType == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_SERIALIZATION)
{
if (list->device->device_info.ray_tracing_maintenance1_features.rayTracingMaintenance1)
{
type_index = VKD3D_QUERY_TYPE_INDEX_RT_SERIALIZE_SIZE_BOTTOM_LEVEL_POINTERS;
if (!d3d12_command_allocator_allocate_query_from_type_index(list->allocator,
type_index, &vk_query_pool, &vk_query_index))
{
ERR("Failed to allocate query.\n");
return;
}
d3d12_command_list_reset_query(list, vk_query_pool, vk_query_index);
VK_CALL(vkCmdWriteAccelerationStructuresPropertiesKHR(list->vk_command_buffer,
1, &vk_acceleration_structure, vk_query_type, vk_query_pool, vk_query_index));
VK_CALL(vkCmdCopyQueryPoolResults(list->vk_command_buffer,
vk_query_pool, vk_query_index, 1,
vk_buffer, offset + sizeof(uint64_t), stride,
VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
}
else
{
FIXME("NumBottomLevelPointers will always return 0.\n");
VK_CALL(vkCmdFillBuffer(list->vk_command_buffer, vk_buffer, offset + sizeof(uint64_t),
sizeof(uint64_t), 0));
}
}
}
void vkd3d_acceleration_structure_emit_postbuild_info(
struct d3d12_command_list *list,
const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC *desc,
uint32_t count,
const D3D12_GPU_VIRTUAL_ADDRESS *addresses)
{
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
VkAccelerationStructureKHR vk_acceleration_structure;
VkMemoryBarrier barrier;
VkDeviceSize stride;
uint32_t i;
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.pNext = NULL;
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
/* We resolve the query in TRANSFER, but DXR expects UNORDERED_ACCESS. */
VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
1, &barrier, 0, NULL, 0, NULL));
stride = desc->InfoType == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_SERIALIZATION ?
2 * sizeof(uint64_t) : sizeof(uint64_t);
for (i = 0; i < count; i++)
{
vk_acceleration_structure = vkd3d_va_map_place_acceleration_structure(
&list->device->memory_allocator.va_map, list->device, addresses[i]);
if (vk_acceleration_structure)
vkd3d_acceleration_structure_write_postbuild_info(list, desc, i * stride, vk_acceleration_structure);
else
ERR("Failed to query acceleration structure for VA 0x%"PRIx64".\n", addresses[i]);
}
vkd3d_acceleration_structure_end_barrier(list);
}
void vkd3d_acceleration_structure_emit_immediate_postbuild_info(
struct d3d12_command_list *list, uint32_t count,
const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC *desc,
VkAccelerationStructureKHR vk_acceleration_structure)
{
/* In D3D12 we are supposed to be able to emit without an explicit barrier,
* but we need to emit them for Vulkan. */
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
VkMemoryBarrier barrier;
uint32_t i;
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.pNext = NULL;
barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
/* The query accesses STRUCTURE_READ_BIT in BUILD_BIT stage. */
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_TRANSFER_WRITE_BIT;
/* Writing to the result buffer is supposed to happen in UNORDERED_ACCESS on DXR for
* some bizarre reason, so we have to satisfy a transfer barrier.
* Have to basically do a full stall to make this work ... */
VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
1, &barrier, 0, NULL, 0, NULL));
/* Could optimize a bit by batching more aggressively, but no idea if it's going to help in practice. */
for (i = 0; i < count; i++)
vkd3d_acceleration_structure_write_postbuild_info(list, &desc[i], 0, vk_acceleration_structure);
vkd3d_acceleration_structure_end_barrier(list);
}
static bool convert_copy_mode(
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE mode,
VkCopyAccelerationStructureModeKHR *vk_mode)
{
switch (mode)
{
case D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_CLONE:
*vk_mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR;
return true;
case D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_COMPACT:
*vk_mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR;
return true;
default:
FIXME("Unsupported RTAS copy mode #%x.\n", mode);
return false;
}
}
void vkd3d_acceleration_structure_copy(
struct d3d12_command_list *list,
D3D12_GPU_VIRTUAL_ADDRESS dst, D3D12_GPU_VIRTUAL_ADDRESS src,
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE mode)
{
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
VkAccelerationStructureKHR dst_as, src_as;
VkCopyAccelerationStructureInfoKHR info;
dst_as = vkd3d_va_map_place_acceleration_structure(&list->device->memory_allocator.va_map, list->device, dst);
if (dst_as == VK_NULL_HANDLE)
{
ERR("Invalid dst address #%"PRIx64" for RTAS copy.\n", dst);
return;
}
src_as = vkd3d_va_map_place_acceleration_structure(&list->device->memory_allocator.va_map, list->device, src);
if (src_as == VK_NULL_HANDLE)
{
ERR("Invalid src address #%"PRIx64" for RTAS copy.\n", src);
return;
}
info.sType = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR;
info.pNext = NULL;
info.dst = dst_as;
info.src = src_as;
if (convert_copy_mode(mode, &info.mode))
VK_CALL(vkCmdCopyAccelerationStructureKHR(list->vk_command_buffer, &info));
}

View File

@ -1,655 +0,0 @@
/*
* Copyright 2022 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_private.h"
#include "vkd3d_debug.h"
#include "vkd3d_common.h"
#include <assert.h>
#include <stdio.h>
/* Just allocate everything up front. This only consumes host memory anyways. */
#define MAX_COMMAND_LISTS (32 * 1024)
/* Questionable on 32-bit, but we don't really care. */
#define NV_ENCODE_CHECKPOINT(context, counter) ((void*) ((uintptr_t)(context) + (uintptr_t)MAX_COMMAND_LISTS * (counter)))
#define NV_CHECKPOINT_CONTEXT(ptr) ((uint32_t)((uintptr_t)(ptr) % MAX_COMMAND_LISTS))
#define NV_CHECKPOINT_COUNTER(ptr) ((uint32_t)((uintptr_t)(ptr) / MAX_COMMAND_LISTS))
static const char *vkd3d_breadcrumb_command_type_to_str(enum vkd3d_breadcrumb_command_type type)
{
switch (type)
{
case VKD3D_BREADCRUMB_COMMAND_SET_TOP_MARKER:
return "top_marker";
case VKD3D_BREADCRUMB_COMMAND_SET_BOTTOM_MARKER:
return "bottom_marker";
case VKD3D_BREADCRUMB_COMMAND_SET_SHADER_HASH:
return "set_shader_hash";
case VKD3D_BREADCRUMB_COMMAND_DRAW:
return "draw";
case VKD3D_BREADCRUMB_COMMAND_DRAW_INDEXED:
return "draw_indexed";
case VKD3D_BREADCRUMB_COMMAND_DISPATCH:
return "dispatch";
case VKD3D_BREADCRUMB_COMMAND_EXECUTE_INDIRECT:
return "execute_indirect";
case VKD3D_BREADCRUMB_COMMAND_EXECUTE_INDIRECT_TEMPLATE:
return "execute_indirect_template";
case VKD3D_BREADCRUMB_COMMAND_COPY:
return "copy";
case VKD3D_BREADCRUMB_COMMAND_RESOLVE:
return "resolve";
case VKD3D_BREADCRUMB_COMMAND_WBI:
return "wbi";
case VKD3D_BREADCRUMB_COMMAND_RESOLVE_QUERY:
return "resolve_query";
case VKD3D_BREADCRUMB_COMMAND_GATHER_VIRTUAL_QUERY:
return "gather_virtual_query";
case VKD3D_BREADCRUMB_COMMAND_BUILD_RTAS:
return "build_rtas";
case VKD3D_BREADCRUMB_COMMAND_COPY_RTAS:
return "copy_rtas";
case VKD3D_BREADCRUMB_COMMAND_EMIT_RTAS_POSTBUILD:
return "emit_rtas_postbuild";
case VKD3D_BREADCRUMB_COMMAND_TRACE_RAYS:
return "trace_rays";
case VKD3D_BREADCRUMB_COMMAND_BARRIER:
return "barrier";
case VKD3D_BREADCRUMB_COMMAND_AUX32:
return "aux32";
case VKD3D_BREADCRUMB_COMMAND_AUX64:
return "aux64";
case VKD3D_BREADCRUMB_COMMAND_VBO:
return "vbo";
case VKD3D_BREADCRUMB_COMMAND_IBO:
return "ibo";
case VKD3D_BREADCRUMB_COMMAND_ROOT_DESC:
return "root_desc";
case VKD3D_BREADCRUMB_COMMAND_ROOT_CONST:
return "root_const";
case VKD3D_BREADCRUMB_COMMAND_TAG:
return "tag";
default:
return "?";
}
}
HRESULT vkd3d_breadcrumb_tracer_init(struct vkd3d_breadcrumb_tracer *tracer, struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
D3D12_HEAP_PROPERTIES heap_properties;
D3D12_RESOURCE_DESC1 resource_desc;
VkMemoryPropertyFlags memory_props;
HRESULT hr;
int rc;
memset(tracer, 0, sizeof(*tracer));
if ((rc = pthread_mutex_init(&tracer->lock, NULL)))
return hresult_from_errno(rc);
if (device->vk_info.AMD_buffer_marker)
{
INFO("Enabling AMD_buffer_marker breadcrumbs.\n");
memset(&resource_desc, 0, sizeof(resource_desc));
resource_desc.Width = MAX_COMMAND_LISTS * sizeof(struct vkd3d_breadcrumb_counter);
resource_desc.Height = 1;
resource_desc.DepthOrArraySize = 1;
resource_desc.MipLevels = 1;
resource_desc.Format = DXGI_FORMAT_UNKNOWN;
resource_desc.SampleDesc.Count = 1;
resource_desc.SampleDesc.Quality = 0;
resource_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
if (FAILED(hr = vkd3d_create_buffer(device, &heap_properties, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS,
&resource_desc, &tracer->host_buffer)))
{
goto err;
}
memory_props = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
/* If device faults in the middle of execution we will never get the chance to flush device caches.
* Make sure that breadcrumbs are always written directly out.
* This is the primary usecase for the device coherent/uncached extension after all ...
* Don't make this a hard requirement since buffer markers might be implicitly coherent on some
* implementations (Turnip?). */
if (device->device_info.device_coherent_memory_features_amd.deviceCoherentMemory)
{
memory_props |= VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD |
VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD;
}
if (FAILED(hr = vkd3d_allocate_buffer_memory(device, tracer->host_buffer,
memory_props, &tracer->host_buffer_memory)))
{
goto err;
}
if (VK_CALL(vkMapMemory(device->vk_device, tracer->host_buffer_memory.vk_memory,
0, VK_WHOLE_SIZE,
0, (void**)&tracer->mapped)) != VK_SUCCESS)
{
hr = E_OUTOFMEMORY;
goto err;
}
memset(tracer->mapped, 0, sizeof(*tracer->mapped) * MAX_COMMAND_LISTS);
}
else if (device->vk_info.NV_device_diagnostic_checkpoints)
{
INFO("Enabling NV_device_diagnostics_checkpoints breadcrumbs.\n");
}
else
{
ERR("Breadcrumbs require support for either AMD_buffer_marker or NV_device_diagnostics_checkpoints.\n");
hr = E_FAIL;
goto err;
}
tracer->trace_contexts = vkd3d_calloc(MAX_COMMAND_LISTS, sizeof(*tracer->trace_contexts));
tracer->trace_context_index = 0;
return S_OK;
err:
vkd3d_breadcrumb_tracer_cleanup(tracer, device);
return hr;
}
void vkd3d_breadcrumb_tracer_cleanup(struct vkd3d_breadcrumb_tracer *tracer, struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
if (device->vk_info.AMD_buffer_marker)
{
VK_CALL(vkDestroyBuffer(device->vk_device, tracer->host_buffer, NULL));
vkd3d_free_device_memory(device, &tracer->host_buffer_memory);
}
vkd3d_free(tracer->trace_contexts);
pthread_mutex_destroy(&tracer->lock);
}
unsigned int vkd3d_breadcrumb_tracer_allocate_command_list(struct vkd3d_breadcrumb_tracer *tracer,
struct d3d12_command_list *list, struct d3d12_command_allocator *allocator)
{
unsigned int index = UINT32_MAX;
unsigned int iteration_count;
int rc;
if ((rc = pthread_mutex_lock(&tracer->lock)))
{
ERR("Failed to lock mutex, rc %d.\n", rc);
return UINT32_MAX;
}
/* Since this is a ring, this is extremely likely to succeed on first attempt. */
for (iteration_count = 0; iteration_count < MAX_COMMAND_LISTS; iteration_count++)
{
tracer->trace_context_index = (tracer->trace_context_index + 1) % MAX_COMMAND_LISTS;
if (!tracer->trace_contexts[tracer->trace_context_index].locked)
{
tracer->trace_contexts[tracer->trace_context_index].locked = 1;
index = tracer->trace_context_index;
break;
}
}
pthread_mutex_unlock(&tracer->lock);
if (index == UINT32_MAX)
{
ERR("Failed to allocate new index for command list.\n");
return index;
}
TRACE("Allocating breadcrumb context %u for list %p.\n", index, list);
list->breadcrumb_context_index = index;
/* Need to clear this on a fresh allocation rather than release, since we can end up releasing a command list
* before we observe the device lost. */
tracer->trace_contexts[index].command_count = 0;
tracer->trace_contexts[index].counter = 0;
if (list->device->vk_info.AMD_buffer_marker)
memset(&tracer->mapped[index], 0, sizeof(tracer->mapped[index]));
vkd3d_array_reserve((void**)&allocator->breadcrumb_context_indices, &allocator->breadcrumb_context_index_size,
allocator->breadcrumb_context_index_count + 1,
sizeof(*allocator->breadcrumb_context_indices));
allocator->breadcrumb_context_indices[allocator->breadcrumb_context_index_count++] = index;
return index;
}
/* Command allocator keeps a list of allocated breadcrumb command lists. */
void vkd3d_breadcrumb_tracer_release_command_lists(struct vkd3d_breadcrumb_tracer *tracer,
const unsigned int *indices, size_t indices_count)
{
unsigned int index;
size_t i;
int rc;
if (!indices_count)
return;
if ((rc = pthread_mutex_lock(&tracer->lock)))
{
ERR("Failed to lock mutex, rc %d.\n", rc);
return;
}
for (i = 0; i < indices_count; i++)
{
index = indices[i];
if (index != UINT32_MAX)
tracer->trace_contexts[index].locked = 0;
TRACE("Releasing breadcrumb context %u.\n", index);
}
pthread_mutex_unlock(&tracer->lock);
}
static void vkd3d_breadcrumb_tracer_report_command_list(
const struct vkd3d_breadcrumb_command_list_trace_context *context,
uint32_t begin_marker,
uint32_t end_marker)
{
const struct vkd3d_breadcrumb_command *cmd;
bool observed_begin_cmd = false;
bool observed_end_cmd = false;
unsigned int i;
if (end_marker == 0)
{
ERR(" ===== Potential crash region BEGIN (make sure RADV_DEBUG=syncshaders is used for maximum accuracy) =====\n");
observed_begin_cmd = true;
}
/* We can assume that possible culprit commands lie between the end_marker
* and top_marker. */
for (i = 0; i < context->command_count; i++)
{
cmd = &context->commands[i];
/* If there is a command which sets TOP_OF_PIPE, but we haven't observed the marker yet,
* the command processor hasn't gotten there yet (most likely ...), so that should be the
* natural end-point. */
if (!observed_end_cmd &&
cmd->type == VKD3D_BREADCRUMB_COMMAND_SET_TOP_MARKER &&
cmd->count > begin_marker)
{
observed_end_cmd = true;
ERR(" ===== Potential crash region END =====\n");
}
if (cmd->type == VKD3D_BREADCRUMB_COMMAND_AUX32)
{
ERR(" Set arg: %u (#%x)\n", cmd->word_32bit, cmd->word_32bit);
}
else if (cmd->type == VKD3D_BREADCRUMB_COMMAND_AUX64)
{
ERR(" Set arg: %"PRIu64" (#%"PRIx64")\n", cmd->word_64bit, cmd->word_64bit);
}
else if (cmd->type == VKD3D_BREADCRUMB_COMMAND_TAG)
{
ERR(" Tag: %s\n", cmd->tag);
}
else
{
ERR(" Command: %s\n", vkd3d_breadcrumb_command_type_to_str(cmd->type));
switch (cmd->type)
{
case VKD3D_BREADCRUMB_COMMAND_SET_TOP_MARKER:
case VKD3D_BREADCRUMB_COMMAND_SET_BOTTOM_MARKER:
ERR(" marker: %u\n", cmd->count);
break;
case VKD3D_BREADCRUMB_COMMAND_SET_SHADER_HASH:
ERR(" hash: %016"PRIx64", stage: %x\n", cmd->shader.hash, cmd->shader.stage);
break;
default:
break;
}
}
/* We have proved we observed this command is complete.
* Some command after this signal is at fault. */
if (!observed_begin_cmd &&
cmd->type == VKD3D_BREADCRUMB_COMMAND_SET_BOTTOM_MARKER &&
cmd->count == end_marker)
{
observed_begin_cmd = true;
ERR(" ===== Potential crash region BEGIN (make sure RADV_DEBUG=syncshaders is used for maximum accuracy) =====\n");
}
}
}
static void vkd3d_breadcrumb_tracer_report_command_list_amd(struct vkd3d_breadcrumb_tracer *tracer,
unsigned int context_index)
{
const struct vkd3d_breadcrumb_command_list_trace_context *context;
uint32_t begin_marker;
uint32_t end_marker;
context = &tracer->trace_contexts[context_index];
/* Unused, cannot be the cause. */
if (context->counter == 0)
return;
begin_marker = tracer->mapped[context_index].begin_marker;
end_marker = tracer->mapped[context_index].end_marker;
/* Never executed, cannot be the cause. */
if (begin_marker == 0 && end_marker == 0)
return;
/* Successfully retired, cannot be the cause. */
if (begin_marker == UINT32_MAX && end_marker == UINT32_MAX)
return;
/* Edge case if we re-submitted a command list,
* but it ends up crashing before we hit any BOTTOM_OF_PIPE
* marker. Normalize the inputs such that end_marker <= begin_marker. */
if (begin_marker > 0 && end_marker == UINT32_MAX)
end_marker = 0;
ERR("Found pending command list context %u in executable state, TOP_OF_PIPE marker %u, BOTTOM_OF_PIPE marker %u.\n",
context_index, begin_marker, end_marker);
vkd3d_breadcrumb_tracer_report_command_list(context, begin_marker, end_marker);
ERR("Done analyzing command list.\n");
}
static void vkd3d_breadcrumb_tracer_report_queue_nv(struct vkd3d_breadcrumb_tracer *tracer,
struct d3d12_device *device,
VkQueue vk_queue)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
uint32_t begin_marker, end_marker;
uint32_t checkpoint_context_index;
VkCheckpointDataNV *checkpoints;
uint32_t checkpoint_marker;
uint32_t checkpoint_count;
uint32_t context_index;
uint32_t i;
VK_CALL(vkGetQueueCheckpointDataNV(vk_queue, &checkpoint_count, NULL));
if (checkpoint_count == 0)
return;
checkpoints = vkd3d_calloc(checkpoint_count, sizeof(VkCheckpointDataNV));
for (i = 0; i < checkpoint_count; i++)
checkpoints[i].sType = VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV;
VK_CALL(vkGetQueueCheckpointDataNV(vk_queue, &checkpoint_count, checkpoints));
context_index = UINT32_MAX;
begin_marker = 0;
end_marker = 0;
for (i = 0; i < checkpoint_count; i++)
{
checkpoint_context_index = NV_CHECKPOINT_CONTEXT(checkpoints[i].pCheckpointMarker);
checkpoint_marker = NV_CHECKPOINT_COUNTER(checkpoints[i].pCheckpointMarker);
if (context_index != checkpoint_context_index && context_index != UINT32_MAX)
{
FIXME("Markers have different contexts. Execution is likely split across multiple command buffers?\n");
context_index = UINT32_MAX;
break;
}
context_index = checkpoint_context_index;
if (checkpoints[i].stage == VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT && checkpoint_marker > begin_marker)
{
/* We want to find the latest TOP_OF_PIPE_BIT. Then we prove that command processor got to that point. */
begin_marker = checkpoint_marker;
}
else if (checkpoints[i].stage == VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT && checkpoint_marker > end_marker)
{
/* We want to find the latest BOTTOM_OF_PIPE_BIT. Then we prove that we got that far. */
end_marker = checkpoint_marker;
}
else if (checkpoints[i].stage != VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT &&
checkpoints[i].stage != VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT)
{
FIXME("Unexpected checkpoint pipeline stage. #%x\n", checkpoints[i].stage);
context_index = UINT32_MAX;
break;
}
}
if (context_index != UINT32_MAX && begin_marker != 0 && end_marker != 0 && end_marker != UINT32_MAX)
{
ERR("Found pending command list context %u in executable state, TOP_OF_PIPE marker %u, BOTTOM_OF_PIPE marker %u.\n",
context_index, begin_marker, end_marker);
vkd3d_breadcrumb_tracer_report_command_list(&tracer->trace_contexts[context_index], begin_marker, end_marker);
ERR("Done analyzing command list.\n");
}
vkd3d_free(checkpoints);
}
void vkd3d_breadcrumb_tracer_report_device_lost(struct vkd3d_breadcrumb_tracer *tracer,
struct d3d12_device *device)
{
struct vkd3d_queue_family_info *queue_family_info;
VkQueue vk_queue;
unsigned int i;
ERR("Device lost observed, analyzing breadcrumbs ...\n");
if (device->vk_info.AMD_buffer_marker)
{
/* AMD path, buffer marker. */
for (i = 0; i < MAX_COMMAND_LISTS; i++)
vkd3d_breadcrumb_tracer_report_command_list_amd(tracer, i);
}
else if (device->vk_info.NV_device_diagnostic_checkpoints)
{
/* vkGetQueueCheckpointDataNV does not require us to synchronize access to the queue. */
queue_family_info = d3d12_device_get_vkd3d_queue_family(device, D3D12_COMMAND_LIST_TYPE_DIRECT);
for (i = 0; i < queue_family_info->queue_count; i++)
{
vk_queue = queue_family_info->queues[i]->vk_queue;
vkd3d_breadcrumb_tracer_report_queue_nv(tracer, device, vk_queue);
}
queue_family_info = d3d12_device_get_vkd3d_queue_family(device, D3D12_COMMAND_LIST_TYPE_COMPUTE);
for (i = 0; i < queue_family_info->queue_count; i++)
{
vk_queue = queue_family_info->queues[i]->vk_queue;
vkd3d_breadcrumb_tracer_report_queue_nv(tracer, device, vk_queue);
}
queue_family_info = d3d12_device_get_vkd3d_queue_family(device, D3D12_COMMAND_LIST_TYPE_COPY);
for (i = 0; i < queue_family_info->queue_count; i++)
{
vk_queue = queue_family_info->queues[i]->vk_queue;
vkd3d_breadcrumb_tracer_report_queue_nv(tracer, device, vk_queue);
}
}
ERR("Done analyzing breadcrumbs ...\n");
}
void vkd3d_breadcrumb_tracer_begin_command_list(struct d3d12_command_list *list)
{
struct vkd3d_breadcrumb_tracer *breadcrumb_tracer = &list->device->breadcrumb_tracer;
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
struct vkd3d_breadcrumb_command_list_trace_context *trace;
unsigned int context = list->breadcrumb_context_index;
struct vkd3d_breadcrumb_command cmd;
if (context == UINT32_MAX)
return;
trace = &breadcrumb_tracer->trace_contexts[context];
trace->counter++;
cmd.count = trace->counter;
cmd.type = VKD3D_BREADCRUMB_COMMAND_SET_TOP_MARKER;
vkd3d_breadcrumb_tracer_add_command(list, &cmd);
if (list->device->vk_info.AMD_buffer_marker)
{
VK_CALL(vkCmdWriteBufferMarkerAMD(list->vk_command_buffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
breadcrumb_tracer->host_buffer,
context * sizeof(struct vkd3d_breadcrumb_counter) +
offsetof(struct vkd3d_breadcrumb_counter, begin_marker),
trace->counter));
}
else if (list->device->vk_info.NV_device_diagnostic_checkpoints)
{
/* A checkpoint is implicitly a top and bottom marker. */
cmd.count = trace->counter;
cmd.type = VKD3D_BREADCRUMB_COMMAND_SET_BOTTOM_MARKER;
vkd3d_breadcrumb_tracer_add_command(list, &cmd);
VK_CALL(vkCmdSetCheckpointNV(list->vk_command_buffer, NV_ENCODE_CHECKPOINT(context, trace->counter)));
}
}
void vkd3d_breadcrumb_tracer_add_command(struct d3d12_command_list *list,
const struct vkd3d_breadcrumb_command *command)
{
struct vkd3d_breadcrumb_tracer *breadcrumb_tracer = &list->device->breadcrumb_tracer;
struct vkd3d_breadcrumb_command_list_trace_context *trace;
unsigned int context = list->breadcrumb_context_index;
if (context == UINT32_MAX)
return;
trace = &breadcrumb_tracer->trace_contexts[context];
TRACE("Adding command (%s) to context %u.\n",
vkd3d_breadcrumb_command_type_to_str(command->type), context);
vkd3d_array_reserve((void**)&trace->commands, &trace->command_size,
trace->command_count + 1, sizeof(*trace->commands));
trace->commands[trace->command_count++] = *command;
}
void vkd3d_breadcrumb_tracer_signal(struct d3d12_command_list *list)
{
struct vkd3d_breadcrumb_tracer *breadcrumb_tracer = &list->device->breadcrumb_tracer;
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
struct vkd3d_breadcrumb_command_list_trace_context *trace;
unsigned int context = list->breadcrumb_context_index;
struct vkd3d_breadcrumb_command cmd;
if (context == UINT32_MAX)
return;
trace = &breadcrumb_tracer->trace_contexts[context];
if (list->device->vk_info.AMD_buffer_marker)
{
cmd.type = VKD3D_BREADCRUMB_COMMAND_SET_BOTTOM_MARKER;
cmd.count = trace->counter;
vkd3d_breadcrumb_tracer_add_command(list, &cmd);
TRACE("Breadcrumb signal bottom-of-pipe context %u -> %u\n", context, cmd.count);
VK_CALL(vkCmdWriteBufferMarkerAMD(list->vk_command_buffer,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
breadcrumb_tracer->host_buffer,
context * sizeof(struct vkd3d_breadcrumb_counter) +
offsetof(struct vkd3d_breadcrumb_counter, end_marker),
trace->counter));
trace->counter++;
cmd.type = VKD3D_BREADCRUMB_COMMAND_SET_TOP_MARKER;
cmd.count = trace->counter;
vkd3d_breadcrumb_tracer_add_command(list, &cmd);
TRACE("Breadcrumb signal top-of-pipe context %u -> %u\n", context, cmd.count);
VK_CALL(vkCmdWriteBufferMarkerAMD(list->vk_command_buffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
breadcrumb_tracer->host_buffer,
context * sizeof(struct vkd3d_breadcrumb_counter) +
offsetof(struct vkd3d_breadcrumb_counter, begin_marker),
trace->counter));
}
else if (list->device->vk_info.NV_device_diagnostic_checkpoints)
{
trace->counter++;
cmd.type = VKD3D_BREADCRUMB_COMMAND_SET_TOP_MARKER;
cmd.count = trace->counter;
vkd3d_breadcrumb_tracer_add_command(list, &cmd);
TRACE("Breadcrumb signal top-of-pipe context %u -> %u\n", context, cmd.count);
cmd.type = VKD3D_BREADCRUMB_COMMAND_SET_BOTTOM_MARKER;
cmd.count = trace->counter;
vkd3d_breadcrumb_tracer_add_command(list, &cmd);
TRACE("Breadcrumb signal bottom-of-pipe context %u -> %u\n", context, cmd.count);
VK_CALL(vkCmdSetCheckpointNV(list->vk_command_buffer, NV_ENCODE_CHECKPOINT(context, trace->counter)));
}
}
void vkd3d_breadcrumb_tracer_end_command_list(struct d3d12_command_list *list)
{
struct vkd3d_breadcrumb_tracer *breadcrumb_tracer = &list->device->breadcrumb_tracer;
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
struct vkd3d_breadcrumb_command_list_trace_context *trace;
unsigned int context = list->breadcrumb_context_index;
struct vkd3d_breadcrumb_command cmd;
if (context == UINT32_MAX)
return;
trace = &breadcrumb_tracer->trace_contexts[context];
trace->counter = UINT32_MAX;
if (list->device->vk_info.AMD_buffer_marker)
{
VK_CALL(vkCmdWriteBufferMarkerAMD(list->vk_command_buffer,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
breadcrumb_tracer->host_buffer,
context * sizeof(struct vkd3d_breadcrumb_counter) +
offsetof(struct vkd3d_breadcrumb_counter, begin_marker),
trace->counter));
VK_CALL(vkCmdWriteBufferMarkerAMD(list->vk_command_buffer,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
breadcrumb_tracer->host_buffer,
context * sizeof(struct vkd3d_breadcrumb_counter) +
offsetof(struct vkd3d_breadcrumb_counter, end_marker),
trace->counter));
}
else if (list->device->vk_info.NV_device_diagnostic_checkpoints)
{
VK_CALL(vkCmdSetCheckpointNV(list->vk_command_buffer, NV_ENCODE_CHECKPOINT(context, trace->counter)));
}
cmd.count = trace->counter;
cmd.type = VKD3D_BREADCRUMB_COMMAND_SET_TOP_MARKER;
vkd3d_breadcrumb_tracer_add_command(list, &cmd);
cmd.type = VKD3D_BREADCRUMB_COMMAND_SET_BOTTOM_MARKER;
vkd3d_breadcrumb_tracer_add_command(list, &cmd);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -459,12 +459,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_RSSetShadingRateImage_profiled(
COMMAND_LIST_PROFILED_CALL(RSSetShadingRateImage, iface, image);
}
static void STDMETHODCALLTYPE d3d12_command_list_DispatchMesh_profiled(d3d12_command_list_iface *iface, UINT x, UINT y, UINT z)
{
COMMAND_LIST_PROFILED_CALL(DispatchMesh, iface, x, y, z);
}
static CONST_VTBL struct ID3D12GraphicsCommandList6Vtbl d3d12_command_list_vtbl_profiled =
static CONST_VTBL struct ID3D12GraphicsCommandList5Vtbl d3d12_command_list_vtbl_profiled =
{
/* IUnknown methods */
d3d12_command_list_QueryInterface,
@ -474,7 +469,7 @@ static CONST_VTBL struct ID3D12GraphicsCommandList6Vtbl d3d12_command_list_vtbl_
d3d12_command_list_GetPrivateData,
d3d12_command_list_SetPrivateData,
d3d12_command_list_SetPrivateDataInterface,
(void *)d3d12_object_SetName,
d3d12_command_list_SetName,
/* ID3D12DeviceChild methods */
d3d12_command_list_GetDevice,
/* ID3D12CommandList methods */
@ -555,8 +550,6 @@ static CONST_VTBL struct ID3D12GraphicsCommandList6Vtbl d3d12_command_list_vtbl_
/* ID3D12GraphicsCommandList5 methods */
d3d12_command_list_RSSetShadingRate_profiled,
d3d12_command_list_RSSetShadingRateImage_profiled,
/* ID3D12GraphicsCommandList6 methods */
d3d12_command_list_DispatchMesh_profiled,
};
#endif

View File

@ -1,116 +0,0 @@
/*
* * Copyright 2021 NVIDIA Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_private.h"
static inline struct d3d12_command_list *d3d12_command_list_from_ID3D12GraphicsCommandListExt(ID3D12GraphicsCommandListExt *iface)
{
return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandListExt_iface);
}
extern ULONG STDMETHODCALLTYPE d3d12_command_list_AddRef(d3d12_command_list_iface *iface);
ULONG STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_AddRef(ID3D12GraphicsCommandListExt *iface)
{
struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface);
return d3d12_command_list_AddRef(&command_list->ID3D12GraphicsCommandList_iface);
}
extern ULONG STDMETHODCALLTYPE d3d12_command_list_Release(d3d12_command_list_iface *iface);
static ULONG STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_Release(ID3D12GraphicsCommandListExt *iface)
{
struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface);
return d3d12_command_list_Release(&command_list->ID3D12GraphicsCommandList_iface);
}
extern HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(d3d12_command_list_iface *iface,
REFIID iid, void **object);
static HRESULT STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_QueryInterface(ID3D12GraphicsCommandListExt *iface,
REFIID iid, void **out)
{
struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface);
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
return d3d12_command_list_QueryInterface(&command_list->ID3D12GraphicsCommandList_iface, iid, out);
}
static HRESULT STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_GetVulkanHandle(ID3D12GraphicsCommandListExt *iface,
VkCommandBuffer *pVkCommandBuffer)
{
struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface);
TRACE("iface %p, pVkCommandBuffer %p.\n", iface, pVkCommandBuffer);
if (!pVkCommandBuffer)
return E_INVALIDARG;
*pVkCommandBuffer = command_list->vk_command_buffer;
return S_OK;
}
#define CU_LAUNCH_PARAM_BUFFER_POINTER (const void*)0x01
#define CU_LAUNCH_PARAM_BUFFER_SIZE (const void*)0x02
#define CU_LAUNCH_PARAM_END (const void*)0x00
static HRESULT STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_LaunchCubinShader(ID3D12GraphicsCommandListExt *iface, D3D12_CUBIN_DATA_HANDLE *handle, UINT32 block_x, UINT32 block_y, UINT32 block_z, const void *params, UINT32 param_size)
{
VkCuLaunchInfoNVX launchInfo = { VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX };
const struct vkd3d_vk_device_procs *vk_procs;
const void *config[] = {
CU_LAUNCH_PARAM_BUFFER_POINTER, params,
CU_LAUNCH_PARAM_BUFFER_SIZE, &param_size,
CU_LAUNCH_PARAM_END
};
struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface);
TRACE("iface %p, handle %p, block_x %u, block_y %u, block_z %u, params %p, param_size %u \n", iface, handle, block_x, block_y, block_z, params, param_size);
if (!handle || !block_x || !block_y || !block_z || !params || !param_size)
return E_INVALIDARG;
launchInfo.function = handle->vkCuFunction;
launchInfo.gridDimX = block_x;
launchInfo.gridDimY = block_y;
launchInfo.gridDimZ = block_z;
launchInfo.blockDimX = handle->blockX;
launchInfo.blockDimY = handle->blockY;
launchInfo.blockDimZ = handle->blockZ;
launchInfo.sharedMemBytes = 0;
launchInfo.paramCount = 0;
launchInfo.pParams = NULL;
launchInfo.extraCount = 1;
launchInfo.pExtras = config;
vk_procs = &command_list->device->vk_procs;
VK_CALL(vkCmdCuLaunchKernelNVX(command_list->vk_command_buffer, &launchInfo));
return S_OK;
}
CONST_VTBL struct ID3D12GraphicsCommandListExtVtbl d3d12_command_list_vkd3d_ext_vtbl =
{
/* IUnknown methods */
d3d12_command_list_vkd3d_ext_QueryInterface,
d3d12_command_list_vkd3d_ext_AddRef,
d3d12_command_list_vkd3d_ext_Release,
/* ID3D12GraphicsCommandListExt methods */
d3d12_command_list_vkd3d_ext_GetVulkanHandle,
d3d12_command_list_vkd3d_ext_LaunchCubinShader
};

View File

@ -21,7 +21,6 @@
#include "vkd3d_private.h"
#include "vkd3d_debug.h"
#include "vkd3d_common.h"
#include "vkd3d_platform.h"
#include <stdio.h>
void vkd3d_shader_debug_ring_init_spec_constant(struct d3d12_device *device,
@ -54,199 +53,22 @@ void vkd3d_shader_debug_ring_init_spec_constant(struct d3d12_device *device,
info->map_entries[3].size = sizeof(uint32_t);
}
#define READ_RING_WORD(off) ring->mapped_ring[(off) & ((ring->ring_size / sizeof(uint32_t)) - 1)]
#define READ_RING_WORD_ACQUIRE(off) \
vkd3d_atomic_uint32_load_explicit(&ring->mapped_ring[(off) & ((ring->ring_size / sizeof(uint32_t)) - 1)], \
vkd3d_memory_order_acquire)
#define DEBUG_CHANNEL_WORD_COOKIE 0xdeadca70u
#define DEBUG_CHANNEL_WORD_MASK 0xfffffff0u
static const char *vkd3d_patch_command_token_str(enum vkd3d_patch_command_token token)
{
switch (token)
{
case VKD3D_PATCH_COMMAND_TOKEN_COPY_CONST_U32: return "RootConst";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_IBO_VA_LO: return "IBO VA LO";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_IBO_VA_HI: return "IBO VA HI";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_IBO_SIZE: return "IBO Size";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_INDEX_FORMAT: return "IBO Type";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_VBO_VA_LO: return "VBO VA LO";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_VBO_VA_HI: return "VBO VA HI";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_VBO_SIZE: return "VBO Size";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_VBO_STRIDE: return "VBO Stride";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_ROOT_VA_LO: return "ROOT VA LO";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_ROOT_VA_HI: return "ROOT VA HI";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_VERTEX_COUNT: return "Vertex Count";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_INDEX_COUNT: return "Index Count";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_INSTANCE_COUNT: return "Instance Count";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_FIRST_INDEX: return "First Index";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_FIRST_VERTEX: return "First Vertex";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_FIRST_INSTANCE: return "First Instance";
case VKD3D_PATCH_COMMAND_TOKEN_COPY_VERTEX_OFFSET: return "Vertex Offset";
default: return "???";
}
}
static bool vkd3d_patch_command_token_is_hex(enum vkd3d_patch_command_token token)
{
switch (token)
{
case VKD3D_PATCH_COMMAND_TOKEN_COPY_IBO_VA_LO:
case VKD3D_PATCH_COMMAND_TOKEN_COPY_IBO_VA_HI:
case VKD3D_PATCH_COMMAND_TOKEN_COPY_VBO_VA_LO:
case VKD3D_PATCH_COMMAND_TOKEN_COPY_VBO_VA_HI:
case VKD3D_PATCH_COMMAND_TOKEN_COPY_ROOT_VA_LO:
case VKD3D_PATCH_COMMAND_TOKEN_COPY_ROOT_VA_HI:
return true;
default:
return false;
}
}
static bool vkd3d_shader_debug_ring_print_message(struct vkd3d_shader_debug_ring *ring,
uint32_t word_offset, uint32_t message_word_count)
{
uint32_t i, debug_instance, debug_thread_id[3], fmt;
char message_buffer[4096];
uint64_t shader_hash;
size_t len, avail;
if (message_word_count < 8)
{
ERR("Message word count %u is invalid.\n", message_word_count);
return false;
}
shader_hash = (uint64_t)READ_RING_WORD(word_offset + 1) | ((uint64_t)READ_RING_WORD(word_offset + 2) << 32);
debug_instance = READ_RING_WORD(word_offset + 3);
for (i = 0; i < 3; i++)
debug_thread_id[i] = READ_RING_WORD(word_offset + 4 + i);
fmt = READ_RING_WORD(word_offset + 7);
word_offset += 8;
message_word_count -= 8;
if (shader_hash == 0)
{
/* We got this from our internal debug shaders. Pretty-print.
* Make sure the log is sortable for easier debug.
* TODO: Might consider a callback system that listeners from different subsystems can listen to and print their own messages,
* but that is overengineering at this time ... */
snprintf(message_buffer, sizeof(message_buffer), "ExecuteIndirect: GlobalCommandIndex %010u, Debug tag %010u, DrawID %04u (ThreadID %04u): ",
debug_instance, debug_thread_id[0], debug_thread_id[1], debug_thread_id[2]);
if (message_word_count == 2)
{
len = strlen(message_buffer);
avail = sizeof(message_buffer) - len;
snprintf(message_buffer + len, avail, "DrawCount %u, MaxDrawCount %u",
READ_RING_WORD(word_offset + 0),
READ_RING_WORD(word_offset + 1));
}
else if (message_word_count == 4)
{
union { uint32_t u32; float f32; int32_t s32; } value;
enum vkd3d_patch_command_token token;
uint32_t dst_offset;
uint32_t src_offset;
len = strlen(message_buffer);
avail = sizeof(message_buffer) - len;
token = READ_RING_WORD(word_offset + 0);
dst_offset = READ_RING_WORD(word_offset + 1);
src_offset = READ_RING_WORD(word_offset + 2);
value.u32 = READ_RING_WORD(word_offset + 3);
if (vkd3d_patch_command_token_is_hex(token))
{
snprintf(message_buffer + len, avail, "%s <- #%08x",
vkd3d_patch_command_token_str(token), value.u32);
}
else if (token == VKD3D_PATCH_COMMAND_TOKEN_COPY_CONST_U32)
{
snprintf(message_buffer + len, avail, "%s <- {hex #%08x, s32 %d, f32 %f}",
vkd3d_patch_command_token_str(token), value.u32, value.s32, value.f32);
}
else
{
snprintf(message_buffer + len, avail, "%s <- %d",
vkd3d_patch_command_token_str(token), value.s32);
}
len = strlen(message_buffer);
avail = sizeof(message_buffer) - len;
snprintf(message_buffer + len, avail, " (dst offset %u, src offset %u)", dst_offset, src_offset);
}
}
else
{
snprintf(message_buffer, sizeof(message_buffer), "Shader: %"PRIx64": Instance %010u, ID (%u, %u, %u):",
shader_hash, debug_instance,
debug_thread_id[0], debug_thread_id[1], debug_thread_id[2]);
for (i = 0; i < message_word_count; i++)
{
union
{
float f32;
uint32_t u32;
int32_t i32;
} u;
const char *delim;
u.u32 = READ_RING_WORD(word_offset + i);
len = strlen(message_buffer);
if (len + 1 >= sizeof(message_buffer))
break;
avail = sizeof(message_buffer) - len;
delim = i == 0 ? " " : ", ";
#define VKD3D_DEBUG_CHANNEL_FMT_HEX 0u
#define VKD3D_DEBUG_CHANNEL_FMT_I32 1u
#define VKD3D_DEBUG_CHANNEL_FMT_F32 2u
switch ((fmt >> (2u * i)) & 3u)
{
case VKD3D_DEBUG_CHANNEL_FMT_HEX:
snprintf(message_buffer + len, avail, "%s#%x", delim, u.u32);
break;
case VKD3D_DEBUG_CHANNEL_FMT_I32:
snprintf(message_buffer + len, avail, "%s%d", delim, u.i32);
break;
case VKD3D_DEBUG_CHANNEL_FMT_F32:
snprintf(message_buffer + len, avail, "%s%f", delim, u.f32);
break;
default:
snprintf(message_buffer + len, avail, "%s????", delim);
break;
}
}
}
INFO("%s\n", message_buffer);
return true;
}
void *vkd3d_shader_debug_ring_thread_main(void *arg)
{
uint32_t last_counter, new_counter, count, i, cookie_word_count;
volatile const uint32_t *ring_counter; /* Atomic updated by the GPU. */
uint32_t last_counter, new_counter, count, i, j, message_word_count, debug_instance, debug_thread_id[3], fmt;
struct vkd3d_shader_debug_ring *ring;
struct d3d12_device *device = arg;
const uint32_t *ring_counter;
const uint32_t *ring_base;
char message_buffer[4096];
bool is_active = true;
uint32_t *ring_base;
uint32_t word_count;
uint64_t shader_hash;
size_t ring_mask;
ring = &device->debug_ring;
ring_mask = (ring->ring_size / sizeof(uint32_t)) - 1;
ring_counter = ring->mapped_control_block;
ring_base = ring->mapped_ring;
ring_mask = ring->ring_size - 1;
ring_counter = ring->mapped;
ring_base = ring_counter + (ring->ring_offset / sizeof(uint32_t));
last_counter = 0;
vkd3d_set_thread_name("debug-ring");
@ -254,99 +76,93 @@ void *vkd3d_shader_debug_ring_thread_main(void *arg)
while (is_active)
{
pthread_mutex_lock(&ring->ring_lock);
if (ring->active)
pthread_cond_wait(&ring->ring_cond, &ring->ring_lock);
pthread_cond_wait(&ring->ring_cond, &ring->ring_lock);
is_active = ring->active;
pthread_mutex_unlock(&ring->ring_lock);
new_counter = *ring_counter;
if (last_counter != new_counter)
{
count = (new_counter - last_counter) & ring_mask;
/* Assume that each iteration can safely use 1/4th of the buffer to avoid WAR hazards. */
if (count > (ring->ring_size / 16))
if ((new_counter - last_counter) > (ring->ring_size / 16))
{
ERR("Debug ring is probably too small (%u new words this iteration), increase size to avoid risk of dropping messages.\n",
count);
new_counter - last_counter);
}
for (i = 0; i < count; )
{
/* The debug ring shader has "release" semantics for the word count write,
* so just make sure the reads don't get reordered here. */
cookie_word_count = READ_RING_WORD_ACQUIRE(last_counter + i);
word_count = cookie_word_count & ~DEBUG_CHANNEL_WORD_MASK;
if (cookie_word_count == 0)
{
ERR("Message was allocated, but write did not complete. last_counter = %u, rewrite new_counter = %u -> %u\n",
last_counter, new_counter, last_counter + i);
/* Rewind the counter, and try again later. */
new_counter = last_counter + i;
#define READ_RING_WORD(off) ring_base[((off) + i + last_counter) & ring_mask]
message_word_count = READ_RING_WORD(0);
if (i + message_word_count > count)
break;
if (message_word_count < 8 || message_word_count > 16 + 8)
break;
shader_hash = (uint64_t)READ_RING_WORD(1) | ((uint64_t)READ_RING_WORD(2) << 32);
debug_instance = READ_RING_WORD(3);
for (j = 0; j < 3; j++)
debug_thread_id[j] = READ_RING_WORD(4 + j);
fmt = READ_RING_WORD(7);
snprintf(message_buffer, sizeof(message_buffer), "Shader: %"PRIx64": Instance %u, ID (%u, %u, %u):",
shader_hash, debug_instance,
debug_thread_id[0], debug_thread_id[1], debug_thread_id[2]);
i += 8;
message_word_count -= 8;
for (j = 0; j < message_word_count; j++)
{
union
{
float f32;
uint32_t u32;
int32_t i32;
} u;
const char *delim;
size_t len, avail;
u.u32 = READ_RING_WORD(j);
len = strlen(message_buffer);
if (len + 1 >= sizeof(message_buffer))
break;
avail = sizeof(message_buffer) - len;
delim = j == 0 ? " " : ", ";
#define VKD3D_DEBUG_CHANNEL_FMT_HEX 0u
#define VKD3D_DEBUG_CHANNEL_FMT_I32 1u
#define VKD3D_DEBUG_CHANNEL_FMT_F32 2u
switch ((fmt >> (2u * j)) & 3u)
{
case VKD3D_DEBUG_CHANNEL_FMT_HEX:
snprintf(message_buffer + len, avail, "%s#%x", delim, u.u32);
break;
case VKD3D_DEBUG_CHANNEL_FMT_I32:
snprintf(message_buffer + len, avail, "%s%d", delim, u.i32);
break;
case VKD3D_DEBUG_CHANNEL_FMT_F32:
snprintf(message_buffer + len, avail, "%s%f", delim, u.f32);
break;
default:
snprintf(message_buffer + len, avail, "%s????", delim);
break;
}
}
/* If something is written here, it must be a cookie. */
if ((cookie_word_count & DEBUG_CHANNEL_WORD_MASK) != DEBUG_CHANNEL_WORD_COOKIE)
{
ERR("Invalid message work cookie detected, 0x%x.\n", cookie_word_count);
break;
}
ERR("%s\n", message_buffer);
if (i + word_count > count)
{
ERR("Message word count %u is out of bounds (i = %u, count = %u).\n",
word_count, i, count);
break;
}
if (!vkd3d_shader_debug_ring_print_message(ring, last_counter + i, word_count))
break;
i += word_count;
#undef READ_RING_WORD
i += message_word_count;
}
}
/* Make sure to clear out any messages we read so that when the ring gets around to
* this point again, we can detect unwritten memory.
* This relies on having a ring that is large enough, but in practice, if we just make the ring
* large enough, there is nothing to worry about. */
while (last_counter != new_counter)
{
ring_base[last_counter & ring_mask] = 0;
last_counter++;
}
}
if (ring->device_lost)
{
INFO("Device lost detected, attempting to fish for clues.\n");
new_counter = *ring_counter;
if (last_counter != new_counter)
{
count = (new_counter - last_counter) & ring_mask;
for (i = 0; i < count; )
{
cookie_word_count = READ_RING_WORD_ACQUIRE(last_counter + i);
word_count = cookie_word_count & ~DEBUG_CHANNEL_WORD_MASK;
/* This is considered a message if it has the marker and a word count that is in-range. */
if ((cookie_word_count & DEBUG_CHANNEL_WORD_MASK) == DEBUG_CHANNEL_WORD_COOKIE &&
i + word_count <= count &&
vkd3d_shader_debug_ring_print_message(ring, last_counter + i, word_count))
{
i += word_count;
}
else
{
/* Keep going. */
i++;
}
}
}
INFO("Done fishing for clues ...\n");
last_counter = new_counter;
}
return NULL;
@ -357,21 +173,20 @@ HRESULT vkd3d_shader_debug_ring_init(struct vkd3d_shader_debug_ring *ring,
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
D3D12_HEAP_PROPERTIES heap_properties;
D3D12_RESOURCE_DESC1 resource_desc;
VkMemoryPropertyFlags memory_props;
char env[VKD3D_PATH_MAX];
D3D12_RESOURCE_DESC resource_desc;
const char *env;
memset(ring, 0, sizeof(*ring));
if (!vkd3d_get_env_var("VKD3D_SHADER_DEBUG_RING_SIZE_LOG2", env, sizeof(env)))
if (!(env = getenv("VKD3D_SHADER_DEBUG_RING_SIZE_LOG2")))
return S_OK;
ring->active = true;
ring->ring_size = (size_t)1 << strtoul(env, NULL, 0);
ring->control_block_size = 4096;
// Reserve 4k to be used as a control block of some sort.
ring->ring_offset = 4096;
INFO("Enabling shader debug ring of size: %zu.\n", ring->ring_size);
WARN("Enabling shader debug ring of size: %zu.\n", ring->ring_size);
if (!device->device_info.buffer_device_address_features.bufferDeviceAddress)
{
@ -385,7 +200,7 @@ HRESULT vkd3d_shader_debug_ring_init(struct vkd3d_shader_debug_ring *ring,
heap_properties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
memset(&resource_desc, 0, sizeof(resource_desc));
resource_desc.Width = ring->ring_size;
resource_desc.Width = ring->ring_offset + ring->ring_size;
resource_desc.Height = 1;
resource_desc.DepthOrArraySize = 1;
resource_desc.MipLevels = 1;
@ -396,71 +211,32 @@ HRESULT vkd3d_shader_debug_ring_init(struct vkd3d_shader_debug_ring *ring,
resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
if (FAILED(vkd3d_create_buffer(device, &heap_properties, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS,
&resource_desc, &ring->host_buffer)))
&resource_desc, &ring->host_buffer)))
goto err_free_buffers;
memory_props = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
/* If we're doing breadcrumb debugging, we also need to be able to read debug ring messages
* from a crash, so we cannot rely on being able to copy the device payload back to host.
* Use PCI-e BAR + UNCACHED + DEVICE_COHERENT if we must. */
if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_BREADCRUMBS)
{
INFO("Using debug ring with breadcrumbs, opting in to device uncached payload buffer.\n");
/* We use coherent in the debug_channel.h header, but not necessarily guaranteed to be coherent with
* host reads, so make extra sure. */
if (device->device_info.device_coherent_memory_features_amd.deviceCoherentMemory)
{
memory_props |= VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD | VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD;
INFO("Enabling uncached device memory for debug ring.\n");
}
}
if (FAILED(vkd3d_allocate_buffer_memory(device, ring->host_buffer,
memory_props, &ring->host_buffer_memory)))
if (FAILED(vkd3d_allocate_buffer_memory(device, ring->host_buffer, NULL,
&heap_properties, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, &ring->host_buffer_memory, NULL, NULL)))
goto err_free_buffers;
resource_desc.Width = ring->control_block_size;
ring->ring_device_address = vkd3d_get_buffer_device_address(device, ring->host_buffer) + ring->ring_offset;
resource_desc.Width = ring->ring_offset;
memset(&heap_properties, 0, sizeof(heap_properties));
heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
if (FAILED(vkd3d_create_buffer(device, &heap_properties, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS,
&resource_desc, &ring->device_atomic_buffer)))
&resource_desc, &ring->device_atomic_buffer)))
goto err_free_buffers;
memory_props = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_BREADCRUMBS)
{
/* Expect crashes since we won't have time to flush caches.
* We use coherent in the debug_channel.h header, but not necessarily guaranteed to be coherent with
* host reads, so make extra sure. */
if (device->device_info.device_coherent_memory_features_amd.deviceCoherentMemory)
memory_props |= VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD | VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD;
}
if (FAILED(vkd3d_allocate_buffer_memory(device, ring->device_atomic_buffer,
memory_props, &ring->device_atomic_buffer_memory)))
if (FAILED(vkd3d_allocate_buffer_memory(device, ring->device_atomic_buffer, NULL,
&heap_properties, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, &ring->device_atomic_buffer_memory, NULL, NULL)))
goto err_free_buffers;
if (VK_CALL(vkMapMemory(device->vk_device, ring->host_buffer_memory.vk_memory,
0, VK_WHOLE_SIZE, 0, (void**)&ring->mapped_ring)) != VK_SUCCESS)
if (VK_CALL(vkMapMemory(device->vk_device, ring->host_buffer_memory, 0, VK_WHOLE_SIZE, 0, &ring->mapped)) != VK_SUCCESS)
goto err_free_buffers;
if (VK_CALL(vkMapMemory(device->vk_device, ring->device_atomic_buffer_memory.vk_memory,
0, VK_WHOLE_SIZE, 0, (void**)&ring->mapped_control_block)) != VK_SUCCESS)
goto err_free_buffers;
ring->ring_device_address = vkd3d_get_buffer_device_address(device, ring->host_buffer);
ring->atomic_device_address = vkd3d_get_buffer_device_address(device, ring->device_atomic_buffer);
memset(ring->mapped_control_block, 0, ring->control_block_size);
memset(ring->mapped_ring, 0, ring->ring_size);
if (pthread_mutex_init(&ring->ring_lock, NULL) != 0)
goto err_free_buffers;
if (pthread_cond_init(&ring->ring_cond, NULL) != 0)
@ -481,8 +257,8 @@ err_destroy_cond:
err_free_buffers:
VK_CALL(vkDestroyBuffer(device->vk_device, ring->host_buffer, NULL));
VK_CALL(vkDestroyBuffer(device->vk_device, ring->device_atomic_buffer, NULL));
vkd3d_free_device_memory(device, &ring->host_buffer_memory);
vkd3d_free_device_memory(device, &ring->device_atomic_buffer_memory);
VK_CALL(vkFreeMemory(device->vk_device, ring->host_buffer_memory, NULL));
VK_CALL(vkFreeMemory(device->vk_device, ring->device_atomic_buffer_memory, NULL));
memset(ring, 0, sizeof(*ring));
return E_OUTOFMEMORY;
}
@ -504,28 +280,42 @@ void vkd3d_shader_debug_ring_cleanup(struct vkd3d_shader_debug_ring *ring,
VK_CALL(vkDestroyBuffer(device->vk_device, ring->host_buffer, NULL));
VK_CALL(vkDestroyBuffer(device->vk_device, ring->device_atomic_buffer, NULL));
vkd3d_free_device_memory(device, &ring->host_buffer_memory);
vkd3d_free_device_memory(device, &ring->device_atomic_buffer_memory);
VK_CALL(vkFreeMemory(device->vk_device, ring->host_buffer_memory, NULL));
VK_CALL(vkFreeMemory(device->vk_device, ring->device_atomic_buffer_memory, NULL));
}
static pthread_mutex_t debug_ring_teardown_lock = PTHREAD_MUTEX_INITIALIZER;
void vkd3d_shader_debug_ring_kick(struct vkd3d_shader_debug_ring *ring, struct d3d12_device *device, bool device_lost)
void vkd3d_shader_debug_ring_end_command_buffer(struct d3d12_command_list *list)
{
if (device_lost)
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
VkBufferCopy buffer_copy;
VkMemoryBarrier barrier;
if (list->device->debug_ring.active &&
list->has_replaced_shaders &&
(list->type == D3D12_COMMAND_LIST_TYPE_DIRECT || list->type == D3D12_COMMAND_LIST_TYPE_COMPUTE))
{
/* Need a global lock here since multiple threads can observe device lost at the same time. */
pthread_mutex_lock(&debug_ring_teardown_lock);
{
ring->device_lost = true;
/* We're going to die or hang after this most likely, so make sure we get to see all messages the
* GPU had to write. Just cleanup now. */
vkd3d_shader_debug_ring_cleanup(ring, device);
}
pthread_mutex_unlock(&debug_ring_teardown_lock);
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.pNext = NULL;
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
1, &barrier, 0, NULL, 0, NULL));
buffer_copy.size = list->device->debug_ring.ring_offset;
buffer_copy.dstOffset = 0;
buffer_copy.srcOffset = 0;
VK_CALL(vkCmdCopyBuffer(list->vk_command_buffer,
list->device->debug_ring.device_atomic_buffer,
list->device->debug_ring.host_buffer,
1, &buffer_copy));
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0,
1, &barrier, 0, NULL, 0, NULL));
}
else
{
pthread_cond_signal(&ring->ring_cond);
}
}
}

View File

@ -1,530 +0,0 @@
/*
* Copyright 2020 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_descriptor_debug.h"
#include "vkd3d_threads.h"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
static pthread_once_t debug_once = PTHREAD_ONCE_INIT;
static pthread_mutex_t debug_lock = PTHREAD_MUTEX_INITIALIZER;
static bool descriptor_debug_active_qa_checks;
static bool descriptor_debug_active_log;
static FILE *descriptor_debug_file;
struct vkd3d_descriptor_qa_global_info
{
struct vkd3d_descriptor_qa_global_buffer_data *data;
VkDescriptorBufferInfo descriptor;
VkBuffer vk_buffer;
struct vkd3d_device_memory_allocation device_allocation;
unsigned int num_cookies;
pthread_t ring_thread;
pthread_mutex_t ring_lock;
pthread_cond_t ring_cond;
bool active;
};
static const char *debug_descriptor_type(vkd3d_descriptor_qa_flags type_flags)
{
bool has_raw_va = !!(type_flags & VKD3D_DESCRIPTOR_QA_TYPE_RAW_VA_BIT);
switch (type_flags & ~VKD3D_DESCRIPTOR_QA_TYPE_RAW_VA_BIT)
{
case VKD3D_DESCRIPTOR_QA_TYPE_SAMPLER_BIT: return "SAMPLER";
case VKD3D_DESCRIPTOR_QA_TYPE_SAMPLED_IMAGE_BIT: return "SAMPLED_IMAGE";
case VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_IMAGE_BIT: return "STORAGE_IMAGE";
case VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_BUFFER_BIT: return "UNIFORM_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT: return "STORAGE_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_TEXEL_BUFFER_BIT: return "UNIFORM_TEXEL_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_TEXEL_BUFFER_BIT: return "STORAGE_TEXEL_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_TEXEL_BUFFER_BIT | VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT:
return has_raw_va ? "STORAGE_TEXEL_BUFFER / STORAGE_BUFFER (w/ counter)" : "STORAGE_TEXEL_BUFFER / STORAGE_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_UNIFORM_TEXEL_BUFFER_BIT | VKD3D_DESCRIPTOR_QA_TYPE_STORAGE_BUFFER_BIT:
return has_raw_va ? "UNIFORM_TEXEL_BUFFER / STORAGE_BUFFER (w/ counter)" : "UNIFORM_TEXEL_BUFFER / STORAGE_BUFFER";
case VKD3D_DESCRIPTOR_QA_TYPE_RT_ACCELERATION_STRUCTURE_BIT:
return "RTAS";
case 0:
return "NONE";
default: return "?";
}
}
static void vkd3d_descriptor_debug_init_once(void)
{
char env[VKD3D_PATH_MAX];
vkd3d_get_env_var("VKD3D_DESCRIPTOR_QA_LOG", env, sizeof(env));
if (strlen(env) > 0)
{
INFO("Enabling VKD3D_DESCRIPTOR_QA_LOG\n");
descriptor_debug_file = fopen(env, "w");
if (!descriptor_debug_file)
ERR("Failed to open file: %s.\n", env);
else
descriptor_debug_active_log = true;
}
if (vkd3d_config_flags & VKD3D_CONFIG_FLAG_DESCRIPTOR_QA_CHECKS)
{
INFO("Enabling descriptor QA checks!\n");
descriptor_debug_active_qa_checks = true;
}
}
void vkd3d_descriptor_debug_init(void)
{
pthread_once(&debug_once, vkd3d_descriptor_debug_init_once);
}
bool vkd3d_descriptor_debug_active_log(void)
{
return descriptor_debug_active_log;
}
bool vkd3d_descriptor_debug_active_qa_checks(void)
{
return descriptor_debug_active_qa_checks;
}
VkDeviceSize vkd3d_descriptor_debug_heap_info_size(unsigned int num_descriptors)
{
return offsetof(struct vkd3d_descriptor_qa_heap_buffer_data, desc) + num_descriptors *
sizeof(struct vkd3d_descriptor_qa_cookie_descriptor);
}
static void vkd3d_descriptor_debug_set_live_status_bit(
struct vkd3d_descriptor_qa_global_info *global_info, uint64_t cookie)
{
if (!global_info || !global_info->active || !global_info->data)
return;
if (cookie < global_info->num_cookies)
{
vkd3d_atomic_uint32_or(&global_info->data->live_status_table[cookie / 32],
1u << (cookie & 31), vkd3d_memory_order_relaxed);
}
else
INFO("Cookie index %"PRIu64" is out of range, cannot be tracked.\n", cookie);
}
static void vkd3d_descriptor_debug_unset_live_status_bit(
struct vkd3d_descriptor_qa_global_info *global_info, uint64_t cookie)
{
if (!global_info || !global_info->active || !global_info->data)
return;
if (cookie < global_info->num_cookies)
{
vkd3d_atomic_uint32_and(&global_info->data->live_status_table[cookie / 32],
~(1u << (cookie & 31)), vkd3d_memory_order_relaxed);
}
}
static void vkd3d_descriptor_debug_qa_check_report_fault(
struct vkd3d_descriptor_qa_global_info *global_info);
static void *vkd3d_descriptor_debug_qa_check_entry(void *userdata)
{
struct vkd3d_descriptor_qa_global_info *global_info = userdata;
bool active = true;
while (active)
{
/* Don't spin endlessly, this thread is kicked after a successful fence wait. */
pthread_mutex_lock(&global_info->ring_lock);
if (global_info->active)
pthread_cond_wait(&global_info->ring_cond, &global_info->ring_lock);
active = global_info->active;
pthread_mutex_unlock(&global_info->ring_lock);
if (global_info->data->fault_type != 0)
{
vkd3d_descriptor_debug_qa_check_report_fault(global_info);
ERR("Num failed checks: %u\n", global_info->data->fault_atomic);
/* Reset the latch so we can get more reports. */
vkd3d_atomic_uint32_store_explicit(&global_info->data->fault_type, 0, vkd3d_memory_order_relaxed);
vkd3d_atomic_uint32_store_explicit(&global_info->data->fault_atomic, 0, vkd3d_memory_order_release);
}
}
return NULL;
}
void vkd3d_descriptor_debug_kick_qa_check(struct vkd3d_descriptor_qa_global_info *global_info)
{
if (global_info && global_info->active)
pthread_cond_signal(&global_info->ring_cond);
}
const VkDescriptorBufferInfo *vkd3d_descriptor_debug_get_global_info_descriptor(
struct vkd3d_descriptor_qa_global_info *global_info)
{
if (global_info)
return &global_info->descriptor;
else
return NULL;
}
HRESULT vkd3d_descriptor_debug_alloc_global_info(
struct vkd3d_descriptor_qa_global_info **out_global_info, unsigned int num_cookies,
struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct vkd3d_descriptor_qa_global_info *global_info;
D3D12_RESOURCE_DESC1 buffer_desc;
D3D12_HEAP_PROPERTIES heap_info;
D3D12_HEAP_FLAGS heap_flags;
VkResult vr;
HRESULT hr;
global_info = vkd3d_calloc(1, sizeof(*global_info));
if (!global_info)
return E_OUTOFMEMORY;
memset(&buffer_desc, 0, sizeof(buffer_desc));
buffer_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
buffer_desc.Width = sizeof(uint32_t) * ((num_cookies + 31) / 32) +
offsetof(struct vkd3d_descriptor_qa_global_buffer_data, live_status_table);
buffer_desc.Height = 1;
buffer_desc.DepthOrArraySize = 1;
buffer_desc.MipLevels = 1;
buffer_desc.SampleDesc.Count = 1;
buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
buffer_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
/* host-visible device memory */
memset(&heap_info, 0, sizeof(heap_info));
heap_info.Type = D3D12_HEAP_TYPE_UPLOAD;
heap_flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
if (FAILED(hr = vkd3d_create_buffer(device, &heap_info, heap_flags, &buffer_desc, &global_info->vk_buffer)))
{
vkd3d_descriptor_debug_free_global_info(global_info, device);
return hr;
}
if (FAILED(hr = vkd3d_allocate_buffer_memory(device, global_info->vk_buffer,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&global_info->device_allocation)))
{
vkd3d_descriptor_debug_free_global_info(global_info, device);
return hr;
}
if ((vr = VK_CALL(vkMapMemory(device->vk_device, global_info->device_allocation.vk_memory,
0, VK_WHOLE_SIZE, 0, (void**)&global_info->data))))
{
ERR("Failed to map buffer, vr %d.\n", vr);
vkd3d_descriptor_debug_free_global_info(global_info, device);
return hresult_from_vk_result(vr);
}
memset(global_info->data, 0, buffer_desc.Width);
/* The NULL descriptor has cookie 0, and is always considered live. */
global_info->data->live_status_table[0] = 1u << 0;
global_info->descriptor.buffer = global_info->vk_buffer;
global_info->descriptor.offset = 0;
global_info->descriptor.range = buffer_desc.Width;
global_info->num_cookies = num_cookies;
pthread_mutex_init(&global_info->ring_lock, NULL);
pthread_cond_init(&global_info->ring_cond, NULL);
global_info->active = true;
if (pthread_create(&global_info->ring_thread, NULL, vkd3d_descriptor_debug_qa_check_entry, global_info) != 0)
{
vkd3d_descriptor_debug_free_global_info(global_info, device);
return E_OUTOFMEMORY;
}
*out_global_info = global_info;
return S_OK;
}
void vkd3d_descriptor_debug_free_global_info(
struct vkd3d_descriptor_qa_global_info *global_info,
struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
if (!global_info)
return;
if (global_info->active)
{
pthread_mutex_lock(&global_info->ring_lock);
global_info->active = false;
pthread_cond_signal(&global_info->ring_cond);
pthread_mutex_unlock(&global_info->ring_lock);
pthread_join(global_info->ring_thread, NULL);
pthread_mutex_destroy(&global_info->ring_lock);
pthread_cond_destroy(&global_info->ring_cond);
}
vkd3d_free_device_memory(device, &global_info->device_allocation);
VK_CALL(vkDestroyBuffer(device->vk_device, global_info->vk_buffer, NULL));
vkd3d_free(global_info);
}
#define DECL_BUFFER() \
char buffer[4096]; \
char *ptr; \
ptr = buffer; \
*ptr = '\0'
#define FLUSH_BUFFER() do { \
pthread_mutex_lock(&debug_lock); \
fprintf(descriptor_debug_file, "%s\n", buffer); \
pthread_mutex_unlock(&debug_lock); \
fflush(descriptor_debug_file); \
} while (0)
#define APPEND_SNPRINTF(...) do { ptr += strlen(ptr); snprintf(ptr, (buffer + ARRAY_SIZE(buffer)) - ptr, __VA_ARGS__); } while(0)
static void vkd3d_descriptor_debug_qa_check_report_fault(
struct vkd3d_descriptor_qa_global_info *global_info)
{
DECL_BUFFER();
if (global_info->data->fault_type & VKD3D_DESCRIPTOR_FAULT_TYPE_HEAP_OF_OF_RANGE)
APPEND_SNPRINTF("Fault type: HEAP_OUT_OF_RANGE\n");
if (global_info->data->fault_type & VKD3D_DESCRIPTOR_FAULT_TYPE_MISMATCH_DESCRIPTOR_TYPE)
APPEND_SNPRINTF("Fault type: MISMATCH_DESCRIPTOR_TYPE\n");
if (global_info->data->fault_type & VKD3D_DESCRIPTOR_FAULT_TYPE_DESTROYED_RESOURCE)
APPEND_SNPRINTF("Fault type: DESTROYED_RESOURCE\n");
APPEND_SNPRINTF("CBV_SRV_UAV heap cookie: %u\n", global_info->data->failed_heap);
APPEND_SNPRINTF("Shader hash and instruction: %"PRIx64" (%u)\n",
global_info->data->failed_hash, global_info->data->failed_instruction);
APPEND_SNPRINTF("Accessed resource/view cookie: %u\n", global_info->data->failed_cookie);
APPEND_SNPRINTF("Shader desired descriptor type: %u (%s)\n",
global_info->data->failed_descriptor_type_mask,
debug_descriptor_type(global_info->data->failed_descriptor_type_mask));
APPEND_SNPRINTF("Found descriptor type in heap: %u (%s)\n",
global_info->data->actual_descriptor_type_mask,
debug_descriptor_type(global_info->data->actual_descriptor_type_mask));
APPEND_SNPRINTF("Failed heap index: %u\n", global_info->data->failed_offset);
ERR("\n============\n%s==========\n", buffer);
if (!vkd3d_descriptor_debug_active_log())
return;
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_register_heap(
struct vkd3d_descriptor_qa_heap_buffer_data *heap, uint64_t cookie,
const D3D12_DESCRIPTOR_HEAP_DESC *desc)
{
DECL_BUFFER();
if (heap)
{
heap->num_descriptors = desc->NumDescriptors;
heap->heap_index = cookie <= UINT32_MAX ? (uint32_t)cookie : 0u;
memset(heap->desc, 0, desc->NumDescriptors * sizeof(*heap->desc));
}
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("REGISTER HEAP %"PRIu64" || COUNT = %u", cookie, desc->NumDescriptors);
if (desc->Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
APPEND_SNPRINTF(" || SHADER");
switch (desc->Type)
{
case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
APPEND_SNPRINTF(" || CBV_SRV_UAV");
break;
case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
APPEND_SNPRINTF(" || SAMPLER");
break;
case D3D12_DESCRIPTOR_HEAP_TYPE_RTV:
APPEND_SNPRINTF(" || RTV");
break;
case D3D12_DESCRIPTOR_HEAP_TYPE_DSV:
APPEND_SNPRINTF(" || DSV");
break;
default:
APPEND_SNPRINTF(" || ?");
break;
}
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_unregister_heap(uint64_t cookie)
{
DECL_BUFFER();
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("DESTROY HEAP %"PRIu64, cookie);
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_register_resource_cookie(struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie, const D3D12_RESOURCE_DESC1 *desc)
{
const char *fmt;
DECL_BUFFER();
vkd3d_descriptor_debug_set_live_status_bit(global_info, cookie);
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("RESOURCE CREATE #%"PRIu64" || ", cookie);
fmt = debug_dxgi_format(desc->Format);
switch (desc->Dimension)
{
case D3D12_RESOURCE_DIMENSION_BUFFER:
APPEND_SNPRINTF("Buffer");
APPEND_SNPRINTF(" || Size = 0x%"PRIx64" bytes", desc->Width);
break;
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
APPEND_SNPRINTF("Tex1D");
APPEND_SNPRINTF(" || Format = %s || Levels = %u || Layers = %u || Width = %"PRIu64,
fmt, desc->MipLevels, desc->DepthOrArraySize, desc->Width);
break;
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
APPEND_SNPRINTF("Tex2D");
APPEND_SNPRINTF(" || Format = %s || Levels = %u || Layers = %u || Width = %"PRIu64" || Height = %u",
fmt, desc->MipLevels, desc->DepthOrArraySize, desc->Width, desc->Height);
break;
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
APPEND_SNPRINTF("Tex3D");
APPEND_SNPRINTF(" || Format = %s || Levels = %u || Width = %"PRIu64" || Height = %u || Depth = %u",
fmt, desc->MipLevels, desc->Width, desc->Height, desc->DepthOrArraySize);
break;
default:
APPEND_SNPRINTF("Unknown dimension");
break;
}
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
APPEND_SNPRINTF(" || UAV");
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
APPEND_SNPRINTF(" || RTV");
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
APPEND_SNPRINTF(" || DSV");
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_register_allocation_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie, const struct vkd3d_allocate_memory_info *info)
{
D3D12_RESOURCE_DESC1 desc;
memset(&desc, 0, sizeof(desc));
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Width = info->memory_requirements.size;
vkd3d_descriptor_debug_register_resource_cookie(global_info, cookie, &desc);
}
void vkd3d_descriptor_debug_register_view_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie, uint64_t resource_cookie)
{
DECL_BUFFER();
vkd3d_descriptor_debug_set_live_status_bit(global_info, cookie);
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("VIEW CREATE #%"PRIu64" <- RESOURCE #%"PRIu64, cookie, resource_cookie);
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_unregister_cookie(
struct vkd3d_descriptor_qa_global_info *global_info,
uint64_t cookie)
{
DECL_BUFFER();
/* Don't unset the null descriptor by mistake. */
if (cookie != 0)
vkd3d_descriptor_debug_unset_live_status_bit(global_info, cookie);
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("COOKIE DESTROY #%"PRIu64, cookie);
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_write_descriptor(struct vkd3d_descriptor_qa_heap_buffer_data *heap, uint64_t heap_cookie,
uint32_t offset, vkd3d_descriptor_qa_flags type_flags, uint64_t cookie)
{
DECL_BUFFER();
if (heap && offset < heap->num_descriptors)
{
/* Should never overflow here except if game is literally spamming allocations every frame and we
* wait around for hours/days.
* This case will trigger warnings either way. */
heap->desc[offset].cookie = cookie <= UINT32_MAX ? (uint32_t)cookie : 0u;
heap->desc[offset].descriptor_type = type_flags;
}
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("WRITE HEAP %"PRIu64" || OFFSET = %u || TYPE = %s || COOKIE = #%"PRIu64,
heap_cookie, offset, debug_descriptor_type(type_flags), cookie);
FLUSH_BUFFER();
}
void vkd3d_descriptor_debug_copy_descriptor(
struct vkd3d_descriptor_qa_heap_buffer_data *dst_heap, uint64_t dst_heap_cookie, uint32_t dst_offset,
struct vkd3d_descriptor_qa_heap_buffer_data *src_heap, uint64_t src_heap_cookie, uint32_t src_offset,
uint64_t cookie)
{
DECL_BUFFER();
if (dst_heap && src_heap && dst_offset < dst_heap->num_descriptors && src_offset < src_heap->num_descriptors)
dst_heap->desc[dst_offset] = src_heap->desc[src_offset];
if (!vkd3d_descriptor_debug_active_log())
return;
APPEND_SNPRINTF("COPY DST HEAP %"PRIu64" || DST OFFSET = %u || COOKIE = #%"PRIu64" || SRC HEAP %"PRIu64" || SRC OFFSET = %u",
dst_heap_cookie, dst_offset, cookie, src_heap_cookie, src_offset);
FLUSH_BUFFER();
}

File diff suppressed because it is too large Load Diff

View File

@ -215,31 +215,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineState_profiled(d3d12
DEVICE_PROFILED_CALL_HRESULT(CreatePipelineState, iface, desc, riid, pipeline_state);
}
static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource2_profiled(d3d12_device_iface *iface,
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, const D3D12_RESOURCE_DESC1 *desc,
D3D12_RESOURCE_STATES initial_state, const D3D12_CLEAR_VALUE *optimized_clear_value,
ID3D12ProtectedResourceSession *protected_session, REFIID iid, void **resource)
{
DEVICE_PROFILED_CALL_HRESULT(CreateCommittedResource2, iface, heap_properties, heap_flags,
desc, initial_state, optimized_clear_value, protected_session, iid, resource);
}
static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource1_profiled(d3d12_device_iface *iface,
ID3D12Heap *heap, UINT64 heap_offset, const D3D12_RESOURCE_DESC1 *desc,
D3D12_RESOURCE_STATES initial_state, const D3D12_CLEAR_VALUE *optimized_clear_value,
REFIID iid, void **resource)
{
DEVICE_PROFILED_CALL_HRESULT(CreatePlacedResource1, iface, heap, heap_offset,
desc, initial_state, optimized_clear_value, iid, resource);
}
static void STDMETHODCALLTYPE d3d12_device_CreateSamplerFeedbackUnorderedAccessView_profiled(d3d12_device_iface *iface,
ID3D12Resource *target_resource, ID3D12Resource *feedback_resource, D3D12_CPU_DESCRIPTOR_HANDLE descriptor)
{
DEVICE_PROFILED_CALL(CreateSamplerFeedbackUnorderedAccessView, iface, target_resource, feedback_resource, descriptor);
}
CONST_VTBL struct ID3D12Device9Vtbl d3d12_device_vtbl_profiled =
static CONST_VTBL struct ID3D12Device6Vtbl d3d12_device_vtbl_profiled =
{
/* IUnknown methods */
d3d12_device_QueryInterface,
@ -249,7 +225,7 @@ CONST_VTBL struct ID3D12Device9Vtbl d3d12_device_vtbl_profiled =
d3d12_device_GetPrivateData,
d3d12_device_SetPrivateData,
d3d12_device_SetPrivateDataInterface,
(void *)d3d12_object_SetName,
d3d12_device_SetName,
/* ID3D12Device methods */
d3d12_device_GetNodeCount,
d3d12_device_CreateCommandQueue,
@ -316,19 +292,6 @@ CONST_VTBL struct ID3D12Device9Vtbl d3d12_device_vtbl_profiled =
d3d12_device_CheckDriverMatchingIdentifier,
/* ID3D12Device6 methods */
d3d12_device_SetBackgroundProcessingMode,
/* ID3D12Device7 methods */
d3d12_device_AddToStateObject,
d3d12_device_CreateProtectedResourceSession1,
/* ID3D12Device8 methods */
d3d12_device_GetResourceAllocationInfo2,
d3d12_device_CreateCommittedResource2_profiled,
d3d12_device_CreatePlacedResource1_profiled,
d3d12_device_CreateSamplerFeedbackUnorderedAccessView_profiled,
d3d12_device_GetCopyableFootprints1,
/* ID3D12Device9 methods */
d3d12_device_CreateShaderCacheSession,
d3d12_device_ShaderCacheControl,
d3d12_device_CreateCommandQueue1,
};
#endif

View File

@ -1,234 +0,0 @@
/*
* * Copyright 2021 NVIDIA Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_private.h"
static inline struct d3d12_device *d3d12_device_from_ID3D12DeviceExt(ID3D12DeviceExt *iface)
{
return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12DeviceExt_iface);
}
ULONG STDMETHODCALLTYPE d3d12_device_vkd3d_ext_AddRef(ID3D12DeviceExt *iface)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(iface);
return d3d12_device_add_ref(device);
}
static ULONG STDMETHODCALLTYPE d3d12_device_vkd3d_ext_Release(ID3D12DeviceExt *iface)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(iface);
return d3d12_device_release(device);
}
extern HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface,
REFIID riid, void **object);
static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_QueryInterface(ID3D12DeviceExt *iface,
REFIID iid, void **out)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(iface);
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
return d3d12_device_QueryInterface(&device->ID3D12Device_iface, iid, out);
}
static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_GetVulkanHandles(ID3D12DeviceExt *iface, VkInstance *vk_instance, VkPhysicalDevice *vk_physical_device, VkDevice *vk_device)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(iface);
TRACE("iface %p, vk_instance %p, vk_physical_device %u, vk_device %p \n", iface, vk_instance, vk_physical_device, vk_device);
if (!vk_device || !vk_instance || !vk_physical_device)
return E_INVALIDARG;
*vk_instance = device->vkd3d_instance->vk_instance;
*vk_physical_device = device->vk_physical_device;
*vk_device = device->vk_device;
return S_OK;
}
static BOOL STDMETHODCALLTYPE d3d12_device_vkd3d_ext_GetExtensionSupport(ID3D12DeviceExt *iface, D3D12_VK_EXTENSION extension)
{
const struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(iface);
bool ret_val = false;
TRACE("iface %p, extension %u \n", iface, extension);
switch (extension)
{
case D3D12_VK_NVX_BINARY_IMPORT:
ret_val = device->vk_info.NVX_binary_import;
break;
case D3D12_VK_NVX_IMAGE_VIEW_HANDLE:
ret_val = device->vk_info.NVX_image_view_handle;
break;
default:
WARN("Invalid extension %x\n", extension);
}
return ret_val;
}
static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_CreateCubinComputeShaderWithName(ID3D12DeviceExt *iface, const void *cubin_data,
UINT32 cubin_size, UINT32 block_x, UINT32 block_y, UINT32 block_z, const char *shader_name, D3D12_CUBIN_DATA_HANDLE **out_handle)
{
VkCuFunctionCreateInfoNVX functionCreateInfo = { VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX };
VkCuModuleCreateInfoNVX moduleCreateInfo = { VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX };
const struct vkd3d_vk_device_procs *vk_procs;
D3D12_CUBIN_DATA_HANDLE *handle;
struct d3d12_device *device;
VkDevice vk_device;
VkResult vr;
TRACE("iface %p, cubin_data %p, cubin_size %u, shader_name %s \n", iface, cubin_data, cubin_size, shader_name);
if (!cubin_data || !cubin_size || !shader_name)
return E_INVALIDARG;
device = d3d12_device_from_ID3D12DeviceExt(iface);
vk_device = device->vk_device;
handle = vkd3d_calloc(1, sizeof(D3D12_CUBIN_DATA_HANDLE));
handle->blockX = block_x;
handle->blockY = block_y;
handle->blockZ = block_z;
moduleCreateInfo.pData = cubin_data;
moduleCreateInfo.dataSize = cubin_size;
vk_procs = &device->vk_procs;
if ((vr = VK_CALL(vkCreateCuModuleNVX(vk_device, &moduleCreateInfo, NULL, &handle->vkCuModule))) < 0)
{
ERR("Failed to create cubin shader, vr %d.\n", vr);
vkd3d_free(handle);
return hresult_from_vk_result(vr);
}
functionCreateInfo.module = handle->vkCuModule;
functionCreateInfo.pName = shader_name;
if ((vr = VK_CALL(vkCreateCuFunctionNVX(vk_device, &functionCreateInfo, NULL, &handle->vkCuFunction))) < 0)
{
ERR("Failed to create cubin function module, vr %d.\n", vr);
VK_CALL(vkDestroyCuModuleNVX(vk_device, handle->vkCuModule, NULL));
vkd3d_free(handle);
return hresult_from_vk_result(vr);
}
*out_handle = handle;
return S_OK;
}
static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_DestroyCubinComputeShader(ID3D12DeviceExt *iface, D3D12_CUBIN_DATA_HANDLE *handle)
{
const struct vkd3d_vk_device_procs *vk_procs;
struct d3d12_device *device;
VkDevice vk_device;
TRACE("iface %p, handle %p \n", iface, handle);
if (!iface || !handle)
return E_INVALIDARG;
device = d3d12_device_from_ID3D12DeviceExt(iface);
vk_device = device->vk_device;
vk_procs = &device->vk_procs;
VK_CALL(vkDestroyCuFunctionNVX(vk_device, handle->vkCuFunction, NULL));
VK_CALL(vkDestroyCuModuleNVX(vk_device, handle->vkCuModule, NULL));
vkd3d_free(handle);
return S_OK;
}
static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_GetCudaTextureObject(ID3D12DeviceExt *iface, D3D12_CPU_DESCRIPTOR_HANDLE srv_handle,
D3D12_CPU_DESCRIPTOR_HANDLE sampler_handle, UINT32 *cuda_texture_handle)
{
VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX };
const struct vkd3d_vk_device_procs *vk_procs;
struct d3d12_desc_split sampler_desc;
struct d3d12_desc_split srv_desc;
struct d3d12_device *device;
TRACE("iface %p, srv_handle %zu, sampler_handle %zu, cuda_texture_handle %p.\n",
iface, srv_handle.ptr, sampler_handle.ptr, cuda_texture_handle);
if (!cuda_texture_handle)
return E_INVALIDARG;
device = d3d12_device_from_ID3D12DeviceExt(iface);
srv_desc = d3d12_desc_decode_va(srv_handle.ptr);
sampler_desc = d3d12_desc_decode_va(sampler_handle.ptr);
imageViewHandleInfo.imageView = srv_desc.view->info.view->vk_image_view;
imageViewHandleInfo.sampler = sampler_desc.view->info.view->vk_sampler;
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
vk_procs = &device->vk_procs;
*cuda_texture_handle = VK_CALL(vkGetImageViewHandleNVX(device->vk_device, &imageViewHandleInfo));
return S_OK;
}
static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_GetCudaSurfaceObject(ID3D12DeviceExt *iface, D3D12_CPU_DESCRIPTOR_HANDLE uav_handle,
UINT32 *cuda_surface_handle)
{
VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX };
const struct vkd3d_vk_device_procs *vk_procs;
struct d3d12_desc_split uav_desc;
struct d3d12_device *device;
TRACE("iface %p, uav_handle %zu, cuda_surface_handle %p.\n", iface, uav_handle.ptr, cuda_surface_handle);
if (!cuda_surface_handle)
return E_INVALIDARG;
device = d3d12_device_from_ID3D12DeviceExt(iface);
uav_desc = d3d12_desc_decode_va(uav_handle.ptr);
imageViewHandleInfo.imageView = uav_desc.view->info.view->vk_image_view;
imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
vk_procs = &device->vk_procs;
*cuda_surface_handle = VK_CALL(vkGetImageViewHandleNVX(device->vk_device, &imageViewHandleInfo));
return S_OK;
}
extern VKD3D_THREAD_LOCAL struct D3D12_UAV_INFO *d3d12_uav_info;
static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_CaptureUAVInfo(ID3D12DeviceExt *iface, D3D12_UAV_INFO *uav_info)
{
if (!uav_info)
return E_INVALIDARG;
TRACE("iface %p, uav_info %p.\n", iface, uav_info);
/* CaptureUAVInfo() supposed to capture the information from the next CreateUnorderedAccess() on the same thread.
We use d3d12_uav_info pointer to update the information in CreateUnorderedAccess() */
d3d12_uav_info = uav_info;
return S_OK;
}
CONST_VTBL struct ID3D12DeviceExtVtbl d3d12_device_vkd3d_ext_vtbl =
{
/* IUnknown methods */
d3d12_device_vkd3d_ext_QueryInterface,
d3d12_device_vkd3d_ext_AddRef,
d3d12_device_vkd3d_ext_Release,
/* ID3D12DeviceExt methods */
d3d12_device_vkd3d_ext_GetVulkanHandles,
d3d12_device_vkd3d_ext_GetExtensionSupport,
d3d12_device_vkd3d_ext_CreateCubinComputeShaderWithName,
d3d12_device_vkd3d_ext_DestroyCubinComputeShader,
d3d12_device_vkd3d_ext_GetCudaTextureObject,
d3d12_device_vkd3d_ext_GetCudaSurfaceObject,
d3d12_device_vkd3d_ext_CaptureUAVInfo
};

View File

@ -1,278 +0,0 @@
/*
* Copyright 2016 Józef Kucia for CodeWeavers
* Copyright 2019 Conor McCarthy for CodeWeavers
* Copyright 2021 Philip Rebohle for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "vkd3d_private.h"
/* ID3D12Heap */
static HRESULT STDMETHODCALLTYPE d3d12_heap_QueryInterface(d3d12_heap_iface *iface,
REFIID iid, void **object)
{
TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
if (IsEqualGUID(iid, &IID_ID3D12Heap)
|| IsEqualGUID(iid, &IID_ID3D12Heap1)
|| IsEqualGUID(iid, &IID_ID3D12Pageable)
|| IsEqualGUID(iid, &IID_ID3D12DeviceChild)
|| IsEqualGUID(iid, &IID_ID3D12Object)
|| IsEqualGUID(iid, &IID_IUnknown))
{
ID3D12Heap_AddRef(iface);
*object = iface;
return S_OK;
}
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
*object = NULL;
return E_NOINTERFACE;
}
static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(d3d12_heap_iface *iface)
{
struct d3d12_heap *heap = impl_from_ID3D12Heap1(iface);
ULONG refcount = InterlockedIncrement(&heap->refcount);
TRACE("%p increasing refcount to %u.\n", heap, refcount);
return refcount;
}
static void d3d12_heap_destroy(struct d3d12_heap *heap)
{
TRACE("Destroying heap %p.\n", heap);
vkd3d_free_memory(heap->device, &heap->device->memory_allocator, &heap->allocation);
vkd3d_private_store_destroy(&heap->private_store);
d3d12_device_release(heap->device);
vkd3d_free(heap);
}
static void d3d12_heap_set_name(struct d3d12_heap *heap, const char *name)
{
if (!heap->allocation.chunk)
vkd3d_set_vk_object_name(heap->device, (uint64_t)heap->allocation.device_allocation.vk_memory,
VK_OBJECT_TYPE_DEVICE_MEMORY, name);
}
static ULONG STDMETHODCALLTYPE d3d12_heap_Release(d3d12_heap_iface *iface)
{
struct d3d12_heap *heap = impl_from_ID3D12Heap1(iface);
ULONG refcount = InterlockedDecrement(&heap->refcount);
TRACE("%p decreasing refcount to %u.\n", heap, refcount);
if (!refcount)
d3d12_heap_destroy(heap);
return refcount;
}
static HRESULT STDMETHODCALLTYPE d3d12_heap_GetPrivateData(d3d12_heap_iface *iface,
REFGUID guid, UINT *data_size, void *data)
{
struct d3d12_heap *heap = impl_from_ID3D12Heap1(iface);
TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
return vkd3d_get_private_data(&heap->private_store, guid, data_size, data);
}
static HRESULT STDMETHODCALLTYPE d3d12_heap_SetPrivateData(d3d12_heap_iface *iface,
REFGUID guid, UINT data_size, const void *data)
{
struct d3d12_heap *heap = impl_from_ID3D12Heap1(iface);
TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
return vkd3d_set_private_data(&heap->private_store, guid, data_size, data,
(vkd3d_set_name_callback) d3d12_heap_set_name, heap);
}
static HRESULT STDMETHODCALLTYPE d3d12_heap_SetPrivateDataInterface(d3d12_heap_iface *iface,
REFGUID guid, const IUnknown *data)
{
struct d3d12_heap *heap = impl_from_ID3D12Heap1(iface);
TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
return vkd3d_set_private_data_interface(&heap->private_store, guid, data,
(vkd3d_set_name_callback) d3d12_heap_set_name, heap);
}
static HRESULT STDMETHODCALLTYPE d3d12_heap_GetDevice(d3d12_heap_iface *iface, REFIID iid, void **device)
{
struct d3d12_heap *heap = impl_from_ID3D12Heap1(iface);
TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
return d3d12_device_query_interface(heap->device, iid, device);
}
static D3D12_HEAP_DESC * STDMETHODCALLTYPE d3d12_heap_GetDesc(d3d12_heap_iface *iface,
D3D12_HEAP_DESC *desc)
{
struct d3d12_heap *heap = impl_from_ID3D12Heap1(iface);
TRACE("iface %p, desc %p.\n", iface, desc);
*desc = heap->desc;
return desc;
}
static HRESULT STDMETHODCALLTYPE d3d12_heap_GetProtectedResourceSession(d3d12_heap_iface *iface,
REFIID iid, void **protected_session)
{
FIXME("iface %p, iid %s, protected_session %p stub!", iface, debugstr_guid(iid), protected_session);
return E_NOTIMPL;
}
CONST_VTBL struct ID3D12Heap1Vtbl d3d12_heap_vtbl =
{
/* IUnknown methods */
d3d12_heap_QueryInterface,
d3d12_heap_AddRef,
d3d12_heap_Release,
/* ID3D12Object methods */
d3d12_heap_GetPrivateData,
d3d12_heap_SetPrivateData,
d3d12_heap_SetPrivateDataInterface,
(void *)d3d12_object_SetName,
/* ID3D12DeviceChild methods */
d3d12_heap_GetDevice,
/* ID3D12Heap methods */
d3d12_heap_GetDesc,
/* ID3D12Heap1 methods */
d3d12_heap_GetProtectedResourceSession,
};
HRESULT d3d12_device_validate_custom_heap_type(struct d3d12_device *device,
const D3D12_HEAP_PROPERTIES *heap_properties)
{
if (heap_properties->Type != D3D12_HEAP_TYPE_CUSTOM)
return S_OK;
if (heap_properties->MemoryPoolPreference == D3D12_MEMORY_POOL_UNKNOWN
|| (heap_properties->MemoryPoolPreference == D3D12_MEMORY_POOL_L1
&& (is_cpu_accessible_heap(heap_properties) || d3d12_device_is_uma(device, NULL))))
{
WARN("Invalid memory pool preference.\n");
return E_INVALIDARG;
}
if (heap_properties->CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_UNKNOWN)
{
WARN("Must have explicit CPU page property for CUSTOM heap type.\n");
return E_INVALIDARG;
}
return S_OK;
}
static HRESULT validate_heap_desc(struct d3d12_device *device, const D3D12_HEAP_DESC *desc)
{
HRESULT hr;
if (!desc->SizeInBytes)
{
WARN("Invalid size %"PRIu64".\n", desc->SizeInBytes);
return E_INVALIDARG;
}
if (desc->Alignment != D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT
&& desc->Alignment != D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT)
{
WARN("Invalid alignment %"PRIu64".\n", desc->Alignment);
return E_INVALIDARG;
}
if (desc->Flags & D3D12_HEAP_FLAG_ALLOW_DISPLAY)
{
WARN("D3D12_HEAP_FLAG_ALLOW_DISPLAY is only for committed resources.\n");
return E_INVALIDARG;
}
if (FAILED(hr = d3d12_device_validate_custom_heap_type(device, &desc->Properties)))
return hr;
return S_OK;
}
static HRESULT d3d12_heap_init(struct d3d12_heap *heap, struct d3d12_device *device,
const D3D12_HEAP_DESC *desc, void* host_address)
{
struct vkd3d_allocate_heap_memory_info alloc_info;
HRESULT hr;
memset(heap, 0, sizeof(*heap));
heap->ID3D12Heap_iface.lpVtbl = &d3d12_heap_vtbl;
heap->refcount = 1;
heap->desc = *desc;
heap->device = device;
if (!heap->desc.Properties.CreationNodeMask)
heap->desc.Properties.CreationNodeMask = 1;
if (!heap->desc.Properties.VisibleNodeMask)
heap->desc.Properties.VisibleNodeMask = 1;
if (!heap->desc.Alignment)
heap->desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
if (FAILED(hr = validate_heap_desc(device, &heap->desc)))
return hr;
alloc_info.heap_desc = heap->desc;
alloc_info.host_ptr = host_address;
alloc_info.extra_allocation_flags = 0;
if (FAILED(hr = vkd3d_private_store_init(&heap->private_store)))
return hr;
if (FAILED(hr = vkd3d_allocate_heap_memory(device,
&device->memory_allocator, &alloc_info, &heap->allocation)))
{
vkd3d_private_store_destroy(&heap->private_store);
return hr;
}
d3d12_device_add_ref(heap->device);
return S_OK;
}
HRESULT d3d12_heap_create(struct d3d12_device *device, const D3D12_HEAP_DESC *desc,
void* host_address, struct d3d12_heap **heap)
{
struct d3d12_heap *object;
HRESULT hr;
if (!(object = vkd3d_malloc(sizeof(*object))))
return E_OUTOFMEMORY;
if (FAILED(hr = d3d12_heap_init(object, device, desc, host_address)))
{
vkd3d_free(object);
return hr;
}
TRACE("Created heap %p.\n", object);
*heap = object;
return S_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
vkd3d_shaders =[
'shaders/cs_clear_uav_buffer_float.comp',
'shaders/cs_clear_uav_buffer_raw.comp',
'shaders/cs_clear_uav_buffer_uint.comp',
'shaders/cs_clear_uav_image_1d_array_float.comp',
'shaders/cs_clear_uav_image_1d_array_uint.comp',
@ -12,46 +11,28 @@ vkd3d_shaders =[
'shaders/cs_clear_uav_image_2d_uint.comp',
'shaders/cs_clear_uav_image_3d_float.comp',
'shaders/cs_clear_uav_image_3d_uint.comp',
'shaders/cs_predicate_command.comp',
'shaders/cs_resolve_binary_queries.comp',
'shaders/cs_resolve_predicate.comp',
'shaders/cs_resolve_query.comp',
'shaders/fs_copy_image_float.frag',
'shaders/fs_copy_image_uint.frag',
'shaders/fs_copy_image_stencil.frag',
'shaders/gs_fullscreen.geom',
'shaders/vs_fullscreen.vert',
'shaders/vs_fullscreen_layer.vert',
'shaders/vs_swapchain_fullscreen.vert',
'shaders/fs_swapchain_fullscreen.frag',
'shaders/cs_execute_indirect_patch.comp',
'shaders/cs_execute_indirect_patch_debug_ring.comp',
]
vkd3d_src = [
'bundle.c',
'cache.c',
'command.c',
'command_list_vkd3d_ext.c',
'device.c',
'device_vkd3d_ext.c',
'heap.c',
'memory.c',
'meta.c',
'platform.c',
'resource.c',
'state.c',
'utils.c',
'debug_ring.c',
'va_map.c',
'vkd3d_main.c',
'raytracing_pipeline.c',
'acceleration_structure.c'
]
if enable_d3d12
if enable_standalone_d3d12
vkd3d_src += 'swapchain.c'
endif
@ -59,28 +40,16 @@ if enable_renderdoc
vkd3d_src += ['renderdoc.c']
endif
if enable_descriptor_qa
vkd3d_src += ['descriptor_debug.c']
endif
if enable_breadcrumbs
vkd3d_src += ['breadcrumbs.c']
endif
if vkd3d_platform == 'windows'
vkd3d_src += ['shared_metadata.c']
endif
if not enable_d3d12
vkd3d_lib = shared_library('vkd3d-proton', vkd3d_src, glsl_generator.process(vkd3d_shaders), vkd3d_build, vkd3d_version,
if not enable_standalone_d3d12
vkd3d_lib = shared_library('vkd3d', vkd3d_src, glsl_generator.process(vkd3d_shaders), vkd3d_version, vkd3d_headers,
dependencies : [ vkd3d_common_dep, vkd3d_shader_dep ] + vkd3d_extra_libs,
include_directories : vkd3d_private_includes,
install : true,
version : '3.0.0',
c_args : '-DVKD3D_EXPORTS',
vs_module_defs : 'vkd3d.def',
version : '1.1.0',
override_options : [ 'c_std='+vkd3d_c_std ])
else
vkd3d_lib = static_library('vkd3d-proton', vkd3d_src, glsl_generator.process(vkd3d_shaders), vkd3d_build, vkd3d_version,
vkd3d_lib = static_library('vkd3d', vkd3d_src, glsl_generator.process(vkd3d_shaders), vkd3d_version, vkd3d_headers,
dependencies : [ vkd3d_common_dep, vkd3d_shader_dep ] + vkd3d_extra_libs,
include_directories : vkd3d_private_includes,
override_options : [ 'c_std='+vkd3d_c_std ])
@ -88,5 +57,5 @@ endif
vkd3d_dep = declare_dependency(
link_with : [ vkd3d_lib, vkd3d_common_lib ],
dependencies : [ vkd3d_extra_libs, vkd3d_common_dep ],
dependencies : vkd3d_extra_libs,
include_directories : vkd3d_public_includes)

View File

@ -53,28 +53,6 @@ static VkResult vkd3d_meta_create_descriptor_set_layout(struct d3d12_device *dev
return VK_CALL(vkCreateDescriptorSetLayout(device->vk_device, &set_layout_info, NULL, set_layout));
}
static VkResult vkd3d_meta_create_sampler(struct d3d12_device *device, VkFilter filter, VkSampler *vk_sampler)
{
struct vkd3d_view_key view_key;
struct vkd3d_view *view;
D3D12_SAMPLER_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
desc.Filter = filter == VK_FILTER_LINEAR ? D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_POINT;
view_key.view_type = VKD3D_VIEW_TYPE_SAMPLER;
view_key.u.sampler = desc;
view = vkd3d_view_map_create_view(&device->sampler_map, device, &view_key);
if (!view)
return VK_ERROR_OUT_OF_HOST_MEMORY;
*vk_sampler = view->vk_sampler;
return VK_SUCCESS;
}
static VkResult vkd3d_meta_create_pipeline_layout(struct d3d12_device *device,
uint32_t set_layout_count, const VkDescriptorSetLayout *set_layouts,
uint32_t push_constant_range_count, const VkPushConstantRange *push_constant_ranges,
@ -137,9 +115,68 @@ static VkResult vkd3d_meta_create_compute_pipeline(struct d3d12_device *device,
return vr;
}
static VkResult vkd3d_meta_create_render_pass(struct d3d12_device *device, VkSampleCountFlagBits samples,
const struct vkd3d_format *format, VkRenderPass *vk_render_pass)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VkAttachmentDescription attachment_info;
VkAttachmentReference attachment_ref;
VkSubpassDescription subpass_info;
VkRenderPassCreateInfo pass_info;
bool has_depth_target;
VkImageLayout layout;
VkResult vr;
assert(format);
has_depth_target = (format->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0;
layout = has_depth_target
? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment_info.flags = 0;
attachment_info.format = format->vk_format;
attachment_info.samples = samples;
attachment_info.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachment_info.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_info.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachment_info.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_info.initialLayout = layout;
attachment_info.finalLayout = layout;
attachment_ref.attachment = 0;
attachment_ref.layout = layout;
subpass_info.flags = 0;
subpass_info.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass_info.inputAttachmentCount = 0;
subpass_info.pInputAttachments = NULL;
subpass_info.colorAttachmentCount = has_depth_target ? 0 : 1;
subpass_info.pColorAttachments = has_depth_target ? NULL : &attachment_ref;
subpass_info.pResolveAttachments = NULL;
subpass_info.pDepthStencilAttachment = has_depth_target ? &attachment_ref : NULL;
subpass_info.preserveAttachmentCount = 0;
subpass_info.pPreserveAttachments = NULL;
pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
pass_info.pNext = NULL;
pass_info.flags = 0;
pass_info.attachmentCount = 1;
pass_info.pAttachments = &attachment_info;
pass_info.subpassCount = 1;
pass_info.pSubpasses = &subpass_info;
pass_info.dependencyCount = 0;
pass_info.pDependencies = NULL;
if ((vr = VK_CALL(vkCreateRenderPass(device->vk_device, &pass_info, NULL, vk_render_pass))) < 0)
ERR("Failed to create render pass, vr %d.\n", vr);
return vr;
}
static VkResult vkd3d_meta_create_graphics_pipeline(struct vkd3d_meta_ops *meta_ops,
VkPipelineLayout layout, VkFormat color_format, VkFormat ds_format, VkImageAspectFlags vk_aspect_mask,
VkShaderModule vs_module, VkShaderModule fs_module,
VkPipelineLayout layout, VkRenderPass render_pass, VkShaderModule fs_module,
VkSampleCountFlagBits samples, const VkPipelineDepthStencilStateCreateInfo *ds_state,
const VkPipelineColorBlendStateCreateInfo *cb_state, const VkSpecializationInfo *spec_info,
VkPipeline *vk_pipeline)
@ -148,7 +185,6 @@ static VkResult vkd3d_meta_create_graphics_pipeline(struct vkd3d_meta_ops *meta_
VkPipelineShaderStageCreateInfo shader_stages[3];
VkPipelineInputAssemblyStateCreateInfo ia_state;
VkPipelineRasterizationStateCreateInfo rs_state;
VkPipelineRenderingCreateInfoKHR rendering_info;
VkPipelineVertexInputStateCreateInfo vi_state;
VkPipelineMultisampleStateCreateInfo ms_state;
VkPipelineViewportStateCreateInfo vp_state;
@ -215,16 +251,8 @@ static VkResult vkd3d_meta_create_graphics_pipeline(struct vkd3d_meta_ops *meta_
dyn_state.dynamicStateCount = ARRAY_SIZE(dynamic_states);
dyn_state.pDynamicStates = dynamic_states;
rendering_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR;
rendering_info.pNext = NULL;
rendering_info.viewMask = 0;
rendering_info.colorAttachmentCount = color_format && (vk_aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) ? 1 : 0;
rendering_info.pColorAttachmentFormats = color_format ? &color_format : NULL;
rendering_info.depthAttachmentFormat = (vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) ? ds_format : VK_FORMAT_UNDEFINED;
rendering_info.stencilAttachmentFormat = (vk_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) ? ds_format : VK_FORMAT_UNDEFINED;
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_info.pNext = &rendering_info;
pipeline_info.pNext = NULL;
pipeline_info.flags = 0;
pipeline_info.stageCount = 0;
pipeline_info.pStages = shader_stages;
@ -238,15 +266,13 @@ static VkResult vkd3d_meta_create_graphics_pipeline(struct vkd3d_meta_ops *meta_
pipeline_info.pColorBlendState = cb_state;
pipeline_info.pDynamicState = &dyn_state;
pipeline_info.layout = layout;
pipeline_info.renderPass = VK_NULL_HANDLE;
pipeline_info.renderPass = render_pass;
pipeline_info.subpass = 0;
pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
pipeline_info.basePipelineIndex = -1;
vkd3d_meta_make_shader_stage(&shader_stages[pipeline_info.stageCount++],
VK_SHADER_STAGE_VERTEX_BIT,
vs_module ? vs_module : meta_ops->common.vk_module_fullscreen_vs,
"main", NULL);
VK_SHADER_STAGE_VERTEX_BIT, meta_ops->common.vk_module_fullscreen_vs, "main", NULL);
if (meta_ops->common.vk_module_fullscreen_gs)
{
@ -283,9 +309,8 @@ HRESULT vkd3d_clear_uav_ops_init(struct vkd3d_clear_uav_ops *meta_clear_uav_ops,
}
set_layouts[] =
{
{ &meta_clear_uav_ops->vk_set_layout_buffer_raw, &meta_clear_uav_ops->vk_pipeline_layout_buffer_raw, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER },
{ &meta_clear_uav_ops->vk_set_layout_buffer, &meta_clear_uav_ops->vk_pipeline_layout_buffer, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER },
{ &meta_clear_uav_ops->vk_set_layout_image, &meta_clear_uav_ops->vk_pipeline_layout_image, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },
{ &meta_clear_uav_ops->vk_set_layout_buffer, &meta_clear_uav_ops->vk_pipeline_layout_buffer, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER },
{ &meta_clear_uav_ops->vk_set_layout_image, &meta_clear_uav_ops->vk_pipeline_layout_image, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE },
};
struct {
@ -317,9 +342,6 @@ HRESULT vkd3d_clear_uav_ops_init(struct vkd3d_clear_uav_ops *meta_clear_uav_ops,
{ &meta_clear_uav_ops->clear_uint.buffer,
&meta_clear_uav_ops->vk_pipeline_layout_buffer,
SPIRV_CODE(cs_clear_uav_buffer_uint) },
{ &meta_clear_uav_ops->clear_uint.buffer_raw,
&meta_clear_uav_ops->vk_pipeline_layout_buffer_raw,
SPIRV_CODE(cs_clear_uav_buffer_raw) },
{ &meta_clear_uav_ops->clear_uint.image_1d,
&meta_clear_uav_ops->vk_pipeline_layout_image,
SPIRV_CODE(cs_clear_uav_image_1d_uint) },
@ -397,18 +419,15 @@ void vkd3d_clear_uav_ops_cleanup(struct vkd3d_clear_uav_ops *meta_clear_uav_ops,
&meta_clear_uav_ops->clear_uint,
};
VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, meta_clear_uav_ops->vk_set_layout_buffer_raw, NULL));
VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, meta_clear_uav_ops->vk_set_layout_buffer, NULL));
VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, meta_clear_uav_ops->vk_set_layout_image, NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_clear_uav_ops->vk_pipeline_layout_buffer_raw, NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_clear_uav_ops->vk_pipeline_layout_buffer, NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_clear_uav_ops->vk_pipeline_layout_image, NULL));
for (i = 0; i < ARRAY_SIZE(pipeline_sets); i++)
{
VK_CALL(vkDestroyPipeline(device->vk_device, pipeline_sets[i]->buffer, NULL));
VK_CALL(vkDestroyPipeline(device->vk_device, pipeline_sets[i]->buffer_raw, NULL));
VK_CALL(vkDestroyPipeline(device->vk_device, pipeline_sets[i]->image_1d, NULL));
VK_CALL(vkDestroyPipeline(device->vk_device, pipeline_sets[i]->image_2d, NULL));
VK_CALL(vkDestroyPipeline(device->vk_device, pipeline_sets[i]->image_3d, NULL));
@ -418,18 +437,18 @@ void vkd3d_clear_uav_ops_cleanup(struct vkd3d_clear_uav_ops *meta_clear_uav_ops,
}
struct vkd3d_clear_uav_pipeline vkd3d_meta_get_clear_buffer_uav_pipeline(struct vkd3d_meta_ops *meta_ops,
bool as_uint, bool raw)
bool as_uint)
{
struct vkd3d_clear_uav_ops *meta_clear_uav_ops = &meta_ops->clear_uav;
struct vkd3d_clear_uav_pipeline info;
const struct vkd3d_clear_uav_pipelines *pipelines = (as_uint || raw)
const struct vkd3d_clear_uav_pipelines *pipelines = as_uint
? &meta_clear_uav_ops->clear_uint
: &meta_clear_uav_ops->clear_float;
info.vk_set_layout = raw ? meta_clear_uav_ops->vk_set_layout_buffer_raw : meta_clear_uav_ops->vk_set_layout_buffer;
info.vk_pipeline_layout = raw ? meta_clear_uav_ops->vk_pipeline_layout_buffer_raw : meta_clear_uav_ops->vk_pipeline_layout_buffer;
info.vk_pipeline = raw ? pipelines->buffer_raw : pipelines->buffer;
info.vk_set_layout = meta_clear_uav_ops->vk_set_layout_buffer;
info.vk_pipeline_layout = meta_clear_uav_ops->vk_pipeline_layout_buffer;
info.vk_pipeline = pipelines->buffer;
return info;
}
@ -536,30 +555,12 @@ HRESULT vkd3d_copy_image_ops_init(struct vkd3d_copy_image_ops *meta_copy_image_o
goto fail;
}
if ((vr = vkd3d_meta_create_shader_module(device, SPIRV_CODE(fs_copy_image_float),
&meta_copy_image_ops->vk_fs_float_module)) < 0)
if ((vr = vkd3d_meta_create_shader_module(device, SPIRV_CODE(fs_copy_image_float), &meta_copy_image_ops->vk_fs_module)) < 0)
{
ERR("Failed to create shader modules, vr %d.\n", vr);
goto fail;
}
if ((vr = vkd3d_meta_create_shader_module(device, SPIRV_CODE(fs_copy_image_uint),
&meta_copy_image_ops->vk_fs_uint_module)) < 0)
{
ERR("Failed to create shader modules, vr %d.\n", vr);
goto fail;
}
if (device->vk_info.EXT_shader_stencil_export)
{
if ((vr = vkd3d_meta_create_shader_module(device, SPIRV_CODE(fs_copy_image_stencil),
&meta_copy_image_ops->vk_fs_stencil_module)) < 0)
{
ERR("Failed to create shader modules, vr %d.\n", vr);
goto fail;
}
}
return S_OK;
fail:
@ -577,59 +578,28 @@ void vkd3d_copy_image_ops_cleanup(struct vkd3d_copy_image_ops *meta_copy_image_o
{
struct vkd3d_copy_image_pipeline *pipeline = &meta_copy_image_ops->pipelines[i];
VK_CALL(vkDestroyRenderPass(device->vk_device, pipeline->vk_render_pass, NULL));
VK_CALL(vkDestroyPipeline(device->vk_device, pipeline->vk_pipeline, NULL));
}
VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, meta_copy_image_ops->vk_set_layout, NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_copy_image_ops->vk_pipeline_layout, NULL));
VK_CALL(vkDestroyShaderModule(device->vk_device, meta_copy_image_ops->vk_fs_float_module, NULL));
VK_CALL(vkDestroyShaderModule(device->vk_device, meta_copy_image_ops->vk_fs_uint_module, NULL));
VK_CALL(vkDestroyShaderModule(device->vk_device, meta_copy_image_ops->vk_fs_stencil_module, NULL));
VK_CALL(vkDestroyShaderModule(device->vk_device, meta_copy_image_ops->vk_fs_module, NULL));
pthread_mutex_destroy(&meta_copy_image_ops->mutex);
vkd3d_free(meta_copy_image_ops->pipelines);
}
static HRESULT vkd3d_meta_create_swapchain_pipeline(struct vkd3d_meta_ops *meta_ops,
const struct vkd3d_swapchain_pipeline_key *key, struct vkd3d_swapchain_pipeline *pipeline)
{
struct vkd3d_swapchain_ops *meta_swapchain_ops = &meta_ops->swapchain;
VkPipelineColorBlendAttachmentState blend_att;
VkPipelineColorBlendStateCreateInfo cb_state;
VkResult vr;
memset(&cb_state, 0, sizeof(cb_state));
memset(&blend_att, 0, sizeof(blend_att));
cb_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
cb_state.attachmentCount = 1;
cb_state.pAttachments = &blend_att;
blend_att.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT |
VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT;
if ((vr = vkd3d_meta_create_graphics_pipeline(meta_ops,
meta_swapchain_ops->vk_pipeline_layouts[key->filter], key->format, VK_FORMAT_UNDEFINED, VK_IMAGE_ASPECT_COLOR_BIT,
meta_swapchain_ops->vk_vs_module, meta_swapchain_ops->vk_fs_module, 1,
NULL, &cb_state,
NULL, &pipeline->vk_pipeline)) < 0)
return hresult_from_vk_result(vr);
pipeline->key = *key;
return S_OK;
}
static HRESULT vkd3d_meta_create_copy_image_pipeline(struct vkd3d_meta_ops *meta_ops,
const struct vkd3d_copy_image_pipeline_key *key, struct vkd3d_copy_image_pipeline *pipeline)
{
const struct vkd3d_vk_device_procs *vk_procs = &meta_ops->device->vk_procs;
struct vkd3d_copy_image_ops *meta_copy_image_ops = &meta_ops->copy_image;
VkPipelineColorBlendAttachmentState blend_attachment;
VkPipelineDepthStencilStateCreateInfo ds_state;
VkPipelineColorBlendStateCreateInfo cb_state;
VkSpecializationInfo spec_info;
VkShaderModule vk_module;
bool has_depth_target;
VkResult vr;
@ -668,30 +638,13 @@ static HRESULT vkd3d_meta_create_copy_image_pipeline(struct vkd3d_meta_ops *meta
ds_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
ds_state.pNext = NULL;
ds_state.flags = 0;
ds_state.depthTestEnable = (key->dst_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) ? VK_TRUE : VK_FALSE;
ds_state.depthWriteEnable = ds_state.depthTestEnable;
ds_state.depthTestEnable = VK_TRUE;
ds_state.depthWriteEnable = VK_TRUE;
ds_state.depthCompareOp = VK_COMPARE_OP_ALWAYS;
ds_state.depthBoundsTestEnable = VK_FALSE;
if (key->dst_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)
{
ds_state.stencilTestEnable = VK_TRUE;
ds_state.front.reference = 0;
ds_state.front.writeMask = 0xff;
ds_state.front.compareMask = 0xff;
ds_state.front.passOp = VK_STENCIL_OP_REPLACE;
ds_state.front.failOp = VK_STENCIL_OP_KEEP;
ds_state.front.depthFailOp = VK_STENCIL_OP_KEEP;
ds_state.front.compareOp = VK_COMPARE_OP_ALWAYS;
ds_state.back = ds_state.front;
}
else
{
ds_state.stencilTestEnable = VK_FALSE;
memset(&ds_state.front, 0, sizeof(ds_state.front));
memset(&ds_state.back, 0, sizeof(ds_state.back));
}
ds_state.stencilTestEnable = VK_FALSE;
memset(&ds_state.front, 0, sizeof(ds_state.front));
memset(&ds_state.back, 0, sizeof(ds_state.back));
ds_state.minDepthBounds = 0.0f;
ds_state.maxDepthBounds = 1.0f;
@ -710,32 +663,19 @@ static HRESULT vkd3d_meta_create_copy_image_pipeline(struct vkd3d_meta_ops *meta
cb_state.pAttachments = &blend_attachment;
memset(&cb_state.blendConstants, 0, sizeof(cb_state.blendConstants));
/* Special path when copying stencil -> color. */
if (key->format->vk_format == VK_FORMAT_R8_UINT)
{
/* Special path when copying stencil -> color. */
vk_module = meta_copy_image_ops->vk_fs_uint_module;
}
else if (key->dst_aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT)
{
/* FragStencilRef path. */
vk_module = meta_copy_image_ops->vk_fs_stencil_module;
}
else
{
/* Depth or float color path. */
vk_module = meta_copy_image_ops->vk_fs_float_module;
}
if ((vr = vkd3d_meta_create_render_pass(meta_ops->device,
key->sample_count, key->format, &pipeline->vk_render_pass)) < 0)
return hresult_from_vk_result(vr);
if ((vr = vkd3d_meta_create_graphics_pipeline(meta_ops,
meta_copy_image_ops->vk_pipeline_layout,
has_depth_target ? VK_FORMAT_UNDEFINED : key->format->vk_format,
has_depth_target ? key->format->vk_format : VK_FORMAT_UNDEFINED,
key->format->vk_aspect_mask,
VK_NULL_HANDLE, vk_module, key->sample_count,
meta_copy_image_ops->vk_pipeline_layout, pipeline->vk_render_pass,
meta_copy_image_ops->vk_fs_module, key->sample_count,
has_depth_target ? &ds_state : NULL, has_depth_target ? NULL : &cb_state,
&spec_info, &pipeline->vk_pipeline)) < 0)
{
VK_CALL(vkDestroyRenderPass(meta_ops->device->vk_device, pipeline->vk_render_pass, NULL));
return hresult_from_vk_result(vr);
}
pipeline->key = *key;
return S_OK;
@ -765,6 +705,7 @@ HRESULT vkd3d_meta_get_copy_image_pipeline(struct vkd3d_meta_ops *meta_ops,
if (!memcmp(key, &pipeline->key, sizeof(*key)))
{
info->vk_render_pass = pipeline->vk_render_pass;
info->vk_pipeline = pipeline->vk_pipeline;
pthread_mutex_unlock(&meta_copy_image_ops->mutex);
return S_OK;
@ -786,6 +727,7 @@ HRESULT vkd3d_meta_get_copy_image_pipeline(struct vkd3d_meta_ops *meta_ops,
return hr;
}
info->vk_render_pass = pipeline->vk_render_pass;
info->vk_pipeline = pipeline->vk_pipeline;
pthread_mutex_unlock(&meta_copy_image_ops->mutex);
@ -807,32 +749,23 @@ VkImageViewType vkd3d_meta_get_copy_image_view_type(D3D12_RESOURCE_DIMENSION dim
}
const struct vkd3d_format *vkd3d_meta_get_copy_image_attachment_format(struct vkd3d_meta_ops *meta_ops,
const struct vkd3d_format *dst_format, const struct vkd3d_format *src_format,
VkImageAspectFlags dst_aspect, VkImageAspectFlags src_aspect)
const struct vkd3d_format *dst_format, const struct vkd3d_format *src_format)
{
DXGI_FORMAT dxgi_format = DXGI_FORMAT_UNKNOWN;
if (dst_aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
if (dst_format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
return dst_format;
assert(src_aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
assert(src_format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT);
switch (src_format->vk_format)
{
case VK_FORMAT_D16_UNORM:
dxgi_format = DXGI_FORMAT_R16_UNORM;
break;
case VK_FORMAT_D16_UNORM_S8_UINT:
dxgi_format = (src_aspect & VK_IMAGE_ASPECT_DEPTH_BIT) ?
DXGI_FORMAT_R16_UNORM : DXGI_FORMAT_R8_UINT;
break;
case VK_FORMAT_D32_SFLOAT:
dxgi_format = DXGI_FORMAT_R32_FLOAT;
break;
case VK_FORMAT_D32_SFLOAT_S8_UINT:
dxgi_format = (src_aspect & VK_IMAGE_ASPECT_DEPTH_BIT) ?
DXGI_FORMAT_R32_FLOAT : DXGI_FORMAT_R8_UINT;
break;
default:
ERR("Unhandled format %u.\n", src_format->vk_format);
return NULL;
@ -874,487 +807,6 @@ static void vkd3d_meta_ops_common_cleanup(struct vkd3d_meta_ops_common *meta_ops
VK_CALL(vkDestroyShaderModule(device->vk_device, meta_ops_common->vk_module_fullscreen_gs, NULL));
}
HRESULT vkd3d_swapchain_ops_init(struct vkd3d_swapchain_ops *meta_swapchain_ops, struct d3d12_device *device)
{
VkDescriptorSetLayoutBinding set_binding;
unsigned int i;
VkResult vr;
int rc;
memset(meta_swapchain_ops, 0, sizeof(*meta_swapchain_ops));
if ((rc = pthread_mutex_init(&meta_swapchain_ops->mutex, NULL)))
{
ERR("Failed to initialize mutex, error %d.\n", rc);
return hresult_from_errno(rc);
}
set_binding.binding = 0;
set_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
set_binding.descriptorCount = 1;
set_binding.stageFlags = VK_SHADER_STAGE_ALL; /* Could be compute or graphics, so just use ALL. */
for (i = 0; i < 2; i++)
{
if ((vr = vkd3d_meta_create_sampler(device, (VkFilter)i, &meta_swapchain_ops->vk_samplers[i])))
{
ERR("Failed to create sampler, vr, %d.\n", vr);
goto fail;
}
set_binding.pImmutableSamplers = &meta_swapchain_ops->vk_samplers[i];
if ((vr = vkd3d_meta_create_descriptor_set_layout(device, 1, &set_binding,
&meta_swapchain_ops->vk_set_layouts[i])) < 0)
{
ERR("Failed to create descriptor set layout, vr %d.\n", vr);
goto fail;
}
if ((vr = vkd3d_meta_create_pipeline_layout(device, 1, &meta_swapchain_ops->vk_set_layouts[i],
0, NULL, &meta_swapchain_ops->vk_pipeline_layouts[i])))
{
ERR("Failed to create pipeline layout, vr %d.\n", vr);
goto fail;
}
}
if ((vr = vkd3d_meta_create_shader_module(device, SPIRV_CODE(vs_swapchain_fullscreen), &meta_swapchain_ops->vk_vs_module)) < 0)
{
ERR("Failed to create shader modules, vr %d.\n", vr);
goto fail;
}
if ((vr = vkd3d_meta_create_shader_module(device, SPIRV_CODE(fs_swapchain_fullscreen), &meta_swapchain_ops->vk_fs_module)) < 0)
{
ERR("Failed to create shader modules, vr %d.\n", vr);
goto fail;
}
return S_OK;
fail:
vkd3d_swapchain_ops_cleanup(meta_swapchain_ops, device);
return hresult_from_vk_result(vr);
}
void vkd3d_swapchain_ops_cleanup(struct vkd3d_swapchain_ops *meta_swapchain_ops, struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
size_t i;
for (i = 0; i < meta_swapchain_ops->pipeline_count; i++)
{
struct vkd3d_swapchain_pipeline *pipeline = &meta_swapchain_ops->pipelines[i];
VK_CALL(vkDestroyPipeline(device->vk_device, pipeline->vk_pipeline, NULL));
}
for (i = 0; i < 2; i++)
{
VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, meta_swapchain_ops->vk_set_layouts[i], NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_swapchain_ops->vk_pipeline_layouts[i], NULL));
}
VK_CALL(vkDestroyShaderModule(device->vk_device, meta_swapchain_ops->vk_vs_module, NULL));
VK_CALL(vkDestroyShaderModule(device->vk_device, meta_swapchain_ops->vk_fs_module, NULL));
pthread_mutex_destroy(&meta_swapchain_ops->mutex);
vkd3d_free(meta_swapchain_ops->pipelines);
}
HRESULT vkd3d_meta_get_swapchain_pipeline(struct vkd3d_meta_ops *meta_ops,
const struct vkd3d_swapchain_pipeline_key *key, struct vkd3d_swapchain_info *info)
{
struct vkd3d_swapchain_ops *meta_swapchain_ops = &meta_ops->swapchain;
struct vkd3d_swapchain_pipeline *pipeline;
HRESULT hr;
size_t i;
int rc;
if ((rc = pthread_mutex_lock(&meta_swapchain_ops->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return hresult_from_errno(rc);
}
info->vk_set_layout = meta_swapchain_ops->vk_set_layouts[key->filter];
info->vk_pipeline_layout = meta_swapchain_ops->vk_pipeline_layouts[key->filter];
for (i = 0; i < meta_swapchain_ops->pipeline_count; i++)
{
pipeline = &meta_swapchain_ops->pipelines[i];
if (!memcmp(key, &pipeline->key, sizeof(*key)))
{
info->vk_pipeline = pipeline->vk_pipeline;
pthread_mutex_unlock(&meta_swapchain_ops->mutex);
return S_OK;
}
}
if (!vkd3d_array_reserve((void **)&meta_swapchain_ops->pipelines, &meta_swapchain_ops->pipelines_size,
meta_swapchain_ops->pipeline_count + 1, sizeof(*meta_swapchain_ops->pipelines)))
{
ERR("Failed to reserve space for pipeline.\n");
return E_OUTOFMEMORY;
}
pipeline = &meta_swapchain_ops->pipelines[meta_swapchain_ops->pipeline_count++];
if (FAILED(hr = vkd3d_meta_create_swapchain_pipeline(meta_ops, key, pipeline)))
{
pthread_mutex_unlock(&meta_swapchain_ops->mutex);
return hr;
}
info->vk_pipeline = pipeline->vk_pipeline;
pthread_mutex_unlock(&meta_swapchain_ops->mutex);
return S_OK;
}
HRESULT vkd3d_query_ops_init(struct vkd3d_query_ops *meta_query_ops,
struct d3d12_device *device)
{
VkPushConstantRange push_constant_range;
VkSpecializationInfo spec_info;
uint32_t field_count;
VkResult vr;
static const VkDescriptorSetLayoutBinding gather_bindings[] =
{
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
};
static const VkDescriptorSetLayoutBinding resolve_bindings[] =
{
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
};
static const VkSpecializationMapEntry spec_map = { 0, 0, sizeof(uint32_t) };
if ((vr = vkd3d_meta_create_descriptor_set_layout(device,
ARRAY_SIZE(gather_bindings), gather_bindings,
&meta_query_ops->vk_gather_set_layout)) < 0)
goto fail;
push_constant_range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
push_constant_range.offset = 0;
push_constant_range.size = sizeof(struct vkd3d_query_gather_args);
if ((vr = vkd3d_meta_create_pipeline_layout(device, 1, &meta_query_ops->vk_gather_set_layout,
1, &push_constant_range, &meta_query_ops->vk_gather_pipeline_layout)) < 0)
goto fail;
spec_info.mapEntryCount = 1;
spec_info.pMapEntries = &spec_map;
spec_info.dataSize = sizeof(field_count);
spec_info.pData = &field_count;
field_count = 1;
if ((vr = vkd3d_meta_create_compute_pipeline(device, sizeof(cs_resolve_query), cs_resolve_query,
meta_query_ops->vk_gather_pipeline_layout, &spec_info, &meta_query_ops->vk_gather_occlusion_pipeline)) < 0)
goto fail;
field_count = 2;
if ((vr = vkd3d_meta_create_compute_pipeline(device, sizeof(cs_resolve_query), cs_resolve_query,
meta_query_ops->vk_gather_pipeline_layout, &spec_info, &meta_query_ops->vk_gather_so_statistics_pipeline)) < 0)
goto fail;
push_constant_range.size = sizeof(struct vkd3d_query_resolve_args);
if ((vr = vkd3d_meta_create_descriptor_set_layout(device,
ARRAY_SIZE(resolve_bindings), resolve_bindings,
&meta_query_ops->vk_resolve_set_layout)) < 0)
goto fail;
if ((vr = vkd3d_meta_create_pipeline_layout(device, 1, &meta_query_ops->vk_resolve_set_layout,
1, &push_constant_range, &meta_query_ops->vk_resolve_pipeline_layout)) < 0)
goto fail;
if ((vr = vkd3d_meta_create_compute_pipeline(device, sizeof(cs_resolve_binary_queries), cs_resolve_binary_queries,
meta_query_ops->vk_resolve_pipeline_layout, NULL, &meta_query_ops->vk_resolve_binary_pipeline)) < 0)
goto fail;
return S_OK;
fail:
vkd3d_query_ops_cleanup(meta_query_ops, device);
return hresult_from_vk_result(vr);
}
void vkd3d_query_ops_cleanup(struct vkd3d_query_ops *meta_query_ops,
struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VK_CALL(vkDestroyPipeline(device->vk_device, meta_query_ops->vk_gather_occlusion_pipeline, NULL));
VK_CALL(vkDestroyPipeline(device->vk_device, meta_query_ops->vk_gather_so_statistics_pipeline, NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_query_ops->vk_gather_pipeline_layout, NULL));
VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, meta_query_ops->vk_gather_set_layout, NULL));
VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, meta_query_ops->vk_resolve_set_layout, NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_query_ops->vk_resolve_pipeline_layout, NULL));
VK_CALL(vkDestroyPipeline(device->vk_device, meta_query_ops->vk_resolve_binary_pipeline, NULL));
}
bool vkd3d_meta_get_query_gather_pipeline(struct vkd3d_meta_ops *meta_ops,
D3D12_QUERY_HEAP_TYPE heap_type, struct vkd3d_query_gather_info *info)
{
const struct vkd3d_query_ops *query_ops = &meta_ops->query;
info->vk_set_layout = query_ops->vk_gather_set_layout;
info->vk_pipeline_layout = query_ops->vk_gather_pipeline_layout;
switch (heap_type)
{
case D3D12_QUERY_HEAP_TYPE_OCCLUSION:
info->vk_pipeline = query_ops->vk_gather_occlusion_pipeline;
return true;
case D3D12_QUERY_HEAP_TYPE_SO_STATISTICS:
info->vk_pipeline = query_ops->vk_gather_so_statistics_pipeline;
return true;
default:
ERR("No pipeline for query heap type %u.\n", heap_type);
return false;
}
}
HRESULT vkd3d_predicate_ops_init(struct vkd3d_predicate_ops *meta_predicate_ops,
struct d3d12_device *device)
{
VkPushConstantRange push_constant_range;
VkSpecializationInfo spec_info;
VkResult vr;
size_t i;
static const struct spec_data
{
uint32_t arg_count;
VkBool32 arg_indirect;
}
spec_data[] =
{
{ 4, VK_FALSE }, /* VKD3D_PREDICATE_OP_DRAW */
{ 5, VK_FALSE }, /* VKD3D_PREDICATE_OP_DRAW_INDEXED */
{ 1, VK_FALSE }, /* VKD3D_PREDICATE_OP_DRAW_INDIRECT */
{ 1, VK_TRUE }, /* VKD3D_PREDICATE_OP_DRAW_INDIRECT_COUNT */
{ 3, VK_FALSE }, /* VKD3D_PREDICATE_OP_DISPATCH */
{ 3, VK_TRUE }, /* VKD3D_PREDICATE_OP_DISPATCH_INDIRECT */
};
static const VkSpecializationMapEntry spec_map[] =
{
{ 0, offsetof(struct spec_data, arg_count), sizeof(uint32_t) },
{ 1, offsetof(struct spec_data, arg_indirect), sizeof(VkBool32) },
};
memset(meta_predicate_ops, 0, sizeof(*meta_predicate_ops));
push_constant_range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
push_constant_range.offset = 0;
push_constant_range.size = sizeof(struct vkd3d_predicate_command_args);
if ((vr = vkd3d_meta_create_pipeline_layout(device, 0, NULL, 1,
&push_constant_range, &meta_predicate_ops->vk_command_pipeline_layout)) < 0)
return hresult_from_vk_result(vr);
push_constant_range.size = sizeof(struct vkd3d_predicate_resolve_args);
if ((vr = vkd3d_meta_create_pipeline_layout(device, 0, NULL, 1,
&push_constant_range, &meta_predicate_ops->vk_resolve_pipeline_layout)) < 0)
return hresult_from_vk_result(vr);
spec_info.mapEntryCount = ARRAY_SIZE(spec_map);
spec_info.pMapEntries = spec_map;
spec_info.dataSize = sizeof(struct spec_data);
for (i = 0; i < ARRAY_SIZE(spec_data); i++)
{
spec_info.pData = &spec_data[i];
if ((vr = vkd3d_meta_create_compute_pipeline(device, sizeof(cs_predicate_command), cs_predicate_command,
meta_predicate_ops->vk_command_pipeline_layout, &spec_info, &meta_predicate_ops->vk_command_pipelines[i])) < 0)
goto fail;
meta_predicate_ops->data_sizes[i] = spec_data[i].arg_count * sizeof(uint32_t);
}
if ((vr = vkd3d_meta_create_compute_pipeline(device, sizeof(cs_resolve_predicate), cs_resolve_predicate,
meta_predicate_ops->vk_resolve_pipeline_layout, &spec_info, &meta_predicate_ops->vk_resolve_pipeline)) < 0)
goto fail;
return S_OK;
fail:
vkd3d_predicate_ops_cleanup(meta_predicate_ops, device);
return hresult_from_vk_result(vr);
}
void vkd3d_predicate_ops_cleanup(struct vkd3d_predicate_ops *meta_predicate_ops,
struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
size_t i;
for (i = 0; i < VKD3D_PREDICATE_COMMAND_COUNT; i++)
VK_CALL(vkDestroyPipeline(device->vk_device, meta_predicate_ops->vk_command_pipelines[i], NULL));
VK_CALL(vkDestroyPipeline(device->vk_device, meta_predicate_ops->vk_resolve_pipeline, NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_predicate_ops->vk_command_pipeline_layout, NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_predicate_ops->vk_resolve_pipeline_layout, NULL));
}
void vkd3d_meta_get_predicate_pipeline(struct vkd3d_meta_ops *meta_ops,
enum vkd3d_predicate_command_type command_type, struct vkd3d_predicate_command_info *info)
{
const struct vkd3d_predicate_ops *predicate_ops = &meta_ops->predicate;
info->vk_pipeline_layout = predicate_ops->vk_command_pipeline_layout;
info->vk_pipeline = predicate_ops->vk_command_pipelines[command_type];
info->data_size = predicate_ops->data_sizes[command_type];
}
HRESULT vkd3d_execute_indirect_ops_init(struct vkd3d_execute_indirect_ops *meta_indirect_ops,
struct d3d12_device *device)
{
VkPushConstantRange push_constant_range;
VkResult vr;
int rc;
if ((rc = pthread_mutex_init(&meta_indirect_ops->mutex, NULL)))
return hresult_from_errno(rc);
push_constant_range.offset = 0;
push_constant_range.size = sizeof(struct vkd3d_execute_indirect_args);
push_constant_range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
if ((vr = vkd3d_meta_create_pipeline_layout(device, 0, NULL, 1,
&push_constant_range, &meta_indirect_ops->vk_pipeline_layout)) < 0)
{
pthread_mutex_destroy(&meta_indirect_ops->mutex);
return hresult_from_vk_result(vr);
}
meta_indirect_ops->pipelines_count = 0;
meta_indirect_ops->pipelines_size = 0;
meta_indirect_ops->pipelines = NULL;
return S_OK;
}
struct vkd3d_meta_execute_indirect_spec_constant_data
{
struct vkd3d_shader_debug_ring_spec_constants constants;
uint32_t workgroup_size_x;
};
HRESULT vkd3d_meta_get_execute_indirect_pipeline(struct vkd3d_meta_ops *meta_ops,
uint32_t patch_command_count, struct vkd3d_execute_indirect_info *info)
{
struct vkd3d_meta_execute_indirect_spec_constant_data execute_indirect_spec_constants;
VkSpecializationMapEntry map_entry[VKD3D_SHADER_DEBUG_RING_SPEC_INFO_MAP_ENTRIES + 1];
struct vkd3d_execute_indirect_ops *meta_indirect_ops = &meta_ops->execute_indirect;
struct vkd3d_shader_debug_ring_spec_info debug_ring_info;
VkSpecializationInfo spec;
HRESULT hr = S_OK;
VkResult vr;
bool debug;
size_t i;
int rc;
if ((rc = pthread_mutex_lock(&meta_indirect_ops->mutex)))
{
ERR("Failed to lock mutex, error %d.\n", rc);
return hresult_from_errno(rc);
}
for (i = 0; i < meta_indirect_ops->pipelines_count; i++)
{
if (meta_indirect_ops->pipelines[i].workgroup_size_x == patch_command_count)
{
info->vk_pipeline_layout = meta_indirect_ops->vk_pipeline_layout;
info->vk_pipeline = meta_indirect_ops->pipelines[i].vk_pipeline;
goto out;
}
}
debug = meta_ops->device->debug_ring.active;
/* If we have debug ring, we can dump indirect command buffer data to the ring as well.
* Vital for debugging broken execute indirect data with templates. */
if (debug)
{
vkd3d_shader_debug_ring_init_spec_constant(meta_ops->device, &debug_ring_info,
0 /* Reserve this hash for internal debug streams. */);
memset(&execute_indirect_spec_constants, 0, sizeof(execute_indirect_spec_constants));
execute_indirect_spec_constants.constants = debug_ring_info.constants;
execute_indirect_spec_constants.workgroup_size_x = patch_command_count;
memcpy(map_entry, debug_ring_info.map_entries, sizeof(debug_ring_info.map_entries));
map_entry[VKD3D_SHADER_DEBUG_RING_SPEC_INFO_MAP_ENTRIES].constantID = 4;
map_entry[VKD3D_SHADER_DEBUG_RING_SPEC_INFO_MAP_ENTRIES].offset =
offsetof(struct vkd3d_meta_execute_indirect_spec_constant_data, workgroup_size_x);
map_entry[VKD3D_SHADER_DEBUG_RING_SPEC_INFO_MAP_ENTRIES].size = sizeof(patch_command_count);
spec.pMapEntries = map_entry;
spec.pData = &execute_indirect_spec_constants;
spec.mapEntryCount = ARRAY_SIZE(map_entry);
spec.dataSize = sizeof(execute_indirect_spec_constants);
}
else
{
map_entry[0].constantID = 0;
map_entry[0].offset = 0;
map_entry[0].size = sizeof(patch_command_count);
spec.pMapEntries = map_entry;
spec.pData = &patch_command_count;
spec.mapEntryCount = 1;
spec.dataSize = sizeof(patch_command_count);
}
vkd3d_array_reserve((void**)&meta_indirect_ops->pipelines, &meta_indirect_ops->pipelines_size,
meta_indirect_ops->pipelines_count + 1, sizeof(*meta_indirect_ops->pipelines));
meta_indirect_ops->pipelines[meta_indirect_ops->pipelines_count].workgroup_size_x = patch_command_count;
vr = vkd3d_meta_create_compute_pipeline(meta_ops->device,
debug ? sizeof(cs_execute_indirect_patch_debug_ring) : sizeof(cs_execute_indirect_patch),
debug ? cs_execute_indirect_patch_debug_ring : cs_execute_indirect_patch,
meta_indirect_ops->vk_pipeline_layout, &spec,
&meta_indirect_ops->pipelines[meta_indirect_ops->pipelines_count].vk_pipeline);
if (vr)
{
hr = hresult_from_vk_result(vr);
goto out;
}
info->vk_pipeline_layout = meta_indirect_ops->vk_pipeline_layout;
info->vk_pipeline = meta_indirect_ops->pipelines[meta_indirect_ops->pipelines_count].vk_pipeline;
meta_indirect_ops->pipelines_count++;
out:
pthread_mutex_unlock(&meta_indirect_ops->mutex);
return hr;
}
void vkd3d_execute_indirect_ops_cleanup(struct vkd3d_execute_indirect_ops *meta_indirect_ops,
struct d3d12_device *device)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
size_t i;
for (i = 0; i < meta_indirect_ops->pipelines_count; i++)
VK_CALL(vkDestroyPipeline(device->vk_device, meta_indirect_ops->pipelines[i].vk_pipeline, NULL));
VK_CALL(vkDestroyPipelineLayout(device->vk_device, meta_indirect_ops->vk_pipeline_layout, NULL));
pthread_mutex_destroy(&meta_indirect_ops->mutex);
}
HRESULT vkd3d_meta_ops_init(struct vkd3d_meta_ops *meta_ops, struct d3d12_device *device)
{
HRESULT hr;
@ -1371,28 +823,8 @@ HRESULT vkd3d_meta_ops_init(struct vkd3d_meta_ops *meta_ops, struct d3d12_device
if (FAILED(hr = vkd3d_copy_image_ops_init(&meta_ops->copy_image, device)))
goto fail_copy_image_ops;
if (FAILED(hr = vkd3d_swapchain_ops_init(&meta_ops->swapchain, device)))
goto fail_swapchain_ops;
if (FAILED(hr = vkd3d_query_ops_init(&meta_ops->query, device)))
goto fail_query_ops;
if (FAILED(hr = vkd3d_predicate_ops_init(&meta_ops->predicate, device)))
goto fail_predicate_ops;
if (FAILED(hr = vkd3d_execute_indirect_ops_init(&meta_ops->execute_indirect, device)))
goto fail_execute_indirect_ops;
return S_OK;
fail_execute_indirect_ops:
vkd3d_predicate_ops_cleanup(&meta_ops->predicate, device);
fail_predicate_ops:
vkd3d_query_ops_cleanup(&meta_ops->query, device);
fail_query_ops:
vkd3d_swapchain_ops_cleanup(&meta_ops->swapchain, device);
fail_swapchain_ops:
vkd3d_copy_image_ops_cleanup(&meta_ops->copy_image, device);
fail_copy_image_ops:
vkd3d_clear_uav_ops_cleanup(&meta_ops->clear_uav, device);
fail_clear_uav_ops:
@ -1403,10 +835,6 @@ fail_common:
HRESULT vkd3d_meta_ops_cleanup(struct vkd3d_meta_ops *meta_ops, struct d3d12_device *device)
{
vkd3d_execute_indirect_ops_cleanup(&meta_ops->execute_indirect, device);
vkd3d_predicate_ops_cleanup(&meta_ops->predicate, device);
vkd3d_query_ops_cleanup(&meta_ops->query, device);
vkd3d_swapchain_ops_cleanup(&meta_ops->swapchain, device);
vkd3d_copy_image_ops_cleanup(&meta_ops->copy_image, device);
vkd3d_clear_uav_ops_cleanup(&meta_ops->clear_uav, device);
vkd3d_meta_ops_common_cleanup(&meta_ops->common, device);

View File

@ -18,9 +18,6 @@
#include "vkd3d_platform.h"
#include <assert.h>
#include <stdio.h>
#if defined(__linux__)
# include <dlfcn.h>
@ -155,44 +152,4 @@ bool vkd3d_get_program_name(char program_name[VKD3D_PATH_MAX])
return false;
}
#endif
#if defined(_WIN32)
bool vkd3d_get_env_var(const char *name, char *value, size_t value_size)
{
DWORD len;
assert(value);
assert(value_size > 0);
len = GetEnvironmentVariableA(name, value, value_size);
if (len > 0 && len <= value_size)
{
return true;
}
value[0] = '\0';
return false;
}
#else
bool vkd3d_get_env_var(const char *name, char *value, size_t value_size)
{
const char *env_value;
assert(value);
assert(value_size > 0);
if ((env_value = getenv(name)))
{
snprintf(value, value_size, "%s", env_value);
return true;
}
value[0] = '\0';
return false;
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,6 @@ static vkd3d_shader_hash_t renderdoc_capture_shader_hash;
static uint32_t *renderdoc_capture_counts;
static size_t renderdoc_capture_counts_count;
static bool vkd3d_renderdoc_is_active;
static bool vkd3d_renderdoc_global_capture;
static void vkd3d_renderdoc_init_capture_count_list(const char *env)
{
@ -50,13 +49,6 @@ static void vkd3d_renderdoc_init_capture_count_list(const char *env)
uint32_t count;
char *endp;
if (strcmp(env, "-1") == 0)
{
INFO("Doing one big capture of the entire lifetime of a device.\n");
vkd3d_renderdoc_global_capture = true;
return;
}
while (*env != '\0')
{
errno = 0;
@ -71,7 +63,7 @@ static void vkd3d_renderdoc_init_capture_count_list(const char *env)
renderdoc_capture_counts_count + 1,
sizeof(*renderdoc_capture_counts));
INFO("Enabling automatic RenderDoc capture of submit #%u.\n", count);
TRACE("Enabling automatic RenderDoc capture of submit #%u.\n", count);
renderdoc_capture_counts[renderdoc_capture_counts_count++] = count;
if (*endp == ',')
@ -100,9 +92,9 @@ static bool vkd3d_renderdoc_enable_submit_counter(uint32_t counter)
static void vkd3d_renderdoc_init_once(void)
{
char counts[VKD3D_PATH_MAX];
pRENDERDOC_GetAPI get_api;
char env[VKD3D_PATH_MAX];
const char *counts;
const char *env;
#ifdef _WIN32
HMODULE renderdoc;
@ -112,27 +104,27 @@ static void vkd3d_renderdoc_init_once(void)
void *fn_ptr;
#endif
vkd3d_get_env_var("VKD3D_AUTO_CAPTURE_SHADER", env, sizeof(env));
vkd3d_get_env_var("VKD3D_AUTO_CAPTURE_COUNTS", counts, sizeof(counts));
env = getenv("VKD3D_AUTO_CAPTURE_SHADER");
counts = getenv("VKD3D_AUTO_CAPTURE_COUNTS");
if (strlen(env) == 0 && strlen(counts) == 0)
if (!env && !counts)
{
WARN("VKD3D_AUTO_CAPTURE_SHADER or VKD3D_AUTO_CAPTURE_COUNTS is not set, RenderDoc auto capture will not be enabled.\n");
return;
}
if (strlen(counts) == 0)
if (!counts)
WARN("VKD3D_AUTO_CAPTURE_COUNTS is not set, will assume that only the first submission is captured.\n");
if (strlen(env) > 0)
if (env)
renderdoc_capture_shader_hash = strtoull(env, NULL, 16);
if (renderdoc_capture_shader_hash)
INFO("Enabling RenderDoc capture for shader hash: %016"PRIx64".\n", renderdoc_capture_shader_hash);
TRACE("Enabling RenderDoc capture for shader hash: %016"PRIx64".\n", renderdoc_capture_shader_hash);
else
INFO("Enabling RenderDoc capture for all shaders.\n");
TRACE("Enabling RenderDoc capture for all shaders.\n");
if (strlen(counts) > 0)
if (counts)
vkd3d_renderdoc_init_capture_count_list(counts);
else
{
@ -188,11 +180,6 @@ bool vkd3d_renderdoc_active(void)
return vkd3d_renderdoc_is_active;
}
bool vkd3d_renderdoc_global_capture_enabled(void)
{
return vkd3d_renderdoc_global_capture;
}
bool vkd3d_renderdoc_should_capture_shader_hash(vkd3d_shader_hash_t hash)
{
return (renderdoc_capture_shader_hash == hash) || (renderdoc_capture_shader_hash == 0);
@ -203,12 +190,9 @@ bool vkd3d_renderdoc_begin_capture(void *instance)
static uint32_t overall_counter;
uint32_t counter;
if (!vkd3d_renderdoc_global_capture)
{
counter = vkd3d_atomic_uint32_increment(&overall_counter, vkd3d_memory_order_relaxed) - 1;
if (!vkd3d_renderdoc_enable_submit_counter(counter))
return false;
}
counter = vkd3d_atomic_uint32_increment(&overall_counter, vkd3d_memory_order_relaxed) - 1;
if (!vkd3d_renderdoc_enable_submit_counter(counter))
return false;
if (renderdoc_api)
renderdoc_api->StartFrameCapture(RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(instance), NULL);
@ -231,14 +215,11 @@ void vkd3d_renderdoc_command_list_check_capture(struct d3d12_command_list *list,
{
unsigned int i;
if (vkd3d_renderdoc_global_capture_enabled())
return;
if (vkd3d_renderdoc_active() && state)
{
if (state->vk_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE)
{
if (vkd3d_renderdoc_should_capture_shader_hash(state->compute.code.meta.hash))
if (vkd3d_renderdoc_should_capture_shader_hash(state->compute.meta.hash))
{
WARN("Triggering RenderDoc capture for this command list.\n");
list->debug_capture = true;
@ -248,7 +229,7 @@ void vkd3d_renderdoc_command_list_check_capture(struct d3d12_command_list *list,
{
for (i = 0; i < state->graphics.stage_count; i++)
{
if (vkd3d_renderdoc_should_capture_shader_hash(state->graphics.code[i].meta.hash))
if (vkd3d_renderdoc_should_capture_shader_hash(state->graphics.stage_meta[i].hash))
{
WARN("Triggering RenderDoc capture for this command list.\n");
list->debug_capture = true;
@ -265,9 +246,6 @@ bool vkd3d_renderdoc_command_queue_begin_capture(struct d3d12_command_queue *com
VkDebugUtilsLabelEXT capture_label;
bool debug_capture;
if (vkd3d_renderdoc_global_capture_enabled())
return false;
debug_capture = vkd3d_renderdoc_begin_capture(command_queue->device->vkd3d_instance->vk_instance);
if (debug_capture && !vkd3d_renderdoc_loaded_api())
{
@ -295,9 +273,6 @@ void vkd3d_renderdoc_command_queue_end_capture(struct d3d12_command_queue *comma
const struct vkd3d_vk_device_procs *vk_procs = &command_queue->device->vk_procs;
VkDebugUtilsLabelEXT capture_label;
if (vkd3d_renderdoc_global_capture_enabled())
return;
if (!vkd3d_renderdoc_loaded_api())
{
/* Magic fallback which lets us bridge the Wine barrier over to Linux RenderDoc. */
@ -309,4 +284,4 @@ void vkd3d_renderdoc_command_queue_end_capture(struct d3d12_command_queue *comma
}
else
vkd3d_renderdoc_end_capture(command_queue->device->vkd3d_instance->vk_instance);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
int thread_id = int(gl_GlobalInvocationID.x);
if (thread_id < u_info.dst_extent.x)
imageStore(dst, u_info.dst_offset.x + thread_id, u_info.clear_value);
}
}

View File

@ -1,22 +0,0 @@
#version 450
layout(local_size_x = 128) in;
layout(binding = 0)
writeonly buffer dst_buf {
uint data[];
} dst;
layout(push_constant)
uniform u_info_t {
uvec4 clear_value;
ivec2 dst_offset;
ivec2 dst_extent;
} u_info;
void main() {
int thread_id = int(gl_GlobalInvocationID.x);
if (thread_id < u_info.dst_extent.x)
dst.data[u_info.dst_offset.x + thread_id] = u_info.clear_value.x;
}

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
int thread_id = int(gl_GlobalInvocationID.x);
if (thread_id < u_info.dst_extent.x)
imageStore(dst, u_info.dst_offset.x + thread_id, u_info.clear_value);
}
}

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
ivec3 thread_id = ivec3(gl_GlobalInvocationID);
if (thread_id.x < u_info.dst_extent.x)
imageStore(dst, ivec2(u_info.dst_offset.x + thread_id.x, thread_id.y), u_info.clear_value);
}
}

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
ivec3 thread_id = ivec3(gl_GlobalInvocationID);
if (thread_id.x < u_info.dst_extent.x)
imageStore(dst, ivec2(u_info.dst_offset.x + thread_id.x, thread_id.y), u_info.clear_value);
}
}

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
ivec3 thread_id = ivec3(gl_GlobalInvocationID);
if (thread_id.x < u_info.dst_extent.x)
imageStore(dst, u_info.dst_offset.x + thread_id.x, u_info.clear_value);
}
}

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
ivec3 thread_id = ivec3(gl_GlobalInvocationID);
if (thread_id.x < u_info.dst_extent.x)
imageStore(dst, u_info.dst_offset.x + thread_id.x, u_info.clear_value);
}
}

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
ivec3 thread_id = ivec3(gl_GlobalInvocationID);
if (all(lessThan(thread_id.xy, u_info.dst_extent.xy)))
imageStore(dst, ivec3(u_info.dst_offset.xy + thread_id.xy, thread_id.z), u_info.clear_value);
}
}

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
ivec3 thread_id = ivec3(gl_GlobalInvocationID);
if (all(lessThan(thread_id.xy, u_info.dst_extent.xy)))
imageStore(dst, ivec3(u_info.dst_offset.xy + thread_id.xy, thread_id.z), u_info.clear_value);
}
}

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
ivec3 thread_id = ivec3(gl_GlobalInvocationID);
if (all(lessThan(thread_id.xy, u_info.dst_extent.xy)))
imageStore(dst, u_info.dst_offset.xy + thread_id.xy, u_info.clear_value);
}
}

View File

@ -14,7 +14,7 @@ uniform u_info_t {
void main() {
ivec3 thread_id = ivec3(gl_GlobalInvocationID);
if (all(lessThan(thread_id.xy, u_info.dst_extent.xy)))
imageStore(dst, u_info.dst_offset.xy + thread_id.xy, u_info.clear_value);
}
}

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