2019-12-16 04:28:01 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../dxvk/dxvk_device.h"
|
2022-03-11 22:24:58 +01:00
|
|
|
#include "../dxvk/dxvk_cs.h"
|
2019-12-16 04:28:01 +01:00
|
|
|
|
|
|
|
#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)
|
2021-07-24 19:20:27 +02:00
|
|
|
: min(min),
|
|
|
|
max(max) {
|
2019-12-16 04:28:01 +01:00
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool IsDegenerate() { return min == max; }
|
2019-12-16 04:28:01 +01:00
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline void Conjoin(D3D9Range range) {
|
2019-12-16 04:28:01 +01:00
|
|
|
if (IsDegenerate())
|
|
|
|
*this = range;
|
|
|
|
else {
|
|
|
|
min = std::min(range.min, min);
|
|
|
|
max = std::max(range.max, max);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline bool Overlaps(D3D9Range range) {
|
2019-12-16 04:28:01 +01:00
|
|
|
if (IsDegenerate())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return range.max > min && range.min < max;
|
|
|
|
}
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline void Clear() { min = 0; max = 0; }
|
2019-12-16 04:28:01 +01:00
|
|
|
|
|
|
|
uint32_t min = 0;
|
|
|
|
uint32_t max = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class D3D9CommonBuffer {
|
|
|
|
static constexpr VkDeviceSize BufferSliceAlignment = 64;
|
|
|
|
public:
|
|
|
|
|
|
|
|
D3D9CommonBuffer(
|
|
|
|
D3D9DeviceEx* pDevice,
|
|
|
|
const D3D9_BUFFER_DESC* pDesc);
|
|
|
|
|
2023-06-10 01:18:05 +02:00
|
|
|
~D3D9CommonBuffer();
|
|
|
|
|
2019-12-16 04:28:01 +01:00
|
|
|
HRESULT Lock(
|
|
|
|
UINT OffsetToLock,
|
|
|
|
UINT SizeToLock,
|
|
|
|
void** ppbData,
|
|
|
|
DWORD Flags);
|
|
|
|
|
|
|
|
HRESULT Unlock();
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
/**
|
|
|
|
* \brief Determine the mapping mode of the buffer, (ie. direct mapping or backed)
|
|
|
|
*/
|
2023-05-26 03:52:48 +02:00
|
|
|
D3D9_COMMON_BUFFER_MAP_MODE DetermineMapMode(const D3D9Options* options) const;
|
2019-12-16 04:28:01 +01:00
|
|
|
|
2022-02-12 21:03:23 +01:00
|
|
|
/**
|
|
|
|
* \brief Get the mapping mode of the buffer, (ie. direct mapping or backed)
|
|
|
|
*/
|
|
|
|
inline D3D9_COMMON_BUFFER_MAP_MODE GetMapMode() const {
|
|
|
|
return m_mapMode;
|
|
|
|
}
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
/**
|
|
|
|
* \brief Abstraction for getting a type of buffer (mapping/staging/the real buffer) across mapping modes.
|
|
|
|
*/
|
2019-12-16 04:28:01 +01:00
|
|
|
template <D3D9_COMMON_BUFFER_TYPE Type>
|
2021-07-24 19:20:27 +02:00
|
|
|
inline const Rc<DxvkBuffer>& GetBuffer() const {
|
2019-12-16 04:28:01 +01:00
|
|
|
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>
|
2021-07-24 19:20:27 +02:00
|
|
|
inline DxvkBufferSlice GetBufferSlice() const {
|
2019-12-16 04:28:01 +01:00
|
|
|
return GetBufferSlice<Type>(0, m_desc.Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <D3D9_COMMON_BUFFER_TYPE Type>
|
2021-07-24 19:20:27 +02:00
|
|
|
inline DxvkBufferSlice GetBufferSlice(VkDeviceSize offset) const {
|
2019-12-16 04:28:01 +01:00
|
|
|
return GetBufferSlice<Type>(offset, m_desc.Size - offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <D3D9_COMMON_BUFFER_TYPE Type>
|
2021-07-24 19:20:27 +02:00
|
|
|
inline DxvkBufferSlice GetBufferSlice(VkDeviceSize offset, VkDeviceSize length) const {
|
2023-11-14 12:17:39 +01:00
|
|
|
if (likely(length && offset < m_desc.Size)) {
|
|
|
|
return DxvkBufferSlice(GetBuffer<Type>(), offset,
|
|
|
|
std::min<VkDeviceSize>(m_desc.Size - offset, length));
|
|
|
|
}
|
|
|
|
|
|
|
|
return DxvkBufferSlice();
|
2019-12-16 04:28:01 +01:00
|
|
|
}
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline DxvkBufferSliceHandle AllocMapSlice() {
|
2019-12-16 04:28:01 +01:00
|
|
|
return GetMapBuffer()->allocSlice();
|
|
|
|
}
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline DxvkBufferSliceHandle DiscardMapSlice() {
|
2019-12-16 04:28:01 +01:00
|
|
|
m_sliceHandle = GetMapBuffer()->allocSlice();
|
|
|
|
return m_sliceHandle;
|
|
|
|
}
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline DxvkBufferSliceHandle GetMappedSlice() const {
|
2019-12-16 04:28:01 +01:00
|
|
|
return m_sliceHandle;
|
|
|
|
}
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline DWORD GetMapFlags() const { return m_mapFlags; }
|
|
|
|
inline void SetMapFlags(DWORD Flags) { m_mapFlags = Flags; }
|
2019-12-16 04:28:01 +01:00
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline const D3D9_BUFFER_DESC* Desc() const { return &m_desc; }
|
2019-12-16 04:28:01 +01:00
|
|
|
|
|
|
|
static HRESULT ValidateBufferProperties(const D3D9_BUFFER_DESC* pDesc);
|
|
|
|
|
2021-03-17 22:02:00 +01:00
|
|
|
/**
|
|
|
|
* \brief The range of the buffer that was changed using Lock calls
|
|
|
|
*/
|
2021-07-24 19:20:27 +02:00
|
|
|
inline D3D9Range& DirtyRange() { return m_dirtyRange; }
|
2021-03-17 22:02:00 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Whether or not the buffer was written to by the GPU (in IDirect3DDevice9::ProcessVertices)
|
|
|
|
*/
|
2022-02-13 23:58:54 +01:00
|
|
|
inline bool NeedsReadback() const { return m_needsReadback; }
|
2021-03-17 22:02:00 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Sets whether or not the buffer was written to by the GPU
|
|
|
|
*/
|
2022-02-13 23:58:54 +01:00
|
|
|
inline void SetNeedsReadback(bool state) { m_needsReadback = state; }
|
2019-12-16 04:28:01 +01:00
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline uint32_t IncrementLockCount() { return ++m_lockCount; }
|
|
|
|
inline uint32_t DecrementLockCount() {
|
2019-12-16 04:28:01 +01:00
|
|
|
if (m_lockCount == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return --m_lockCount;
|
|
|
|
}
|
2021-07-24 19:20:27 +02:00
|
|
|
inline uint32_t GetLockCount() const { return m_lockCount; }
|
2019-12-16 04:28:01 +01:00
|
|
|
|
2021-03-17 22:20:19 +01:00
|
|
|
/**
|
|
|
|
* \brief Whether or not the staging buffer needs to be copied to the actual buffer
|
|
|
|
*/
|
2021-07-24 19:20:27 +02:00
|
|
|
inline bool NeedsUpload() { return m_desc.Pool != D3DPOOL_DEFAULT && !m_dirtyRange.IsDegenerate(); }
|
2019-12-16 04:28:01 +01:00
|
|
|
|
2020-06-06 21:10:22 +02:00
|
|
|
void PreLoad();
|
|
|
|
|
2022-03-11 22:24:58 +01:00
|
|
|
bool HasSequenceNumber() const {
|
|
|
|
return m_mapMode != D3D9_COMMON_BUFFER_MAP_MODE_DIRECT;
|
|
|
|
}
|
|
|
|
|
2022-02-12 21:25:29 +01:00
|
|
|
/**
|
|
|
|
* \brief Tracks sequence number
|
|
|
|
*
|
|
|
|
* Stores which CS chunk the resource was last used on.
|
|
|
|
* \param [in] Seq Sequence number
|
|
|
|
*/
|
|
|
|
void TrackMappingBufferSequenceNumber(uint64_t Seq) {
|
|
|
|
m_seq = Seq;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Queries sequence number for a given subresource
|
|
|
|
*
|
|
|
|
* Returns which CS chunk the resource was last used on.
|
|
|
|
* \param [in] Subresource Subresource index
|
|
|
|
* \returns Sequence number for the given subresource
|
|
|
|
*/
|
|
|
|
uint64_t GetMappingBufferSequenceNumber() const {
|
2022-03-11 22:24:58 +01:00
|
|
|
return HasSequenceNumber() ? m_seq
|
|
|
|
: DxvkCsThread::SynchronizeAll;
|
2022-02-12 21:25:29 +01:00
|
|
|
}
|
|
|
|
|
2023-12-19 18:37:44 +01:00
|
|
|
bool IsSysmemDynamic() const {
|
|
|
|
return m_desc.Pool == D3DPOOL_SYSTEMMEM && (m_desc.Usage & D3DUSAGE_DYNAMIC) != 0;
|
|
|
|
}
|
|
|
|
|
2019-12-16 04:28:01 +01:00
|
|
|
private:
|
|
|
|
|
|
|
|
Rc<DxvkBuffer> CreateBuffer() const;
|
|
|
|
Rc<DxvkBuffer> CreateStagingBuffer() const;
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline const Rc<DxvkBuffer>& GetMapBuffer() const {
|
2019-12-16 04:28:01 +01:00
|
|
|
return m_stagingBuffer != nullptr ? m_stagingBuffer : m_buffer;
|
|
|
|
}
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline const Rc<DxvkBuffer>& GetStagingBuffer() const {
|
2019-12-16 04:28:01 +01:00
|
|
|
return m_stagingBuffer;
|
|
|
|
}
|
|
|
|
|
2021-07-24 19:20:27 +02:00
|
|
|
inline const Rc<DxvkBuffer>& GetRealBuffer() const {
|
2019-12-16 04:28:01 +01:00
|
|
|
return m_buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
D3D9DeviceEx* m_parent;
|
|
|
|
const D3D9_BUFFER_DESC m_desc;
|
2023-04-22 08:01:39 +02:00
|
|
|
DWORD m_mapFlags = 0;
|
2022-02-13 23:58:54 +01:00
|
|
|
bool m_needsReadback = false;
|
2022-02-12 21:03:23 +01:00
|
|
|
D3D9_COMMON_BUFFER_MAP_MODE m_mapMode;
|
2019-12-16 04:28:01 +01:00
|
|
|
|
|
|
|
Rc<DxvkBuffer> m_buffer;
|
|
|
|
Rc<DxvkBuffer> m_stagingBuffer;
|
|
|
|
|
|
|
|
DxvkBufferSliceHandle m_sliceHandle;
|
|
|
|
|
|
|
|
D3D9Range m_dirtyRange;
|
|
|
|
|
|
|
|
uint32_t m_lockCount = 0;
|
|
|
|
|
2022-02-12 21:25:29 +01:00
|
|
|
uint64_t m_seq = 0ull;
|
|
|
|
|
2019-12-16 04:28:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|