...
 
Commits (1052)
......@@ -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:
......@@ -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
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')
LIBRARY D3D9.DLL
EXPORTS
Direct3DCreate9
Direct3DCreate9Ex
D3DPERF_BeginEvent
D3DPERF_EndEvent
D3DPERF_SetMarker
D3DPERF_SetRegion
D3DPERF_QueryRepeatFrame
D3DPERF_SetOptions
D3DPERF_GetStatus
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 Direct3DCreate9(long)
@ stdcall Direct3DShaderValidatorCreate9()
@ stdcall Direct3DCreate9Ex(long ptr)
@ stdcall PSGPError(ptr long long)
@ stdcall PSGPSampleTexture(ptr long ptr long ptr)
@ stdcall D3DPERF_BeginEvent(long wstr)
@ stdcall D3DPERF_EndEvent()
@ stdcall D3DPERF_SetMarker(long wstr)
@ stdcall D3DPERF_SetRegion(long wstr)
@ stdcall D3DPERF_GetStatus()
@ stdcall D3DPERF_QueryRepeatFrame()
@ stdcall D3DPERF_SetMarker(long wstr)
@ stdcall D3DPERF_SetOptions(long)
@ stdcall D3DPERF_GetStatus()
@ 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
......@@ -3,15 +3,16 @@
namespace dxvk {
////////////////////////
// Direct3DVertexBuffer9
// D3D9VertexBuffer
////////////////////////
Direct3DVertexBuffer9::Direct3DVertexBuffer9(
Direct3DDevice9Ex* pDevice,
D3D9VertexBuffer::D3D9VertexBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc)
: Direct3DVertexBuffer9Base ( pDevice, pDesc ) { }
: D3D9VertexBufferBase( pDevice, pDesc ) { }
HRESULT STDMETHODCALLTYPE Direct3DVertexBuffer9::QueryInterface(
HRESULT STDMETHODCALLTYPE D3D9VertexBuffer::QueryInterface(
REFIID riid,
void** ppvObject) {
if (ppvObject == nullptr)
......@@ -26,22 +27,24 @@ namespace dxvk {
return S_OK;
}
Logger::warn("Direct3DVertexBuffer9::QueryInterface: Unknown interface query");
Logger::warn("D3D9VertexBuffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
return E_NOINTERFACE;
}
D3DRESOURCETYPE STDMETHODCALLTYPE Direct3DVertexBuffer9::GetType() {
D3DRESOURCETYPE STDMETHODCALLTYPE D3D9VertexBuffer::GetType() {
return D3DRTYPE_VERTEXBUFFER;
}
HRESULT STDMETHODCALLTYPE Direct3DVertexBuffer9::GetDesc(
HRESULT STDMETHODCALLTYPE D3D9VertexBuffer::GetDesc(
D3DVERTEXBUFFER_DESC* pDesc) {
if (pDesc == nullptr)
return D3DERR_INVALIDCALL;
D3D9_BUFFER_DESC desc;
m_buffer->GetDesc(&desc);
m_buffer.GetDesc(&desc);
pDesc->Format = static_cast<D3DFORMAT>(desc.Format);
pDesc->Type = desc.Type;
......@@ -53,16 +56,19 @@ namespace dxvk {
return D3D_OK;
}
//////////////////////
//Direct3DIndexBuffer9
// D3D9IndexBuffer
//////////////////////
Direct3DIndexBuffer9::Direct3DIndexBuffer9(
Direct3DDevice9Ex* pDevice,
D3D9IndexBuffer::D3D9IndexBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc)
: Direct3DIndexBuffer9Base { pDevice, pDesc } {}
: D3D9IndexBufferBase( pDevice, pDesc ) { }
HRESULT STDMETHODCALLTYPE Direct3DIndexBuffer9::QueryInterface(
HRESULT STDMETHODCALLTYPE D3D9IndexBuffer::QueryInterface(
REFIID riid,
void** ppvObject) {
if (ppvObject == nullptr)
......@@ -77,22 +83,24 @@ namespace dxvk {
return S_OK;
}
Logger::warn("Direct3DIndexBuffer9::QueryInterface: Unknown interface query");
Logger::warn("D3D9IndexBuffer::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
return E_NOINTERFACE;
}
D3DRESOURCETYPE STDMETHODCALLTYPE Direct3DIndexBuffer9::GetType() {
D3DRESOURCETYPE STDMETHODCALLTYPE D3D9IndexBuffer::GetType() {
return D3DRTYPE_INDEXBUFFER;
}
HRESULT STDMETHODCALLTYPE Direct3DIndexBuffer9::GetDesc(
HRESULT STDMETHODCALLTYPE D3D9IndexBuffer::GetDesc(
D3DINDEXBUFFER_DESC* pDesc) {
if (pDesc == nullptr)
return D3DERR_INVALIDCALL;
D3D9_BUFFER_DESC desc;
m_buffer->GetDesc(&desc);
m_buffer.GetDesc(&desc);
pDesc->Format = static_cast<D3DFORMAT>(desc.Format);
pDesc->Type = desc.Type;
......
......@@ -7,22 +7,22 @@
namespace dxvk {
template <typename... Type>
class Direct3DBuffer9 : public Direct3DResource9<Type...> {
class D3D9Buffer : public D3D9Resource<Type...> {
public:
Direct3DBuffer9(
Direct3DDevice9Ex* pDevice,
D3D9Buffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc)
: Direct3DResource9<Type...>{ pDevice }
, m_buffer{ new Direct3DCommonBuffer9{ pDevice, pDesc } } {}
: D3D9Resource<Type...> ( pDevice )
, m_buffer ( pDevice, pDesc ) { }
HRESULT STDMETHODCALLTYPE Lock(
UINT OffsetToLock,
UINT SizeToLock,
void** ppbData,
DWORD Flags) final {
return m_buffer->Lock(
UINT OffsetToLock,
UINT SizeToLock,
void** ppbData,
DWORD Flags) final {
return m_buffer.Lock(
OffsetToLock,
SizeToLock,
ppbData,
......@@ -30,27 +30,27 @@ namespace dxvk {
}
HRESULT STDMETHODCALLTYPE Unlock() final {
return m_buffer->Unlock();
return m_buffer.Unlock();
}
Rc<Direct3DCommonBuffer9> GetCommonBuffer() {
return m_buffer;
D3D9CommonBuffer* GetCommonBuffer() {
return &m_buffer;
}
protected:
Rc<Direct3DCommonBuffer9> m_buffer;
D3D9CommonBuffer m_buffer;
};
using Direct3DVertexBuffer9Base = Direct3DBuffer9<IDirect3DVertexBuffer9>;
class Direct3DVertexBuffer9 final : public Direct3DVertexBuffer9Base {
using D3D9VertexBufferBase = D3D9Buffer<IDirect3DVertexBuffer9>;
class D3D9VertexBuffer final : public D3D9VertexBufferBase {
public:
Direct3DVertexBuffer9(
Direct3DDevice9Ex* pDevice,
D3D9VertexBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc);
HRESULT STDMETHODCALLTYPE QueryInterface(
......@@ -64,13 +64,13 @@ namespace dxvk {
};
using Direct3DIndexBuffer9Base = Direct3DBuffer9<IDirect3DIndexBuffer9>;
class Direct3DIndexBuffer9 final : public Direct3DIndexBuffer9Base {
using D3D9IndexBufferBase = D3D9Buffer<IDirect3DIndexBuffer9>;
class D3D9IndexBuffer final : public D3D9IndexBufferBase {
public:
Direct3DIndexBuffer9(
Direct3DDevice9Ex* pDevice,
D3D9IndexBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc);
HRESULT STDMETHODCALLTYPE QueryInterface(
......@@ -84,4 +84,9 @@ namespace dxvk {
};
template <typename T>
inline D3D9CommonBuffer* GetCommonBuffer(const T& pResource) {
return pResource != nullptr ? pResource->GetCommonBuffer() : nullptr;
}
}
\ No newline at end of file
This diff is collapsed.
#pragma once
#include "d3d9_include.h"
#include "d3d9_format.h"
namespace dxvk {
struct D3D9Options;
}
namespace dxvk::caps {
HRESULT checkDeviceFormat(
D3D9Format adapterFormat,
DWORD usage,
D3DRESOURCETYPE resourceType,
D3D9Format checkFormat);
HRESULT checkDepthStencilMatch(
D3D9Format AdapterFormat,
D3D9Format RenderTargetFormat,
D3D9Format DepthStencilFormat);
HRESULT checkDeviceFormatConversion(
D3D9Format srcFormat,
D3D9Format dstFormat);
HRESULT checkDeviceMultiSampleType(
D3D9Format SurfaceFormat,
BOOL Windowed,
D3DMULTISAMPLE_TYPE MultiSampleType,
DWORD* pQualityLevels);
HRESULT checkDeviceType(
D3D9Format adapterFormat,
D3D9Format backBufferFormat,
BOOL windowed);
HRESULT getDeviceCaps(const dxvk::D3D9Options& options, UINT adapter, D3DDEVTYPE type, D3DCAPS9* pCaps);
constexpr uint32_t MaxClipPlanes = 6;
constexpr uint32_t MaxSamplers = 16;
constexpr uint32_t MaxStreams = 16;
constexpr uint32_t MaxTextureBlendStages = 8;
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 MaxFloatConstants = 256;
constexpr uint32_t MaxOtherConstants = 16;
constexpr uint32_t MaxFloatConstantsSoftware = 8192;
constexpr uint32_t MaxOtherConstantsSoftware = 2048;
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 InputRegisterCount = 16;
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 {
Direct3DCommonBuffer9::Direct3DCommonBuffer9(
Direct3DDevice9Ex* pDevice,
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 = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
info.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_TRANSFER_WRITE_BIT;
info.usage = 0;
info.stages = 0;
info.access = 0;
if (pDesc->Type == D3DRTYPE_VERTEXBUFFER) {
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 (pDesc->Type == D3DRTYPE_INDEXBUFFER) {
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 (pDesc->Usage & D3DUSAGE_DYNAMIC) {
if (GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_DIRECT) {
info.stages |= VK_PIPELINE_STAGE_HOST_BIT;
info.access |= VK_ACCESS_HOST_WRITE_BIT;
if (!(pDesc->Usage & D3DUSAGE_WRITEONLY))
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;
VkMemoryPropertyFlags memoryFlags = GetMemoryFlagsForUsage(pDesc->Usage);
memoryFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
}
// Create the buffer and set the entire buffer slice as mapped,
// so that we only have to update it when invalidating the buffer
m_buffer = m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags);
m_mapped = m_buffer->getSliceHandle();
return m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags);
}
if (GetMapMode() == D3D9_COMMON_BUFFER_MAP_MODE_BUFFER) {
info.stages |= VK_PIPELINE_STAGE_HOST_BIT;
info.access |= VK_ACCESS_HOST_WRITE_BIT;
memoryFlags = GetMemoryFlagsForUsage(pDesc->Usage | D3DUSAGE_DYNAMIC);
memoryFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
Rc<DxvkBuffer> D3D9CommonBuffer::CreateStagingBuffer() const {
DxvkBufferCreateInfo info;
info.size = m_desc.Size;
info.stages = VK_PIPELINE_STAGE_HOST_BIT
| VK_PIPELINE_STAGE_TRANSFER_BIT;
m_stagingBuffer = m_parent->GetDXVKDevice()->createBuffer(info, memoryFlags);
m_mapped = m_stagingBuffer->getSliceHandle();
}
}
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
HRESULT Direct3DCommonBuffer9::Lock(
UINT OffsetToLock,
UINT SizeToLock,
void** ppbData,
DWORD Flags) {
return m_parent->LockBuffer(
this,
OffsetToLock,
SizeToLock,
ppbData,
Flags);
}
info.access = VK_ACCESS_HOST_WRITE_BIT
| VK_ACCESS_TRANSFER_READ_BIT;
HRESULT Direct3DCommonBuffer9::Unlock() {
return m_parent->UnlockBuffer(this);
}
if (!(m_desc.Usage & D3DUSAGE_WRITEONLY))
info.access |= VK_ACCESS_HOST_READ_BIT;
void Direct3DCommonBuffer9::GetDesc(
D3D9_BUFFER_DESC* pDesc) {
*pDesc = m_desc;
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
......@@ -3,6 +3,7 @@
#include "../dxvk/dxvk_device.h"
#include "d3d9_device_child.h"
#include "d3d9_format.h"
namespace dxvk {
......@@ -19,11 +20,11 @@ namespace dxvk {
*/
struct D3D9_BUFFER_DESC {
D3DRESOURCETYPE Type;
UINT Size;
DWORD Usage;
D3D9Format Format;
D3DPOOL Pool;
DWORD FVF;
UINT Size;
DWORD Usage;
D3D9Format Format;
D3DPOOL Pool;
DWORD FVF;
};
/**
......@@ -35,12 +36,42 @@ namespace dxvk {
D3D9_COMMON_BUFFER_TYPE_REAL
};
class Direct3DCommonBuffer9 : public RcObject {
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:
Direct3DCommonBuffer9(
Direct3DDevice9Ex* pDevice,
D3D9CommonBuffer(
D3D9DeviceEx* pDevice,
const D3D9_BUFFER_DESC* pDesc);
HRESULT Lock(
......@@ -55,30 +86,34 @@ namespace dxvk {
D3D9_BUFFER_DESC* pDesc);
D3D9_COMMON_BUFFER_MAP_MODE GetMapMode() const {
return (m_buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
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;
}
Rc<DxvkBuffer> GetBuffer(D3D9_COMMON_BUFFER_TYPE type) const {
if (type == D3D9_COMMON_BUFFER_TYPE_MAPPING)
template <D3D9_COMMON_BUFFER_TYPE Type>
Rc<DxvkBuffer> GetBuffer() const {
if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_MAPPING)
return GetMapBuffer();
else if (type == D3D9_COMMON_BUFFER_TYPE_STAGING)
else if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_STAGING)
return GetStagingBuffer();
else //if (type == D3D9_COMMON_BUFFER_TYPE_REAL)
else //if constexpr (Type == D3D9_COMMON_BUFFER_TYPE_REAL)
return GetRealBuffer();
}
DxvkBufferSlice GetBufferSlice(D3D9_COMMON_BUFFER_TYPE type) const {
return GetBufferSlice(type, 0, m_desc.Size);
template <D3D9_COMMON_BUFFER_TYPE Type>
DxvkBufferSlice GetBufferSlice() const {
return GetBufferSlice<Type>(0, m_desc.Size);
}
DxvkBufferSlice GetBufferSlice(D3D9_COMMON_BUFFER_TYPE type, VkDeviceSize offset) const {
return GetBufferSlice(type, offset, m_desc.Size - offset);
template <D3D9_COMMON_BUFFER_TYPE Type>
DxvkBufferSlice GetBufferSlice(VkDeviceSize offset) const {
return GetBufferSlice<Type>(offset, m_desc.Size - offset);
}
DxvkBufferSlice GetBufferSlice(D3D9_COMMON_BUFFER_TYPE type, VkDeviceSize offset, VkDeviceSize length) const {
return DxvkBufferSlice(GetBuffer(type), offset, length);
template <D3D9_COMMON_BUFFER_TYPE Type>
DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const {
return DxvkBufferSlice(GetBuffer<Type>(), offset, length);
}
DxvkBufferSliceHandle AllocMapSlice() {
......@@ -86,26 +121,53 @@ namespace dxvk {
}
DxvkBufferSliceHandle DiscardMapSlice() {
m_mapped = GetMapBuffer()->allocSlice();
return m_mapped;
m_sliceHandle = GetMapBuffer()->allocSlice();
return m_sliceHandle;
}
DxvkBufferSliceHandle GetMappedSlice() const {
return m_mapped;
return m_sliceHandle;
}
DWORD SetMapFlags(DWORD Flags) {
DWORD old = m_mapFlags;
m_mapFlags = Flags;
return old;
}
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;
}
......@@ -118,14 +180,22 @@ namespace dxvk {
return m_buffer;
}
Direct3DDevice9Ex* m_parent;
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_mapped;
DxvkBufferSliceHandle m_sliceHandle;
D3D9Range m_lockRange;
D3D9Range m_dirtyRange;
uint32_t m_lockCount = 0;
bool m_needsUpload = false;
};
......
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
......@@ -2,14 +2,17 @@
#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 {
class Direct3DCommonBuffer9;
enum class D3D9ConstantType {
Float,
Int,
......@@ -17,23 +20,28 @@ namespace dxvk {
};
// We make an assumption later based on the packing of this struct for copying.
#pragma pack(push, 1)
struct D3D9ShaderConstants {
using vec4 = std::array<float, 4>;
using ivec4 = std::array<int, 4>;
struct {
std::array<vec4, caps::MaxFloatConstants> fConsts;
std::array<ivec4, caps::MaxOtherConstants> iConsts;
uint32_t boolBitfield = 0;
} hardware;
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];
};
#pragma pack(pop)
struct D3D9ConstantSets {
constexpr static uint32_t SetSize = sizeof(D3D9ShaderConstants);
Rc<DxvkBuffer> buffer;
bool dirty = true;
Rc<DxvkBuffer> buffer;
const DxsoShaderMetaInfo* meta = nullptr;
bool dirty = true;
};
}
\ No newline at end of file
#include "d3d9_cursor.h"
#include <windows.h>
#include <utility>
namespace dxvk {
D3D9Cursor::D3D9Cursor()
: m_updatePending( false )
, m_pendingX ( 0 )
, m_pendingY ( 0 ) {}
void D3D9Cursor::UpdateCursor(int X, int Y) {
::SetCursorPos(X, Y);
}
void D3D9Cursor::updateCursor(int x, int y, bool immediate) {
m_updatePending = true;
m_pendingX = x;
m_pendingY = y;
if (immediate)
flushCursor();
BOOL D3D9Cursor::ShowCursor(BOOL bShow) {
::SetCursor(bShow ? m_hCursor : nullptr);
return std::exchange(m_visible, bShow);
}
void D3D9Cursor::flushCursor() {
::SetCursorPos(m_pendingX, m_pendingY);
m_updatePending = false;
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:
D3D9Cursor();
void UpdateCursor(int X, int Y);
void updateCursor(int x, int y, bool immediate);
BOOL ShowCursor(BOOL bShow);
void flushCursor();
HRESULT SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap);
private:
bool m_updatePending;
int m_pendingX;
int m_pendingY;
BOOL m_visible = FALSE;
HCURSOR m_hCursor = nullptr;
};
......
This diff is collapsed.
This diff is collapsed.
#pragma once
#include "d3d9_device.h"
#include "d3d9_include.h"
namespace dxvk {
template <typename... Base>
class Direct3DDeviceChild9 : public ComObject<Base...> {
class D3D9DeviceEx;
template <typename Base>
class D3D9DeviceChild : public ComObjectClamp<Base> {
public:
Direct3DDeviceChild9(Direct3DDevice9Ex* device)
: m_parent{ device } {}
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);
......@@ -18,17 +40,21 @@ namespace dxvk {
if (ppDevice == nullptr)
return D3DERR_INVALIDCALL;
*ppDevice = ref(static_cast<IDirect3DDevice9Ex*>(m_parent));
*ppDevice = ref(GetDevice());
return D3D_OK;
}
Direct3DDevice9Ex* GetParent() {
IDirect3DDevice9Ex* GetDevice() {
return reinterpret_cast<IDirect3DDevice9Ex*>(m_parent);
}
D3D9DeviceEx* GetParent() {
return m_parent;
}
protected:
Direct3DDevice9Ex* m_parent;
D3D9DeviceEx* m_parent;
};
......
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));
// Normalize this. DISABLE != 0.
for (uint32_t i = 0; i < caps::TextureStageCount; i++) {
Stages[i].Contents.ColorOp = D3DTOP_DISABLE;
Stages[i].Contents.AlphaOp = D3DTOP_DISABLE;
}
}
D3D9FFShaderStage Stages[caps::TextureStageCount];
};
struct D3D9FFShaderKeyHash {
size_t operator () (const D3D9FFShaderKeyVS& key) const;
size_t operator () (const D3D9FFShaderKeyFS& key) const;
};
bool operator == (const D3D9FFShaderKeyVS& a, const D3D9FFShaderKeyVS& b);
bool operator != (const D3D9FFShaderKeyVS& a, const D3D9FFShaderKeyVS& b);
bool operator == (const D3D9FFShaderKeyFS& a, const D3D9FFShaderKeyFS& b);
bool operator != (const D3D9FFShaderKeyFS& a, const D3D9FFShaderKeyFS& b);
struct D3D9FFShaderKeyEq {
bool operator () (const D3D9FFShaderKeyVS& a, const D3D9FFShaderKeyVS& b) const;
bool operator () (const D3D9FFShaderKeyFS& a, const D3D9FFShaderKeyFS& b) const;
};
class D3D9FFShader {
public:
D3D9FFShader(
D3D9DeviceEx* pDevice,
const</