...
 
Commits (1303)
......@@ -9,7 +9,10 @@ assignees: ''
Please describe your issue as accurately as possible. If you run into a problem with a binary release, make sure to test with latest `master` as well.
**Important:** When reporting an issue with a specific game or application, such as crashes or rendering issues, please include log files and a D3D11 Apitrace (see https://github.com/apitrace/apitrace) so that the issue can be reproduced. In order to create a trace, run `wine apitrace.exe trace -a dxgi YOURGAME.exe`. DO NOT use DXVK together with apitrace!
**Important:** When reporting an issue with a specific game or application, such as crashes or rendering issues, please include log files and a D3D11/D3D9 Apitrace (see https://github.com/apitrace/apitrace) so that the issue can be reproduced.
In order to create a trace for **D3D11/D3D10**: Run `wine apitrace.exe trace -a dxgi YOURGAME.exe`.
In order to create a trace for **D3D9**: Follow https://github.com/Joshua-Ashton/d9vk/wiki/Making-a-Trace.
DO NOT use DXVK together with apitrace!
### Software information
Name of the game, settings used etc.
......@@ -24,5 +27,6 @@ Name of the game, settings used etc.
- Put a link here
### Log files
- d3d9.log:
- d3d11.log:
- dxgi.log:
dxvk:
script:
- chmod +x package-release.sh
- ./package-release.sh release build --no-package
artifacts:
name: "dxvk-${CI_COMMIT_REF_NAME}.${CI_COMMIT_SHA}"
paths:
d9vk:
script:
- chmod +x package-release.sh
- ./package-release.sh release build --no-package
artifacts:
name: "d9vk-${CI_COMMIT_REF_NAME}.${CI_COMMIT_SHA}"
paths:
- build/dxvk-release
\ No newline at end of file
......@@ -6,6 +6,7 @@
# Supported values: True, False
# dxgi.deferSurfaceCreation = False
# d3d9.deferSurfaceCreation = False
# Enforce a stricter maximum frame latency. Overrides the application
......@@ -15,6 +16,7 @@
# Supported values : 0 - 16
# dxgi.maxFrameLatency = 0
# d3d9.maxFrameLatency = 0
# Override PCI vendor and device IDs reported to the application. Can
......@@ -25,6 +27,9 @@
# dxgi.customDeviceId = 0000
# dxgi.customVendorId = 0000
# d3d9.customDeviceId = 0000
# d3d9.customVendorId = 0000
# Report Nvidia GPUs as AMD GPUs by default. This is enabled by default
# to work around issues with NVAPI, but may cause issues in some games.
......@@ -60,7 +65,8 @@
#
# Supported values: Any non-negative number
# dxgi.syncInterval = -1
# dxgi.syncInterval = -1
# d3d9.presentInterval = -1
# Performs range check on dynamically indexed constant buffers in shaders.
......@@ -115,6 +121,7 @@
# Supported values: Any number between 0 and 16
# d3d11.samplerAnisotropy = -1
# d3d9.samplerAnisotropy = -1
# Replaces NaN outputs from fragment shaders with zeroes for floating
......@@ -179,3 +186,106 @@
# ignored. The syntax is identical.
# dxvk.hud =
# Reported shader model
#
# The shader model to state that we support in the device
# capabilities that the applicatation queries.
#
# Supported values:
# - 1: Shader Model 1
# - 2: Shader Model 2
# - 3: Shader Model 3
# d3d9.shaderModel = 3
# Evict Managed on Unlock
#
# Decides whether we should evict managed resources from
# system memory when they are unlocked entirely.
#
# Supported values:
# - True, False: Always enable / disable
# d3d9.evictManagedOnUnlock = False
# DPI Awareness
#
# Decides whether we should call SetProcessDPIAware on device
# creation. Helps avoid upscaling blur in modern Windows on
# Hi-DPI screens/devices.
#
# Supported values:
# - True, False: Always enable / disable
# d3d9.dpiAware = True
# Strict Constant Copies
#
# Decides whether we should always copy defined constants to
# the UBO when relative addresssing is used, or only when the
# relative addressing starts a defined constant.
#
# Supported values:
# - True, False: Always enable / disable
# d3d9.strictConstantCopies = False
# Strict Pow
#
# Decides whether we have an opSelect for handling pow(0,0) = 0
# otherwise it becomes undefined.
#
# Supported values:
# - True, False: Always enable / disable
# d3d9.strictPow = True
# Lenient Clear
#
# Decides whether or not we fastpath clear anyway if we are close enough to
# clearing a full render target.
#
# Supported values:
# - True, False: Always enable / disable
# d3d9.lenientClear = False
# Max available memory
#
# Changes the max initial value used in tracking and GetAvailableTextureMem
# Value in Megabytes
#
# Supported values:
# - Any int32_t
# d3d9.maxAvailableMemory = 4096
# Force enable/disable floating point quirk emulation
#
# Force toggle anything * 0 emulation
# Tristate
# Supported values:
# - True/False
# d3d9.floatEmulation =
# Enable dialog box mode
#
# Changes the default state of dialog box mode.
# *Disables* exclusive fullscreen when enabled.
#
# Supported values:
# - True, False: Always enable / disable
# d3d9.enableDialogMode = False
......@@ -38,6 +38,7 @@ if dxvk_winelib
endif
wrc = find_program('wrc')
lib_vulkan = declare_dependency(link_args: [ '-lwinevulkan' ])
lib_d3d9 = declare_dependency(link_args: [ '-ld3d9' ])
lib_d3d11 = declare_dependency(link_args: [ '-ld3d11' ])
lib_dxgi = declare_dependency(link_args: [ '-ldxgi' ])
lib_d3dcompiler_43 = declare_dependency(link_args: [ '-L'+dxvk_library_path, '-ld3dcompiler_43' ])
......@@ -63,6 +64,7 @@ else
endif
lib_vulkan = dxvk_compiler.find_library('vulkan-1', dirs : dxvk_library_path)
lib_d3d9 = dxvk_compiler.find_library('d3d9')
lib_d3d11 = dxvk_compiler.find_library('d3d11')
lib_dxgi = dxvk_compiler.find_library('dxgi')
lib_d3dcompiler_43 = dxvk_compiler.find_library('d3dcompiler_43', dirs : dxvk_library_path)
......
option('enable_tests', type : 'boolean', value : false)
option('enable_dxgi', type : 'boolean', value : true, description: 'Build DXGI')
option('enable_d3d9', type : 'boolean', value : true, description: 'Build D3D9')
option('enable_d3d10', type : 'boolean', value : true, description: 'Build D3D10')
option('enable_d3d11', type : 'boolean', value : true, description: 'Build D3D11')
......@@ -172,6 +172,7 @@ if [ $with_dxgi -ne 0 ] || [ "$action" == "uninstall" ]; then
$action dxgi
fi
$action d3d9
$action d3d10
$action d3d10_1
$action d3d10core
......
......@@ -208,11 +208,25 @@ namespace dxvk {
if (m_presenter == nullptr)
CreatePresenter();
HRESULT hr = S_OK;
if (!m_presenter->hasSwapChain()) {
RecreateSwapChain(vsync);
m_dirty = false;
}
if (!m_presenter->hasSwapChain())
hr = DXGI_STATUS_OCCLUDED;
if (m_device->getDeviceStatus() != VK_SUCCESS)
hr = DXGI_ERROR_DEVICE_RESET;
if ((PresentFlags & DXGI_PRESENT_TEST) || hr != S_OK)
return hr;
if (std::exchange(m_dirty, false))
RecreateSwapChain(vsync);
HRESULT hr = S_OK;
try {
PresentImage(SyncInterval);
} catch (const DxvkError& e) {
......@@ -220,14 +234,11 @@ namespace dxvk {
hr = E_FAIL;
}
if (m_device->getDeviceStatus() != VK_SUCCESS)
hr = DXGI_ERROR_DEVICE_RESET;
return hr;
}
void D3D11SwapChain::PresentImage(UINT SyncInterval) {
HRESULT D3D11SwapChain::PresentImage(UINT SyncInterval) {
Com<ID3D11DeviceContext> deviceContext = nullptr;
m_parent->GetImmediateContext(&deviceContext);
......@@ -242,11 +253,36 @@ namespace dxvk {
for (uint32_t i = 0; i < SyncInterval || i < 1; i++) {
SynchronizePresent();
if (!m_presenter->hasSwapChain())
return DXGI_STATUS_OCCLUDED;
// Presentation semaphores and WSI swap chain image
vk::PresenterInfo info = m_presenter->info();
vk::PresenterSync sync = m_presenter->getSyncSemaphores();
uint32_t imageIndex = 0;
VkResult status = m_presenter->acquireNextImage(
sync.acquire, VK_NULL_HANDLE, imageIndex);
while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) {
RecreateSwapChain(m_vsync);
if (!m_presenter->hasSwapChain())
return DXGI_STATUS_OCCLUDED;
info = m_presenter->info();
sync = m_presenter->getSyncSemaphores();
status = m_presenter->acquireNextImage(
sync.acquire, VK_NULL_HANDLE, imageIndex);
}
// Resolve back buffer if it is multisampled. We
// only have to do it only for the first frame.
m_context->beginRecording(
m_device->createCommandList());
// Resolve back buffer if it is multisampled. We
// only have to do it only for the first frame.
if (m_swapImageResolve != nullptr && i == 0) {
VkImageSubresourceLayers resolveSubresource;
resolveSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
......@@ -266,25 +302,6 @@ namespace dxvk {
resolveRegion, VK_FORMAT_UNDEFINED);
}
// Presentation semaphores and WSI swap chain image
vk::PresenterInfo info = m_presenter->info();
vk::PresenterSync sync = m_presenter->getSyncSemaphores();
uint32_t imageIndex = 0;
VkResult status = m_presenter->acquireNextImage(
sync.acquire, VK_NULL_HANDLE, imageIndex);
while (status != VK_SUCCESS && status != VK_SUBOPTIMAL_KHR) {
RecreateSwapChain(m_vsync);
info = m_presenter->info();
sync = m_presenter->getSyncSemaphores();
status = m_presenter->acquireNextImage(
sync.acquire, VK_NULL_HANDLE, imageIndex);
}
// Use an appropriate texture filter depending on whether
// the back buffer size matches the swap image size
bool fitSize = m_swapImage->info().extent.width == info.imageExtent.width
......@@ -341,6 +358,7 @@ namespace dxvk {
}
SignalFrameLatencyEvent();
return S_OK;
}
......
......@@ -135,7 +135,7 @@ namespace dxvk {
bool m_dirty = true;
bool m_vsync = true;
void PresentImage(UINT SyncInterval);
HRESULT PresentImage(UINT SyncInterval);
void SubmitPresent(
D3D11ImmediateContext* pContext,
......
LIBRARY D3D9.DLL
EXPORTS
Direct3DShaderValidatorCreate9 @ 24
PSGPError @ 25
PSGPSampleTexture @ 26
D3DPERF_BeginEvent @ 27
D3DPERF_EndEvent @ 28
D3DPERF_GetStatus @ 29
D3DPERF_QueryRepeatFrame @ 30
D3DPERF_SetMarker @ 31
D3DPERF_SetOptions @ 32
D3DPERF_SetRegion @ 33
DebugSetLevel @ 34
DebugSetMute @ 35
Direct3D9EnableMaximizedWindowedModeShim @ 36
Direct3DCreate9 @ 37
Direct3DCreate9Ex @ 38
@ stdcall Direct3DShaderValidatorCreate9()
@ stdcall PSGPError(ptr long long)
@ stdcall PSGPSampleTexture(ptr long ptr long ptr)
@ stdcall D3DPERF_BeginEvent(long wstr)
@ stdcall D3DPERF_EndEvent()
@ stdcall D3DPERF_GetStatus()
@ stdcall D3DPERF_QueryRepeatFrame()
@ stdcall D3DPERF_SetMarker(long wstr)
@ stdcall D3DPERF_SetOptions(long)
@ stdcall D3DPERF_SetRegion(long wstr)
@ stdcall DebugSetLevel()
@ stdcall DebugSetMute()
@ stdcall Direct3D9EnableMaximizedWindowedModeShim(long)
@ stdcall Direct3DCreate9(long)
@ stdcall Direct3DCreate9Ex(long ptr)
\ No newline at end of file
This diff is collapsed.
#pragma once
#include "d3d9_include.h"
#include "d3d9_options.h"
#include "d3d9_format.h"
#include "../dxvk/dxvk_adapter.h"
namespace dxvk {
class D3D9InterfaceEx;
class D3D9Adapter {
public:
D3D9Adapter(
D3D9InterfaceEx* pParent,
Rc<DxvkAdapter> Adapter,
UINT Ordinal);
HRESULT GetAdapterIdentifier(
DWORD Flags,
D3DADAPTER_IDENTIFIER9* pIdentifier);
HRESULT CheckDeviceType(
D3DDEVTYPE DevType,
D3D9Format AdapterFormat,
D3D9Format BackBufferFormat,
BOOL bWindowed);
HRESULT CheckDeviceFormat(
D3DDEVTYPE DeviceType,
D3D9Format AdapterFormat,
DWORD Usage,
D3DRESOURCETYPE RType,
D3D9Format CheckFormat);
HRESULT CheckDeviceMultiSampleType(
D3DDEVTYPE DeviceType,
D3D9Format SurfaceFormat,
BOOL Windowed,
D3DMULTISAMPLE_TYPE MultiSampleType,
DWORD* pQualityLevels);
HRESULT CheckDepthStencilMatch(
D3DDEVTYPE DeviceType,
D3D9Format AdapterFormat,
D3D9Format RenderTargetFormat,
D3D9Format DepthStencilFormat);
HRESULT CheckDeviceFormatConversion(
D3DDEVTYPE DeviceType,
D3D9Format SourceFormat,
D3D9Format TargetFormat);
HRESULT GetDeviceCaps(
D3DDEVTYPE DeviceType,
D3DCAPS9* pCaps);
HMONITOR GetMonitor();
UINT GetAdapterModeCountEx(CONST D3DDISPLAYMODEFILTER* pFilter);
HRESULT EnumAdapterModesEx(
const D3DDISPLAYMODEFILTER* pFilter,
UINT Mode,
D3DDISPLAYMODEEX* pMode);
HRESULT GetAdapterDisplayModeEx(
D3DDISPLAYMODEEX* pMode,
D3DDISPLAYROTATION* pRotation);
HRESULT GetAdapterLUID(LUID* pLUID);
UINT GetOrdinal() { return m_ordinal; }
Rc<DxvkAdapter> GetDXVKAdapter() { return m_adapter; }
D3D9_VK_FORMAT_MAPPING GetFormatMapping(
D3D9Format Format) const {
return m_d3d9Formats.GetFormatMapping(Format);
}
DxvkFormatInfo GetUnsupportedFormatInfo(
D3D9Format Format) const {
return m_d3d9Formats.GetUnsupportedFormatInfo(Format);
}
private:
HRESULT CheckDeviceVkFormat(
VkFormat Format,
DWORD Usage,
D3DRESOURCETYPE RType);
void CacheModes(D3D9Format Format);
D3D9InterfaceEx* m_parent;
Rc<DxvkAdapter> m_adapter;
UINT m_ordinal;
std::vector<D3DDISPLAYMODEEX> m_modes;
D3D9Format m_modeCacheFormat;
const D3D9VkFormatTable m_d3d9Formats;
};
}
\ No newline at end of file
#include "d3d9_buffer.h"
namespace dxvk {
////////////////////////
// D3D9VertexBuffer
////////////////////////
D3D9VertexBuffer::D3D9VertexBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc)
: D3D9VertexBufferBase( pDevice, pDesc ) { }
HRESULT STDMETHODCALLTYPE D3D9VertexBuffer::QueryInterface(
REFIID riid,
void** ppvObject) {
if (ppvObject == nullptr)
return E_POINTER;
*ppvObject = nullptr;
if (riid == __uuidof(IUnknown)
|| riid == __uuidof(IDirect3DResource9)
|| riid == __uuidof(IDirect3DVertexBuffer9)) {
*ppvObject = ref(this);
return S_OK;
}
Logger::warn("D3D9VertexBuffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
return E_NOINTERFACE;
}
D3DRESOURCETYPE STDMETHODCALLTYPE D3D9VertexBuffer::GetType() {
return D3DRTYPE_VERTEXBUFFER;
}
HRESULT STDMETHODCALLTYPE D3D9VertexBuffer::GetDesc(
D3DVERTEXBUFFER_DESC* pDesc) {
if (pDesc == nullptr)
return D3DERR_INVALIDCALL;
D3D9_BUFFER_DESC desc;
m_buffer.GetDesc(&desc);
pDesc->Format = static_cast<D3DFORMAT>(desc.Format);
pDesc->Type = desc.Type;
pDesc->Usage = desc.Usage;
pDesc->Pool = desc.Pool;
pDesc->Size = desc.Size;
pDesc->FVF = desc.FVF;
return D3D_OK;
}
//////////////////////
// D3D9IndexBuffer
//////////////////////
D3D9IndexBuffer::D3D9IndexBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc)
: D3D9IndexBufferBase( pDevice, pDesc ) { }
HRESULT STDMETHODCALLTYPE D3D9IndexBuffer::QueryInterface(
REFIID riid,
void** ppvObject) {
if (ppvObject == nullptr)
return E_POINTER;
*ppvObject = nullptr;
if (riid == __uuidof(IUnknown)
|| riid == __uuidof(IDirect3DResource9)
|| riid == __uuidof(IDirect3DIndexBuffer9)) {
*ppvObject = ref(this);
return S_OK;
}
Logger::warn("D3D9IndexBuffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
return E_NOINTERFACE;
}
D3DRESOURCETYPE STDMETHODCALLTYPE D3D9IndexBuffer::GetType() {
return D3DRTYPE_INDEXBUFFER;
}
HRESULT STDMETHODCALLTYPE D3D9IndexBuffer::GetDesc(
D3DINDEXBUFFER_DESC* pDesc) {
if (pDesc == nullptr)
return D3DERR_INVALIDCALL;
D3D9_BUFFER_DESC desc;
m_buffer.GetDesc(&desc);
pDesc->Format = static_cast<D3DFORMAT>(desc.Format);
pDesc->Type = desc.Type;
pDesc->Usage = desc.Usage;
pDesc->Pool = desc.Pool;
pDesc->Size = desc.Size;
return D3D_OK;
}
}
\ No newline at end of file
#pragma once
#include "d3d9_resource.h"
#include "d3d9_common_buffer.h"
namespace dxvk {
template <typename... Type>
class D3D9Buffer : public D3D9Resource<Type...> {
public:
D3D9Buffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc)
: D3D9Resource<Type...> ( pDevice )
, m_buffer ( pDevice, pDesc ) { }
HRESULT STDMETHODCALLTYPE Lock(
UINT OffsetToLock,
UINT SizeToLock,
void** ppbData,
DWORD Flags) final {
return m_buffer.Lock(
OffsetToLock,
SizeToLock,
ppbData,
Flags);
}
HRESULT STDMETHODCALLTYPE Unlock() final {
return m_buffer.Unlock();
}
D3D9CommonBuffer* GetCommonBuffer() {
return &m_buffer;
}
protected:
D3D9CommonBuffer m_buffer;
};
using D3D9VertexBufferBase = D3D9Buffer<IDirect3DVertexBuffer9>;
class D3D9VertexBuffer final : public D3D9VertexBufferBase {
public:
D3D9VertexBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc);
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject) final;
D3DRESOURCETYPE STDMETHODCALLTYPE GetType() final;
HRESULT STDMETHODCALLTYPE GetDesc(
D3DVERTEXBUFFER_DESC* pDesc) final;
};
using D3D9IndexBufferBase = D3D9Buffer<IDirect3DIndexBuffer9>;
class D3D9IndexBuffer final : public D3D9IndexBufferBase {
public:
D3D9IndexBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc);
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject) final;
D3DRESOURCETYPE STDMETHODCALLTYPE GetType() final;
HRESULT STDMETHODCALLTYPE GetDesc(
D3DINDEXBUFFER_DESC* pDesc) final;
};
template <typename T>
inline D3D9CommonBuffer* GetCommonBuffer(const T& pResource) {
return pResource != nullptr ? pResource->GetCommonBuffer() : nullptr;
}
}
\ No newline at end of file
#pragma once
#include "d3d9_include.h"
namespace dxvk::caps {
constexpr uint32_t MaxClipPlanes = 6;
constexpr uint32_t MaxSamplers = 16;
constexpr uint32_t MaxStreams = 16;
constexpr uint32_t MaxSimultaneousTextures = 8;
constexpr uint32_t MaxTextureBlendStages = MaxSimultaneousTextures;
constexpr uint32_t MaxSimultaneousRenderTargets = D3D_MAX_SIMULTANEOUS_RENDERTARGETS;
constexpr uint32_t MaxFloatConstantsVS = 256;
constexpr uint32_t MaxFloatConstantsPS = 224;
constexpr uint32_t MaxOtherConstants = 16;
constexpr uint32_t MaxFloatConstantsSoftware = 8192;
constexpr uint32_t MaxOtherConstantsSoftware = 2048;
constexpr uint32_t InputRegisterCount = 16;
constexpr uint32_t MaxTextureDimension = 16384;
constexpr uint32_t MaxMipLevels = 15;
constexpr uint32_t MaxSubresources = 15 * 6;
constexpr uint32_t MaxTransforms = 10 + 256;
constexpr uint32_t TextureStageCount = MaxSimultaneousTextures;
constexpr uint32_t MaxEnabledLights = 8;
}
\ No newline at end of file
#include "d3d9_common_buffer.h"
#include "d3d9_device.h"
#include "d3d9_util.h"
namespace dxvk {
D3D9CommonBuffer::D3D9CommonBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc)
: m_parent ( pDevice ), m_desc ( *pDesc ) {
m_buffer = CreateBuffer();
if (GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_BUFFER)
m_stagingBuffer = CreateStagingBuffer();
m_sliceHandle = GetMapBuffer()->getSliceHandle();
}
HRESULT D3D9CommonBuffer::Lock(
UINT OffsetToLock,
UINT SizeToLock,
void** ppbData,
DWORD Flags) {
return m_parent->LockBuffer(
this,
OffsetToLock,
SizeToLock,
ppbData,
Flags);
}
HRESULT D3D9CommonBuffer::Unlock() {
return m_parent->UnlockBuffer(this);
}
void D3D9CommonBuffer::GetDesc(
D3D9_BUFFER_DESC* pDesc) {
*pDesc = m_desc;
}
HRESULT D3D9CommonBuffer::ValidateBufferProperties(const D3D9_BUFFER_DESC* pDesc) {
if (pDesc->Size == 0)
return D3DERR_INVALIDCALL;
return D3D_OK;
}
Rc<DxvkBuffer> D3D9CommonBuffer::CreateBuffer() const {
DxvkBufferCreateInfo info;
info.size = m_desc.Size;
info.usage = 0;
info.stages = 0;
info.access = 0;
VkMemoryPropertyFlags memoryFlags = 0;
if (m_desc.Type == D3DRTYPE_VERTEXBUFFER) {
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 (m_parent->SupportsSWVP()) {
info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
info.stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
info.access |= VK_ACCESS_SHADER_WRITE_BIT;
}
}
else if (m_desc.Type == D3DRTYPE_INDEXBUFFER) {
info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
info.stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
info.access |= VK_ACCESS_INDEX_READ_BIT;
}
if (GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_DIRECT) {
info.stages |= VK_PIPELINE_STAGE_HOST_BIT;
info.access |= VK_ACCESS_HOST_WRITE_BIT;
if (!(m_desc.Usage & D3DUSAGE_WRITEONLY))
info.access |= VK_ACCESS_HOST_READ_BIT;
memoryFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
| VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}
else {
info.stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
info.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
info.access |= VK_ACCESS_TRANSFER_WRITE_BIT;
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}
return m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags);
}
Rc<DxvkBuffer> D3D9CommonBuffer::CreateStagingBuffer() const {
DxvkBufferCreateInfo info;
info.size = m_desc.Size;
info.stages = VK_PIPELINE_STAGE_HOST_BIT
| VK_PIPELINE_STAGE_TRANSFER_BIT;
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
info.access = VK_ACCESS_HOST_WRITE_BIT
| VK_ACCESS_TRANSFER_READ_BIT;
if (!(m_desc.Usage & D3DUSAGE_WRITEONLY))
info.access |= VK_ACCESS_HOST_READ_BIT;
VkMemoryPropertyFlags memoryFlags =
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
| VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
return m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags);
}
}
\ No newline at end of file
#pragma once
#include "../dxvk/dxvk_device.h"
#include "d3d9_device_child.h"
#include "d3d9_format.h"
namespace dxvk {
/**
* \brief Buffer map mode
*/
enum D3D9_COMMON_BUFFER_MAP_MODE {
D3D9_COMMON_BUFFER_MAP_MODE_BUFFER,
D3D9_COMMON_BUFFER_MAP_MODE_DIRECT
};
/**
* \brief Common buffer descriptor
*/
struct D3D9_BUFFER_DESC {
D3DRESOURCETYPE Type;
UINT Size;
DWORD Usage;
D3D9Format Format;
D3DPOOL Pool;
DWORD FVF;
};
/**
* \brief The type of buffer you want to use
*/
enum D3D9_COMMON_BUFFER_TYPE {
D3D9_COMMON_BUFFER_TYPE_MAPPING,
D3D9_COMMON_BUFFER_TYPE_STAGING,
D3D9_COMMON_BUFFER_TYPE_REAL
};
struct D3D9Range {
D3D9Range() { Clear(); }
D3D9Range(uint32_t min, uint32_t max)
: min(min), max(max) { }
bool IsDegenerate() { return min == max; }
void Conjoin(D3D9Range range) {
if (IsDegenerate())
*this = range;
else {
min = std::min(range.min, min);
max = std::max(range.max, max);
}
}
bool Overlaps(D3D9Range range) {
if (IsDegenerate())
return false;
return range.max > min && range.min < max;
}
void Clear() { min = 0; max = 0; }
uint32_t min = 0;
uint32_t max = 0;
};
class D3D9CommonBuffer {
static constexpr VkDeviceSize BufferSliceAlignment = 64;
public:
D3D9CommonBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc);
HRESULT Lock(
UINT OffsetToLock,
UINT SizeToLock,
void** ppbData,
DWORD Flags);
HRESULT Unlock();
void GetDesc(
D3D9_BUFFER_DESC* pDesc);
D3D9_COMMON_BUFFER_MAP_MODE GetMapMode() const {
return (m_desc.Pool == D3DPOOL_DEFAULT && (m_desc.Usage & (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY)))
? D3D9_COMMON_BUFFER_MAP_MODE_DIRECT
: D3D9_COMMON_BUFFER_MAP_MODE_BUFFER;
}
template <D3D9_COMMON_BUFFER_TYPE Type>
Rc<DxvkBuffer> GetBuffer() const {
if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_MAPPING)
return GetMapBuffer();
else if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_STAGING)
return GetStagingBuffer();
else //if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_REAL)
return GetRealBuffer();
}
template <D3D9_COMMON_BUFFER_TYPE Type>
DxvkBufferSlice GetBufferSlice() const {
return GetBufferSlice<Type>(0, m_desc.Size);
}
template <D3D9_COMMON_BUFFER_TYPE Type>
DxvkBufferSlice GetBufferSlice(VkDeviceSize offset) const {
return GetBufferSlice<Type>(offset, m_desc.Size - offset);
}
template <D3D9_COMMON_BUFFER_TYPE Type>
DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const {
return DxvkBufferSlice(GetBuffer<Type>(), offset, length);
}
DxvkBufferSliceHandle AllocMapSlice() {
return GetMapBuffer()->allocSlice();
}
DxvkBufferSliceHandle DiscardMapSlice() {
m_sliceHandle = GetMapBuffer()->allocSlice();
return m_sliceHandle;
}
DxvkBufferSliceHandle GetMappedSlice() const {
return m_sliceHandle;
}
DWORD GetMapFlags() const { return m_mapFlags; }
void SetMapFlags(DWORD Flags) { m_mapFlags = Flags; }
const D3D9_BUFFER_DESC* Desc() const {
return &m_desc;
}
static HRESULT ValidateBufferProperties(const D3D9_BUFFER_DESC* pDesc);
D3D9Range& LockRange() { return m_lockRange; }
D3D9Range& DirtyRange() { return m_dirtyRange; }
bool GetReadLocked() const { return m_readLocked; }
void SetReadLocked(bool state) { m_readLocked = state; }
uint32_t IncrementLockCount() { return ++m_lockCount; }
uint32_t DecrementLockCount() {
if (m_lockCount == 0)
return 0;
return --m_lockCount;
}
void MarkUploaded() { m_needsUpload = false; }
void MarkNeedsUpload() { m_needsUpload = true; }
bool NeedsUpload() const { return m_needsUpload; }
bool MarkLocked() {
bool locked = m_readLocked;
m_readLocked = true;
return locked;
}
private:
Rc<DxvkBuffer> CreateBuffer() const;
Rc<DxvkBuffer> CreateStagingBuffer() const;
Rc<DxvkBuffer> GetMapBuffer() const {
return m_stagingBuffer != nullptr ? m_stagingBuffer : m_buffer;
}
Rc<DxvkBuffer> GetStagingBuffer() const {
return m_stagingBuffer;
}
Rc<DxvkBuffer> GetRealBuffer() const {
return m_buffer;
}
D3D9DeviceEx* m_parent;
const D3D9_BUFFER_DESC m_desc;
DWORD m_mapFlags;
bool m_readLocked = false;
Rc<DxvkBuffer> m_buffer;
Rc<DxvkBuffer> m_stagingBuffer;
DxvkBufferSliceHandle m_sliceHandle;
D3D9Range m_lockRange;
D3D9Range m_dirtyRange;
uint32_t m_lockCount = 0;
bool m_needsUpload = false;
};
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
#pragma once
#include <cstdint>
#include "d3d9_caps.h"
namespace dxvk {
struct D3D9ConstantLayout {
uint32_t floatCount;
uint32_t intCount;
uint32_t boolCount;
uint32_t bitmaskCount;
uint32_t floatSize() const { return floatCount * 4 * sizeof(float); }
uint32_t intSize() const { return intCount * 4 * sizeof(int); }
uint32_t bitmaskSize() const { return bitmaskCount * 1 * sizeof(uint32_t); }
uint32_t floatOffset() const { return 0; }
uint32_t intOffset() const { return floatOffset() + floatSize(); }
uint32_t bitmaskOffset() const { return intOffset() + intSize(); }
uint32_t totalSize() const { return floatSize() + intSize() + bitmaskSize(); }
};
}
\ No newline at end of file
#pragma once
#include "d3d9_caps.h"
#include "../dxvk/dxvk_buffer.h"
#include "../dxso/dxso_isgn.h"
#include "../util/util_math.h"
#include "../util/util_vector.h"
#include <cstdint>
namespace dxvk {
enum class D3D9ConstantType {
Float,
Int,
Bool
};
// We make an assumption later based on the packing of this struct for copying.
struct D3D9ShaderConstantsVSSoftware {
Vector4 fConsts[caps::MaxFloatConstantsSoftware];
Vector4i iConsts[caps::MaxOtherConstantsSoftware];
uint32_t bConsts[caps::MaxOtherConstantsSoftware / 32];
};
struct D3D9ShaderConstantsVSHardware {
Vector4 fConsts[caps::MaxFloatConstantsVS];
Vector4i iConsts[caps::MaxOtherConstants];
uint32_t bConsts[1];
};
struct D3D9ShaderConstantsPS {
Vector4 fConsts[caps::MaxFloatConstantsPS];
Vector4i iConsts[caps::MaxOtherConstants];
uint32_t bConsts[1];
};
struct D3D9ConstantSets {
Rc<DxvkBuffer> buffer;
const DxsoShaderMetaInfo* meta = nullptr;
bool dirty = true;
};
}
\ No newline at end of file
#include "d3d9_cursor.h"
#include <utility>
namespace dxvk {
void D3D9Cursor::UpdateCursor(int X, int Y) {
::SetCursorPos(X, Y);
}
BOOL D3D9Cursor::ShowCursor(BOOL bShow) {
::SetCursor(bShow ? m_hCursor : nullptr);
return std::exchange(m_visible, bShow);
}
HRESULT D3D9Cursor::SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap) {
DWORD mask[32];
std::memset(mask, ~0, sizeof(mask));
ICONINFO info;
info.fIcon = FALSE;
info.xHotspot = XHotSpot;
info.yHotspot = YHotSpot;
info.hbmMask = ::CreateBitmap(HardwareCursorWidth, HardwareCursorHeight, 1, 1, mask);
info.hbmColor = ::CreateBitmap(HardwareCursorWidth, HardwareCursorHeight, 1, 32, &bitmap[0]);
if (m_hCursor != nullptr)
::DestroyCursor(m_hCursor);
m_hCursor = ::CreateIconIndirect(&info);
::DeleteObject(info.hbmMask);
::DeleteObject(info.hbmColor);
ShowCursor(m_visible);
return D3D_OK;
}
}
\ No newline at end of file
#pragma once
#include "d3d9_include.h"
namespace dxvk {
constexpr uint32_t HardwareCursorWidth = 32u;
constexpr uint32_t HardwareCursorHeight = 32u;
constexpr uint32_t HardwareCursorFormatSize = 4u;
constexpr uint32_t HardwareCursorPitch = HardwareCursorWidth * HardwareCursorFormatSize;
// Format Size of 4 bytes (ARGB)
using CursorBitmap = uint8_t[HardwareCursorHeight * HardwareCursorPitch];
class D3D9Cursor {
public:
void UpdateCursor(int X, int Y);
BOOL ShowCursor(BOOL bShow);
HRESULT SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap);
private:
BOOL m_visible = FALSE;
HCURSOR m_hCursor = nullptr;
};
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
#pragma once
#include "d3d9_include.h"
namespace dxvk {
class D3D9DeviceEx;
template <typename Base>
class D3D9DeviceChild : public ComObjectClamp<Base> {
public:
D3D9DeviceChild(D3D9DeviceEx* pDevice)
: m_parent( pDevice ) { }
ULONG STDMETHODCALLTYPE AddRef() {
uint32_t refCount = this->m_refCount++;
if (unlikely(!refCount)) {
this->AddRefPrivate();
GetDevice()->AddRef();
}
return refCount + 1;
}
ULONG STDMETHODCALLTYPE Release() {
uint32_t refCount = --this->m_refCount;
if (unlikely(!refCount)) {
auto* pDevice = GetDevice();
this->ReleasePrivate();
pDevice->Release();
}
return refCount;
}
HRESULT STDMETHODCALLTYPE GetDevice(IDirect3DDevice9** ppDevice) {
InitReturnPtr(ppDevice);
if (ppDevice == nullptr)
return D3DERR_INVALIDCALL;
*ppDevice = ref(GetDevice());
return D3D_OK;
}
IDirect3DDevice9Ex* GetDevice() {
return reinterpret_cast<IDirect3DDevice9Ex*>(m_parent);
}
D3D9DeviceEx* GetParent() {
return m_parent;
}
protected:
D3D9DeviceEx* m_parent;
};
}
\ No newline at end of file
This diff is collapsed.
#pragma once
#include "d3d9_include.h"
#include "d3d9_caps.h"
#include "../dxvk/dxvk_shader.h"
#include "../dxso/dxso_isgn.h"
#include <unordered_map>
#include <bitset>
namespace dxvk {
class D3D9DeviceEx;
class SpirvModule;
struct D3D9Options;
struct D3D9FogContext {
// General inputs...
bool IsPixel;
bool RangeFog;
uint32_t RenderState;
uint32_t vPos;
uint32_t vFog;
uint32_t oColor;
bool HasFogInput;
};
struct D3D9FixedFunctionOptions {
D3D9FixedFunctionOptions(const D3D9Options* options);
bool invariantPosition;
};
// Returns new oFog if VS
// Returns new oColor if PS
uint32_t DoFixedFunctionFog(SpirvModule& spvModule, const D3D9FogContext& fogCtx);
// Returns a render state block
uint32_t SetupRenderStateBlock(SpirvModule& spvModule);
struct D3D9PointSizeInfoVS {
uint32_t defaultValue;
uint32_t min;
uint32_t max;
};
// Default point size and point scale magic!
D3D9PointSizeInfoVS GetPointSizeInfoVS(SpirvModule& spvModule, uint32_t vPos, uint32_t vtx, uint32_t perVertPointSize, uint32_t rsBlock);
struct D3D9PointSizeInfoPS {
uint32_t isSprite;
};
D3D9PointSizeInfoPS GetPointSizeInfoPS(SpirvModule& spvModule, uint32_t rsBlock);
uint32_t GetPointCoord(SpirvModule& spvModule, std::vector<uint32_t>& entryPointInterfaces);
uint32_t GetSharedConstants(SpirvModule& spvModule);
constexpr uint32_t TCIOffset = 16;
constexpr uint32_t TCIMask = 0b111 << TCIOffset;
enum D3D9FF_VertexBlendMode {
D3D9FF_VertexBlendMode_Disabled,
D3D9FF_VertexBlendMode_Normal,
D3D9FF_VertexBlendMode_Tween,
};
struct D3D9FFShaderKeyVSData {
union {
struct {
uint32_t TexcoordIndices : 24;
uint32_t HasPositionT : 1;
uint32_t HasColor0 : 1; // Diffuse
uint32_t HasColor1 : 1; // Specular
uint32_t HasPointSize : 1;
uint32_t UseLighting : 1;
uint32_t NormalizeNormals : 1;
uint32_t LocalViewer : 1;
uint32_t RangeFog : 1;
uint32_t TexcoordFlags : 24;
uint32_t DiffuseSource : 2;
uint32_t AmbientSource : 2;
uint32_t SpecularSource : 2;
uint32_t EmissiveSource : 2;
uint32_t TransformFlags : 24;
uint32_t LightCount : 4;
uint32_t TexcoordDeclMask : 24;
uint32_t HasFog : 1;
uint32_t VertexBlendMode : 2;
uint32_t VertexBlendIndexed : 1;
uint32_t VertexBlendCount : 3;
} Contents;
uint32_t Primitive[4];
};
};
struct D3D9FFShaderKeyVS {
D3D9FFShaderKeyVS() {
// memcmp safety
std::memset(&Data, 0, sizeof(Data));
}
D3D9FFShaderKeyVSData Data;
};
constexpr uint32_t TextureArgCount = 3;
struct D3D9FFShaderStage {
union {
struct {
uint32_t ColorOp : 5;
uint32_t ColorArg0 : 6;
uint32_t ColorArg1 : 6;
uint32_t ColorArg2 : 6;
uint32_t AlphaOp : 5;
uint32_t AlphaArg0 : 6;
uint32_t AlphaArg1 : 6;
uint32_t AlphaArg2 : 6;
uint32_t Type : 2;
uint32_t ResultIsTemp : 1;
uint32_t Projected : 1;
uint32_t ProjectedCount : 3;
// Included in here, read from Stage 0 for packing reasons
// Affects all stages.
uint32_t GlobalSpecularEnable : 1;
uint32_t GlobalFlatShade : 1;
} Contents;
uint32_t Primitive[2];
};
};
struct D3D9FFShaderKeyFS {
D3D9FFShaderKeyFS() {
// memcmp safety
std::memset(Stages, 0, sizeof(Stages));