Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
aaf342e
[vulkan] null out surface handle after destroySurface (2.2)
pythonlover02 Jul 7, 2026
1902c6d
[vulkan] getSupportedFormats: aggregate init + explicit exclusive-FS …
pythonlover02 Jul 7, 2026
1c5196d
[vulkan] getSupportedPresentModes: aggregate init + explicit exclusiv…
pythonlover02 Jul 7, 2026
725d6ba
[vulkan] aggregate-init VkPresentInfoKHR in presentImage (2.2)
pythonlover02 Jul 7, 2026
99ba34b
[vulkan] guard recreateSwapChain against a null surface, keep surface…
pythonlover02 Jul 7, 2026
0169eaa
[util] guard wine console output behind _WIN32 in Logger::emitMsg (2.…
pythonlover02 Jul 7, 2026
8108528
[util] guard wine console check behind _WIN32 in Logger::getFileName …
pythonlover02 Jul 7, 2026
6564e5b
[dxso] zero-init DxsoRegisterPointer via aggregate init in emitGetOpe…
pythonlover02 Jul 7, 2026
267a69d
[dxso] zero-init DxsoRegisterPointer via aggregate init in emitGetOpe…
pythonlover02 Jul 7, 2026
f526c4d
[dxvk] yet another small rewrite of dyasync
pythonlover02 Jul 7, 2026
7c202b1
[dxso] read usedRTs after finalize() so SM1 r0->oC0 write is counted …
pythonlover02 Jul 7, 2026
4f8f295
[dxbc] mark immediate constant buffer NonWritable (2.5.3)
pythonlover02 Jul 7, 2026
1506166
[dxbc] mark sample position array NonWritable (2.7.1)
pythonlover02 Jul 7, 2026
c03f8a4
[dxbc] use NaN-safe opNClamp for HS tess factor clamp (2.7.1)
pythonlover02 Jul 7, 2026
3e63024
[dxbc] use NaN-safe opNClamp for depth output clamp (2.7.1)
pythonlover02 Jul 7, 2026
95b6861
[dxbc] throw on unhandled shader stage in emitInit (2.6.2)
pythonlover02 Jul 7, 2026
8c036fc
[dxbc] guard setDebugName against null name in emitNewBuiltinVariable…
pythonlover02 Jul 7, 2026
2fbd2fb
[dxbc] decode EvalSnapped offset as signed 1/16px fixed point (2.7.1)
pythonlover02 Jul 7, 2026
c5d2bb2
[dxbc] treat multisampled images as single-LOD in emitQueryTextureLod…
pythonlover02 Jul 7, 2026
958649d
[dxbc] zero resinfo size when queried LOD is out of bounds (2.7.1)
pythonlover02 Jul 7, 2026
70a1a46
[dxbc] only use precise FFma for mad/dfma when instruction is marked …
pythonlover02 Jul 7, 2026
91586b9
[dxbc] compute dot product as explicit NoContraction accumulation (2.…
pythonlover02 Jul 7, 2026
d24cf89
[spirv] add SpirvCodeBuffer::append(SpirvInstruction) overload (3.0)
pythonlover02 Jul 7, 2026
fe1fd8a
[spirv] delegate SpirvModule::newVar to newVarInit (2.7.1)
pythonlover02 Jul 7, 2026
ae32528
[spirv] add missing change for SpirvCodeBuffer::append(SpirvInstructi…
pythonlover02 Jul 7, 2026
5067424
[dxgi] lock m_lockBuffer during SetSourceSize, aggregate-init region …
pythonlover02 Jul 8, 2026
f96e969
[dxgi] delegate DxgiOutput::GetFrameStatistics to the active swap cha…
pythonlover02 Jul 8, 2026
206fad4
[d3d11] tag SO counter buffer with a debug name (3.0)
pythonlover02 Jul 8, 2026
f5d19ec
[d3d11] clear DEVICE_LOCAL bit when forcing cached host-visible memor…
pythonlover02 Jul 8, 2026
2057b03
[d3d11] whitelist usage flags and add dedicated storage-image path in…
pythonlover02 Jul 8, 2026
a11affa
[d3d11] reject geometry-shader-with-stream-output creation when trans…
pythonlover02 Jul 8, 2026
8380035
[d3d11] drop unused immediate context lookup in D3D11GDISurface::Crea…
pythonlover02 Jul 8, 2026
c4920a7
[d3d11] zero entire D3D11_MAPPED_SUBRESOURCE on Map failure paths in …
pythonlover02 Jul 8, 2026
4d1420b
[d3d11] read device limits via properties() in GetTimestampQueryFrequ…
pythonlover02 Jul 8, 2026
6e6b395
[d3d11] guard against null ppParentResource in D3D11DXGISurface::GetR…
pythonlover02 Jul 8, 2026
3e8c346
[d3d11] dedupe repeat logging (3.0)
pythonlover02 Jul 8, 2026
982deb3
[d3d11] revert tag SO counter buffer with a debug name (3.0)
pythonlover02 Jul 8, 2026
251094e
[d3d9] clear DEVICE_LOCAL bit when forcing cached host-visible buffer…
pythonlover02 Jul 8, 2026
bf3bcc1
[d3d9] read device limits via properties() in GetTimestampQueryFreque…
pythonlover02 Jul 8, 2026
3c89948
[d3d9] mark alpha-test state dirty when render target 0 changes (2.2)
pythonlover02 Jul 8, 2026
164a966
[d3d9] use ShouldRecord() consistently in BeginStateBlock (3.0)
pythonlover02 Jul 8, 2026
777a33b
[d3d9] skip redundant FlushCsChunk in SynchronizeCsThread (3.0)
pythonlover02 Jul 8, 2026
7a5dc1d
[d3d9] guard GetBackBuffer against empty back-buffer list after a fai…
pythonlover02 Jul 8, 2026
25cc553
[d3d9] write output value in GetLastPresentCount stub (3.0)
pythonlover02 Jul 8, 2026
26f41f2
[d3d9] offer both RGBA and BGRA surface formats for 32-bit swap chain…
pythonlover02 Jul 8, 2026
138350e
[d3d9] log failure of D3DKMTCreateDCFromMemory in Surface::GetDC (2.5.1)
pythonlover02 Jul 8, 2026
b59fd1d
[d3d9] pick stencil-less D32_SFLOAT fallback when D24S8 lacks stencil…
pythonlover02 Jul 8, 2026
8de1733
[d3d9] drop readback marking from mip generation (GPU-only operation)…
pythonlover02 Jul 8, 2026
3c7fa17
[d3d9] CheckDeviceFormat: reject unknown adapter format, use IsDepthS…
pythonlover02 Jul 8, 2026
7bc2d29
[d3d9] accept non-vendor FourCC formats as conversion sources (3.0)
pythonlover02 Jul 8, 2026
c877ccd
[d3d9] validate box bounds and clear output in Volume::LockBox (3.0)
pythonlover02 Jul 8, 2026
7591b1c
[d3d9] lock device around debug label emission in UserDefinedAnnotati…
pythonlover02 Jul 8, 2026
cf94f6f
[dxvk, d3d9, d3d11] Port low latency frame pacing from netborg-afps/d…
pythonlover02 Jul 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ A huge thank-you to the following contributors for their invaluable help:
- [Device Filter](#device-filter)
- [State Cache](#state-cache)
- [Shader Compilation (dyasync)](#shader-compilation-dyasync)
- [Frame Pacing (low-latency mode)](#frame-pacing-low-latency-mode)
- [Debugging](#debugging)
- [Debugging](#debugging)
- [Troubleshooting](#troubleshooting)

Expand Down Expand Up @@ -178,6 +180,21 @@ Dyasync can be disabled by setting `dxvk.enableDyasync = False` in `dxvk.conf`,

`DXVK_ALL_CORES=1` overrides the default way cores are assigned for shader compilation. By default, DXVK-Sarek uses roughly half the available CPU cores for background compilation, leaving the rest free for the game. On CPUs with weak per-core performance that rely on all cores for good throughput, this may cause longer loading times. With `DXVK_ALL_CORES=1`, all available cores are used for both the game and shader compilation. This may cause brief unresponsiveness while compiling shaders but can improve the overall experience on such hardware.

## Frame Pacing (low-latency mode)

DXVK-Sarek includes an optional frame pacing mode adapted from and inspired by [netborg-afps/dxvk-low-latency](https://github.com/netborg-afps/dxvk-low-latency). It is not a direct port: that project relies on per submission GPU timing and an asynchronous presenter that upstream DXVK has but Sarek Vulkan 1.1/1.2-targeted presenter does not, so the mechanism here has been adapted to what Sarek can actually observe.

The `dxvk.framePace` option in `dxvk.conf` (or the `DXVK_FRAME_PACE` environment variable) controls it:

- `"max-frame-latency"` (default) is Sarek's existing, unchanged behaviour. Frame `i` wont start until frame `(i-1)-x` has finished, where `x` is `dxgi.maxFrameLatency` / `d3d9.maxFrameLatency`.
- `"low-latency"` forces the effective frame latency down to the minimum needed for forward progress, and makes a best-effort prediction of when the previous frame will finish (based on a rolling average of recent frame durations) to reduce unnecessary CPU wake-up jitter. The prediction is never load-bearing for correctness; a wrong guess costs microseconds, not a broken frame.
- `"min-latency"` forces the same minimal frame latency without the predictive sleep. Lowest possible latency, usually at a noticeable fps cost.

`dxvk.lowLatencyOffset` fine-tunes `"low-latency"` mode: positive values (in microseconds) delay a frame's predicted start slightly, negative values start it earlier. Clamped to `-10000`..`10000`, defaults to `0`.

> [!NOTE]
> Because Sarek presenter has no per-submission GPU progress telemetry the way upstream DXVK's does, `"low-latency"` and `"min-latency"` currently share the same underlying latency-reduction mechanism rather than being two fully distinct algorithms. There's also no VRR-aware pacing mode and no HUD latency display yet, both of which the upstream project has.

## Debugging

The following environment variables can be used for debugging:
Expand Down
70 changes: 36 additions & 34 deletions src/d3d11/d3d11_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "../dxvk/dxvk_data.h"

namespace dxvk {

D3D11Buffer::D3D11Buffer(
D3D11Device* pDevice,
const D3D11_BUFFER_DESC* pDesc)
Expand All @@ -20,19 +20,19 @@ namespace dxvk {
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
info.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT;

if (pDesc->BindFlags & D3D11_BIND_VERTEX_BUFFER) {
info.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
info.access |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
}

if (pDesc->BindFlags & D3D11_BIND_INDEX_BUFFER) {
info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
info.access |= VK_ACCESS_INDEX_READ_BIT;
}

if (pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER) {
info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
info.stages |= m_parent->GetEnabledShaderStages();
Expand All @@ -41,28 +41,28 @@ namespace dxvk {
if (m_parent->GetOptions()->constantBufferRangeCheck)
info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
}

if (pDesc->BindFlags & D3D11_BIND_SHADER_RESOURCE) {
info.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
info.stages |= m_parent->GetEnabledShaderStages();
info.access |= VK_ACCESS_SHADER_READ_BIT;
}

if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT) {
info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
info.stages |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
info.access |= VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT;
}

if (pDesc->BindFlags & D3D11_BIND_UNORDERED_ACCESS) {
info.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
info.stages |= m_parent->GetEnabledShaderStages();
info.access |= VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
}

if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS) {
info.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
info.stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
Expand All @@ -80,27 +80,27 @@ namespace dxvk {
if (pDesc->BindFlags & D3D11_BIND_STREAM_OUTPUT)
m_soCounter = CreateSoCounterBuffer();
}


D3D11Buffer::~D3D11Buffer() {

}


HRESULT STDMETHODCALLTYPE D3D11Buffer::QueryInterface(REFIID riid, void** ppvObject) {
if (ppvObject == nullptr)
return E_POINTER;

*ppvObject = nullptr;

if (riid == __uuidof(IUnknown)
|| riid == __uuidof(ID3D11DeviceChild)
|| riid == __uuidof(ID3D11Resource)
|| riid == __uuidof(ID3D11Buffer)) {
*ppvObject = ref(this);
return S_OK;
}

if (riid == __uuidof(ID3D10DeviceChild)
|| riid == __uuidof(ID3D10Resource)
|| riid == __uuidof(ID3D10Buffer)) {
Expand All @@ -115,36 +115,36 @@ namespace dxvk {
*ppvObject = ref(&m_resource);
return S_OK;
}

Logger::warn("D3D11Buffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
return E_NOINTERFACE;
}


UINT STDMETHODCALLTYPE D3D11Buffer::GetEvictionPriority() {
return DXGI_RESOURCE_PRIORITY_NORMAL;
}


void STDMETHODCALLTYPE D3D11Buffer::SetEvictionPriority(UINT EvictionPriority) {
static bool s_errorShown = false;

if (!std::exchange(s_errorShown, true))
Logger::warn("D3D11Buffer::SetEvictionPriority: Stub");
}


void STDMETHODCALLTYPE D3D11Buffer::GetType(D3D11_RESOURCE_DIMENSION* pResourceDimension) {
*pResourceDimension = D3D11_RESOURCE_DIMENSION_BUFFER;
}


void STDMETHODCALLTYPE D3D11Buffer::GetDesc(D3D11_BUFFER_DESC* pDesc) {
*pDesc = m_desc;
}


bool D3D11Buffer::CheckViewCompatibility(
UINT BindFlags,
DXGI_FORMAT Format) const {
Expand Down Expand Up @@ -173,7 +173,7 @@ namespace dxvk {
// We don't support tiled resources
if (pDesc->MiscFlags & (D3D11_RESOURCE_MISC_TILE_POOL | D3D11_RESOURCE_MISC_TILED))
return E_INVALIDARG;

// Constant buffer size must be a multiple of 16
if ((pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER)
&& (pDesc->ByteWidth & 0xF))
Expand All @@ -185,7 +185,7 @@ namespace dxvk {
|| (pDesc->StructureByteStride == 0)
|| (pDesc->StructureByteStride & 0x3)))
return E_INVALIDARG;

// Basic validation for raw buffers
if ((pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
&& (!(pDesc->BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS))))
Expand All @@ -194,10 +194,10 @@ namespace dxvk {
// Mip generation obviously doesn't work for buffers
if (pDesc->MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS)
return E_INVALIDARG;

if (!(pDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED))
pDesc->StructureByteStride = 0;

return S_OK;
}

Expand All @@ -212,7 +212,7 @@ namespace dxvk {

VkMemoryPropertyFlags D3D11Buffer::GetMemoryFlags() const {
VkMemoryPropertyFlags memoryFlags = 0;

switch (m_desc.Usage) {
case D3D11_USAGE_IMMUTABLE:
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
Expand All @@ -231,26 +231,27 @@ namespace dxvk {
memoryFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}
break;

case D3D11_USAGE_DYNAMIC:
memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;

if (m_desc.BindFlags)
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
break;

case D3D11_USAGE_STAGING:
memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
break;
}

bool useCached = (m_parent->GetOptions()->cachedDynamicResources == ~0u)
|| (m_parent->GetOptions()->cachedDynamicResources & m_desc.BindFlags);

if ((memoryFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && useCached) {
memoryFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
memoryFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
}
Expand All @@ -276,6 +277,7 @@ namespace dxvk {
| VK_ACCESS_INDIRECT_COMMAND_READ_BIT
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
| VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT;

return device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}

Expand All @@ -285,7 +287,7 @@ namespace dxvk {
? D3D11_COMMON_BUFFER_MAP_MODE_DIRECT
: D3D11_COMMON_BUFFER_MAP_MODE_NONE;
}


D3D11Buffer* GetCommonBuffer(ID3D11Resource* pResource) {
D3D11_RESOURCE_DIMENSION dimension = D3D11_RESOURCE_DIMENSION_UNKNOWN;
Expand Down
6 changes: 3 additions & 3 deletions src/d3d11/d3d11_context_def.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ namespace dxvk {
: MapImage (pResource, Subresource, &mapInfo);

if (unlikely(FAILED(status))) {
pMappedResource->pData = nullptr;
*pMappedResource = D3D11_MAPPED_SUBRESOURCE();
return status;
}

Expand All @@ -214,7 +214,7 @@ namespace dxvk {
auto entry = FindMapEntry(pResource, Subresource);

if (unlikely(!entry)) {
pMappedResource->pData = nullptr;
*pMappedResource = D3D11_MAPPED_SUBRESOURCE();
return D3D11_ERROR_DEFERRED_CONTEXT_MAP_WITHOUT_INITIAL_DISCARD;
}

Expand All @@ -223,7 +223,7 @@ namespace dxvk {
return S_OK;
} else {
// Not allowed on deferred contexts
pMappedResource->pData = nullptr;
*pMappedResource = D3D11_MAPPED_SUBRESOURCE();
return E_INVALIDARG;
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/d3d11/d3d11_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,8 @@ namespace dxvk {
InitReturnPtr(ppGeometryShader);
D3D11CommonShader module;

if (!m_dxvkDevice->features().extTransformFeedback.transformFeedback)
return DXGI_ERROR_INVALID_CALL;

// Zero-init some counterss so that we can increment
// them while walking over the stream output entries
Expand Down
25 changes: 11 additions & 14 deletions src/d3d11/d3d11_gdi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "../util/util_gdi.h"

namespace dxvk {

D3D11GDISurface::D3D11GDISurface(
ID3D11Resource* pResource,
UINT Subresource)
Expand Down Expand Up @@ -33,7 +33,7 @@ namespace dxvk {

if (D3DKMTCreateDCFromMemory(&desc))
Logger::err(str::format("D3D11: Failed to create GDI DC"));

m_hdc = desc.hDc;
m_hbitmap = desc.hBitmap;
}
Expand All @@ -49,16 +49,16 @@ namespace dxvk {
D3DKMTDestroyDCFromMemory(&desc);
}


HRESULT D3D11GDISurface::Acquire(BOOL Discard, HDC* phdc) {
if (!phdc)
return E_INVALIDARG;

*phdc = nullptr;

if (m_acquired)
return DXGI_ERROR_INVALID_CALL;

if (!Discard) {
// Create a staging resource that we can map
if (!m_readback && FAILED(CreateReadbackResource())) {
Expand Down Expand Up @@ -92,13 +92,13 @@ namespace dxvk {

context->Unmap(m_readback, 0);
}

m_acquired = true;
*phdc = m_hdc;
return S_OK;
}


HRESULT D3D11GDISurface::Release(const RECT* pDirtyRect) {
if (!m_acquired)
return DXGI_ERROR_INVALID_CALL;
Expand Down Expand Up @@ -140,7 +140,7 @@ namespace dxvk {
sizeof(uint32_t) * tex->Width,
sizeof(uint32_t) * tex->Width * tex->Height);
}

m_acquired = false;
return S_OK;
}
Expand All @@ -149,11 +149,8 @@ namespace dxvk {
HRESULT D3D11GDISurface::CreateReadbackResource() {
auto tex = GetCommonTexture(m_resource);

Com<ID3D11Device> device;
Com<ID3D11DeviceContext> context;

Com<ID3D11Device> device;
m_resource->GetDevice(&device);
device->GetImmediateContext(&context);

D3D11_RESOURCE_DIMENSION dim = { };
m_resource->GetType(&dim);
Expand All @@ -172,7 +169,7 @@ namespace dxvk {
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;

ID3D11Texture1D* tex1D = nullptr;
HRESULT hr = device->CreateTexture1D(&desc, nullptr, &tex1D);
m_readback = tex1D;
Expand All @@ -191,7 +188,7 @@ namespace dxvk {
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;

ID3D11Texture2D* tex2D = nullptr;
HRESULT hr = device->CreateTexture2D(&desc, nullptr, &tex2D);
m_readback = tex2D;
Expand Down
Loading
Loading