mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-10-14 19:27:09 -04:00
Import pinned DXVK recipe prerequisite from PowerVR PR570
Copy only the standalone build recipe, source pin, BC-format prerequisite
and presentation-sync patch/check from wallentx/DroidDeck at d0f7264ea8.
Source: https://github.com/Droid-Deck/DroidDeck/pull/570
Preserve that proposal attribution; no Android app, compositor, managed
pack, private data or fork development history is imported.
This commit is contained in:
1 parent
de1a734fb5
commit
f08eedb3f6
5 files changed
+227
No files matched your search
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# CI component build; this does not change the APK or an installed Proton depot.
|
||||
set -euo pipefail
|
||||
root=$(cd "$(dirname "$0")/../.." && pwd)
|
||||
. "$root/tools/dxvk/source.env"
|
||||
mkdir -p "${1:?output directory required}"
|
||||
out=$(cd "$1" && pwd)
|
||||
work=$(mktemp -d)
|
||||
trap 'rm -rf "$work"' EXIT
|
||||
git init -q "$work/source"
|
||||
git -C "$work/source" fetch --depth=1 https://github.com/doitsujin/dxvk.git "$DXVK_REVISION"
|
||||
git -C "$work/source" checkout -q --detach FETCH_HEAD
|
||||
test "$(git -C "$work/source" rev-parse HEAD)" = "$DXVK_REVISION"
|
||||
git -C "$work/source" submodule update --init --recursive --depth=1
|
||||
for patch in "$root"/tools/dxvk/patches/*.patch; do
|
||||
git -C "$work/source" apply --check "$patch"
|
||||
git -C "$work/source" apply "$patch"
|
||||
done
|
||||
python3 "$root/tools/dxvk/check_present_sync.py" "$work/source/src/dxvk/dxvk_presenter.cpp"
|
||||
for arch in 32 64; do
|
||||
meson setup "$work/build$arch" "$work/source" --cross-file "$work/source/build-win$arch.txt" \
|
||||
--buildtype release --prefix "$out" --bindir "x$arch" --libdir "x$arch" -Db_ndebug=if-release --strip
|
||||
meson compile -C "$work/build$arch" -j 4
|
||||
meson install -C "$work/build$arch"
|
||||
done
|
||||
cp "$work/source/LICENSE" "$out/LICENSE"
|
||||
printf '%s\n' "$DXVK_REVISION" > "$out/source-commit"
|
||||
git -C "$work/source" submodule status --recursive > "$out/submodules.txt"
|
||||
git -C "$work/source" diff > "$out/downstream.patch"
|
||||
tar --exclude-vcs --zstd -cf "$out/source.tar.zst" -C "$work/source" .
|
||||
(cd "$out" && find x32 x64 -name '*.dll' -type f -print0 | sort -z | xargs -0 sha256sum > SHA256SUMS)
|
||||
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Replay asynchronous WSI ownership using the pinned presenter's actual selections.
|
||||
|
||||
This checks semaphore selection, not the full Vulkan presenter. Real Vulkan
|
||||
validation and device testing remain separate gates. Requires a native C++ compiler.
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
|
||||
def selection_code(source):
|
||||
match = re.search(
|
||||
r"// Return relevant Vulkan objects for the acquired image\s*"
|
||||
r"(?P<acquire>.*?)\s*m_presentPending = true;", source, re.S)
|
||||
wait = re.search(r"info\.pWaitSemaphores\s*=.*?;", source, re.S)
|
||||
if not match or not wait:
|
||||
raise ValueError("unsupported pinned presenter layout")
|
||||
return match["acquire"], wait[0]
|
||||
|
||||
|
||||
HARNESS = r'''
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
using VkSemaphore = uint64_t;
|
||||
struct Sync { VkSemaphore acquire, present; };
|
||||
struct Info { const VkSemaphore* pWaitSemaphores; };
|
||||
|
||||
struct Presenter {
|
||||
std::vector<Sync> m_semaphores;
|
||||
std::vector<unsigned> m_images = {0, 1, 2, 3};
|
||||
unsigned m_frameIndex = 0, m_imageIndex = 0;
|
||||
bool m_hasSwapchainMaintenance1;
|
||||
explicit Presenter(bool maintenance): m_hasSwapchainMaintenance1(maintenance) {
|
||||
for (unsigned i = 0; i < (maintenance ? 4u : 8u); ++i)
|
||||
m_semaphores.push_back({100 + i, 1 + i});
|
||||
}
|
||||
Sync acquire() {
|
||||
Sync sync{}; unsigned image;
|
||||
ACQUIRE_SELECTION
|
||||
(void)image;
|
||||
return sync;
|
||||
}
|
||||
VkSemaphore present() {
|
||||
auto& currSync = m_semaphores.at(m_frameIndex);
|
||||
Info info{};
|
||||
PRESENT_SELECTION
|
||||
return *info.pWaitSemaphores;
|
||||
}
|
||||
};
|
||||
|
||||
int replay(bool maintenance) {
|
||||
Presenter p(maintenance);
|
||||
std::array<VkSemaphore, 4> outstandingByImage{};
|
||||
std::array<VkSemaphore, 4> outstandingByFence{};
|
||||
// Deliberately delay reacquisition of image 2 beyond a full frame-ring cycle.
|
||||
const std::array<unsigned, 21> imageOrder = {
|
||||
2,0,3,0,1,3,0,1,1,2,3,1,0,3,2,2,0,1,3,0,2
|
||||
};
|
||||
for (unsigned iteration = 0; iteration < 200; ++iteration) {
|
||||
p.m_imageIndex = imageOrder[iteration % imageOrder.size()];
|
||||
if (maintenance) {
|
||||
// The existing fence path waits this frame's previous present fence.
|
||||
const auto completed = outstandingByFence.at(p.m_frameIndex);
|
||||
for (auto& pending : outstandingByImage)
|
||||
if (pending == completed) pending = 0;
|
||||
}
|
||||
// Acquisition and its GPU wait complete the last present of THIS image.
|
||||
outstandingByImage.at(p.m_imageIndex) = 0;
|
||||
const auto signal = p.acquire().present;
|
||||
const auto wait = p.present();
|
||||
if (signal != wait) {
|
||||
std::fprintf(stderr, "FAIL: render signal differs from present wait\n");
|
||||
return 2;
|
||||
}
|
||||
for (auto pending : outstandingByImage) {
|
||||
if (pending == signal) {
|
||||
std::fprintf(stderr, "FAIL: semaphore reused before presentation completion at frame %u\n", iteration);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
outstandingByImage.at(p.m_imageIndex) = signal;
|
||||
if (maintenance) outstandingByFence.at(p.m_frameIndex) = signal;
|
||||
p.m_frameIndex = (p.m_frameIndex + 1) % p.m_semaphores.size();
|
||||
}
|
||||
std::printf("PASS: %s, 200 out-of-order acquisitions\n", maintenance ? "present-fence path" : "no-present-fence path");
|
||||
return 0;
|
||||
}
|
||||
int main() {
|
||||
if (int status = replay(false)) return status;
|
||||
return replay(true);
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("source", type=Path, help="pinned dxvk_presenter.cpp, after patching")
|
||||
args = parser.parse_args()
|
||||
acquire, present = selection_code(args.source.read_text())
|
||||
code = HARNESS.replace("ACQUIRE_SELECTION", acquire).replace("PRESENT_SELECTION", present)
|
||||
with tempfile.TemporaryDirectory(prefix="dxvk-present-sync-") as directory:
|
||||
cpp = Path(directory) / "replay.cpp"
|
||||
exe = Path(directory) / "replay"
|
||||
cpp.write_text(code)
|
||||
subprocess.run([os.environ.get("HOST_CXX", "c++"), "-std=c++17", "-Wall", "-Wextra", str(cpp), "-o", str(exe)], check=True)
|
||||
return subprocess.run([str(exe)]).returncode
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,53 @@
|
||||
diff --git a/src/dxvk/dxvk_device_info.cpp b/src/dxvk/dxvk_device_info.cpp
|
||||
index db09fba..8e9a76e 100644
|
||||
--- a/src/dxvk/dxvk_device_info.cpp
|
||||
+++ b/src/dxvk/dxvk_device_info.cpp
|
||||
@@ -118,6 +118,17 @@ namespace dxvk {
|
||||
initQueueProperties(instance, adapter, deviceInfo);
|
||||
initMemoryProperties(instance, adapter);
|
||||
|
||||
+ m_hasBcFormats = true;
|
||||
+ for (uint32_t value = VK_FORMAT_BC1_RGBA_UNORM_BLOCK; value <= VK_FORMAT_BC7_SRGB_BLOCK; value++) {
|
||||
+ VkFormatProperties properties = { };
|
||||
+ vk->vkGetPhysicalDeviceFormatProperties(adapter, VkFormat(value), &properties);
|
||||
+ constexpr VkFormatFeatureFlags required = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
|
||||
+ | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT
|
||||
+ | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
|
||||
+ if ((properties.optimalTilingFeatures & required) != required)
|
||||
+ m_hasBcFormats = false;
|
||||
+ }
|
||||
+
|
||||
disableUnusedFeatures(instance, safeMode);
|
||||
|
||||
enableFeaturesAndExtensions();
|
||||
@@ -785,6 +796,9 @@ namespace dxvk {
|
||||
}
|
||||
}
|
||||
|
||||
+ if (!m_hasBcFormats)
|
||||
+ return std::string("Device does not support the BC formats required by Direct3D");
|
||||
+
|
||||
if (!m_featuresEnabled.extDescriptorHeap.descriptorHeap && m_properties.core.properties.limits.maxPushConstantsSize < MaxTotalPushDataSize)
|
||||
return str::format("Device does not support ", MaxTotalPushDataSize, " of push data");
|
||||
|
||||
@@ -886,7 +900,7 @@ namespace dxvk {
|
||||
ENABLE_FEATURE(core.features, shaderResourceResidency, false),
|
||||
ENABLE_FEATURE(core.features, shaderResourceMinLod, false),
|
||||
ENABLE_FEATURE(core.features, tessellationShader, false),
|
||||
- ENABLE_FEATURE(core.features, textureCompressionBC, true),
|
||||
+ ENABLE_FEATURE(core.features, textureCompressionBC, false),
|
||||
ENABLE_FEATURE(core.features, variableMultisampleRate, false),
|
||||
ENABLE_FEATURE(core.features, vertexPipelineStoresAndAtomics, false),
|
||||
ENABLE_FEATURE(core.features, wideLines, false),
|
||||
diff --git a/src/dxvk/dxvk_device_info.h b/src/dxvk/dxvk_device_info.h
|
||||
index 0a55f90..8bbc770 100644
|
||||
--- a/src/dxvk/dxvk_device_info.h
|
||||
+++ b/src/dxvk/dxvk_device_info.h
|
||||
@@ -394,6 +394,7 @@ namespace dxvk {
|
||||
|
||||
DxvkDeviceQueueMapping m_queueMapping = { };
|
||||
|
||||
+ bool m_hasBcFormats = false;
|
||||
bool m_hasMeshShader = false;
|
||||
bool m_hasFmask = false;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
diff --git a/src/dxvk/dxvk_presenter.cpp b/src/dxvk/dxvk_presenter.cpp
|
||||
index 643f7c5..4dc8c4d 100644
|
||||
--- a/src/dxvk/dxvk_presenter.cpp
|
||||
+++ b/src/dxvk/dxvk_presenter.cpp
|
||||
@@ -161,6 +161,10 @@ namespace dxvk {
|
||||
|
||||
// Return relevant Vulkan objects for the acquired image
|
||||
sync = m_semaphores.at(m_frameIndex);
|
||||
+ // Without a present fence, reacquiring this image is the only guarantee
|
||||
+ // that its previous presentation has consumed the wait semaphore.
|
||||
+ if (!m_hasSwapchainMaintenance1)
|
||||
+ sync.present = m_semaphores.at(m_imageIndex).present;
|
||||
image = m_images.at(m_imageIndex);
|
||||
|
||||
m_presentPending = true;
|
||||
@@ -239,7 +243,9 @@ namespace dxvk {
|
||||
|
||||
VkPresentInfoKHR info = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
|
||||
info.waitSemaphoreCount = 1;
|
||||
- info.pWaitSemaphores = &currSync.present;
|
||||
+ info.pWaitSemaphores = m_hasSwapchainMaintenance1
|
||||
+ ? &currSync.present
|
||||
+ : &m_semaphores.at(m_imageIndex).present;
|
||||
info.swapchainCount = 1;
|
||||
info.pSwapchains = &m_swapchain;
|
||||
info.pImageIndices = &m_imageIndex;
|
||||
@@ -0,0 +1 @@
|
||||
DXVK_REVISION=25ca63f17f34bdc05a39873ee63907d3cbbfa030
|
||||
Reference in new issue
Block a user