mirror of https://github.com/doitsujin/dxvk
[d3d9] Unmap unused resources
This commit is contained in:
parent
b4f432f1de
commit
ea76bfd019
|
@ -560,3 +560,12 @@
|
||||||
# - True/False
|
# - True/False
|
||||||
|
|
||||||
# dxvk.enableDebugUtils = False
|
# dxvk.enableDebugUtils = False
|
||||||
|
|
||||||
|
# Memory limit for locked D3D9 textures
|
||||||
|
#
|
||||||
|
# How much virtual memory will be used for textures (in MB).
|
||||||
|
# 0 to disable the limit.
|
||||||
|
# THIS DOES NOT IMPACT ACTUAL MEMORY CONSUMPTION OR TEXTURE QUALITY.
|
||||||
|
# DO NOT CHANGE THIS UNLESS YOU HAVE A VERY GOOD REASON.
|
||||||
|
|
||||||
|
# d3d9.textureMemory = 100
|
||||||
|
|
|
@ -89,6 +89,8 @@ namespace dxvk {
|
||||||
D3D9CommonTexture::~D3D9CommonTexture() {
|
D3D9CommonTexture::~D3D9CommonTexture() {
|
||||||
if (m_size != 0)
|
if (m_size != 0)
|
||||||
m_device->ChangeReportedMemory(m_size);
|
m_device->ChangeReportedMemory(m_size);
|
||||||
|
|
||||||
|
m_device->RemoveMappedTexture(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -488,7 +490,7 @@ namespace dxvk {
|
||||||
return D3D9_COMMON_TEXTURE_MAP_MODE_NONE;
|
return D3D9_COMMON_TEXTURE_MAP_MODE_NONE;
|
||||||
|
|
||||||
#ifdef D3D9_ALLOW_UNMAPPING
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
if (m_desc.Pool != D3DPOOL_DEFAULT)
|
if (m_device->GetOptions()->textureMemory != 0 && m_desc.Pool != D3DPOOL_DEFAULT)
|
||||||
return D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE;
|
return D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "d3d9_device.h"
|
#include "d3d9_device.h"
|
||||||
|
|
||||||
#include "d3d9_annotation.h"
|
#include "d3d9_annotation.h"
|
||||||
|
#include "d3d9_common_texture.h"
|
||||||
#include "d3d9_interface.h"
|
#include "d3d9_interface.h"
|
||||||
#include "d3d9_swapchain.h"
|
#include "d3d9_swapchain.h"
|
||||||
#include "d3d9_caps.h"
|
#include "d3d9_caps.h"
|
||||||
|
@ -4201,6 +4202,7 @@ namespace dxvk {
|
||||||
pResource->GetBuffer(Subresource, !needsReadback);
|
pResource->GetBuffer(Subresource, !needsReadback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't use MapTexture here to keep the mapped list small while the resource is still locked.
|
||||||
mapPtr = pResource->GetData(Subresource);
|
mapPtr = pResource->GetData(Subresource);
|
||||||
|
|
||||||
if (needsReadback) {
|
if (needsReadback) {
|
||||||
|
@ -4298,6 +4300,8 @@ namespace dxvk {
|
||||||
|
|
||||||
pResource->SetLocked(Subresource, true);
|
pResource->SetLocked(Subresource, true);
|
||||||
|
|
||||||
|
UnmapTextures();
|
||||||
|
|
||||||
const bool noDirtyUpdate = Flags & D3DLOCK_NO_DIRTY_UPDATE;
|
const bool noDirtyUpdate = Flags & D3DLOCK_NO_DIRTY_UPDATE;
|
||||||
if ((desc.Pool == D3DPOOL_DEFAULT || !noDirtyUpdate) && !readOnly) {
|
if ((desc.Pool == D3DPOOL_DEFAULT || !noDirtyUpdate) && !readOnly) {
|
||||||
if (pBox && MipLevel != 0) {
|
if (pBox && MipLevel != 0) {
|
||||||
|
@ -4354,6 +4358,7 @@ namespace dxvk {
|
||||||
if (unlikely(!pResource->GetLocked(Subresource)))
|
if (unlikely(!pResource->GetLocked(Subresource)))
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
|
||||||
|
MapTexture(pResource, Subresource); // Add it to the list of mapped resources
|
||||||
pResource->SetLocked(Subresource, false);
|
pResource->SetLocked(Subresource, false);
|
||||||
|
|
||||||
// Flush image contents from staging if we aren't read only
|
// Flush image contents from staging if we aren't read only
|
||||||
|
@ -4380,6 +4385,7 @@ namespace dxvk {
|
||||||
pResource->SetNeedsReadback(Subresource, true);
|
pResource->SetNeedsReadback(Subresource, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnmapTextures();
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4463,7 +4469,7 @@ namespace dxvk {
|
||||||
+ srcOffsetBlockCount.y * pitch
|
+ srcOffsetBlockCount.y * pitch
|
||||||
+ srcOffsetBlockCount.x * formatInfo->elementSize;
|
+ srcOffsetBlockCount.x * formatInfo->elementSize;
|
||||||
|
|
||||||
const void* mapPtr = pSrcTexture->GetData(SrcSubresource);
|
const void* mapPtr = MapTexture(pSrcTexture, SrcSubresource);
|
||||||
VkDeviceSize dirtySize = extentBlockCount.width * extentBlockCount.height * extentBlockCount.depth * formatInfo->elementSize;
|
VkDeviceSize dirtySize = extentBlockCount.width * extentBlockCount.height * extentBlockCount.depth * formatInfo->elementSize;
|
||||||
D3D9BufferSlice slice = AllocStagingBuffer(dirtySize);
|
D3D9BufferSlice slice = AllocStagingBuffer(dirtySize);
|
||||||
const void* srcData = reinterpret_cast<const uint8_t*>(mapPtr) + copySrcOffset;
|
const void* srcData = reinterpret_cast<const uint8_t*>(mapPtr) + copySrcOffset;
|
||||||
|
@ -4489,7 +4495,7 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const DxvkFormatInfo* formatInfo = lookupFormatInfo(pDestTexture->GetFormatMapping().FormatColor);
|
const DxvkFormatInfo* formatInfo = lookupFormatInfo(pDestTexture->GetFormatMapping().FormatColor);
|
||||||
const void* mapPtr = pSrcTexture->GetData(SrcSubresource);
|
const void* mapPtr = MapTexture(pSrcTexture, SrcSubresource);
|
||||||
|
|
||||||
// Add more blocks for the other planes that we might have.
|
// Add more blocks for the other planes that we might have.
|
||||||
// TODO: PLEASE CLEAN ME
|
// TODO: PLEASE CLEAN ME
|
||||||
|
@ -4522,6 +4528,7 @@ namespace dxvk {
|
||||||
image, dstLayers,
|
image, dstLayers,
|
||||||
slice.slice);
|
slice.slice);
|
||||||
}
|
}
|
||||||
|
UnmapTextures();
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D9DeviceEx::EmitGenerateMips(
|
void D3D9DeviceEx::EmitGenerateMips(
|
||||||
|
@ -4643,6 +4650,7 @@ namespace dxvk {
|
||||||
pResource->SetMapFlags(Flags | oldFlags);
|
pResource->SetMapFlags(Flags | oldFlags);
|
||||||
pResource->IncrementLockCount();
|
pResource->IncrementLockCount();
|
||||||
|
|
||||||
|
UnmapTextures();
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4675,7 +4683,8 @@ namespace dxvk {
|
||||||
pResource->DirtyRange().Clear();
|
pResource->DirtyRange().Clear();
|
||||||
TrackBufferMappingBufferSequenceNumber(pResource);
|
TrackBufferMappingBufferSequenceNumber(pResource);
|
||||||
|
|
||||||
return D3D_OK;
|
UnmapTextures();
|
||||||
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7223,4 +7232,61 @@ namespace dxvk {
|
||||||
return m_csChunk->empty() ? m_csSeqNum : m_csSeqNum + 1;
|
return m_csChunk->empty() ? m_csSeqNum : m_csSeqNum + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* D3D9DeviceEx::MapTexture(D3D9CommonTexture* pTexture, UINT Subresource) {
|
||||||
|
// Will only be called inside the device lock
|
||||||
|
void *ptr = pTexture->GetData(Subresource);
|
||||||
|
|
||||||
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
|
if (likely(pTexture->GetMapMode() == D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE)) {
|
||||||
|
m_mappedTextures.insert(pTexture);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D9DeviceEx::TouchMappedTexture(D3D9CommonTexture* pTexture) {
|
||||||
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
|
if (pTexture->GetMapMode() != D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
D3D9DeviceLock lock = LockDevice();
|
||||||
|
m_mappedTextures.touch(pTexture);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D9DeviceEx::RemoveMappedTexture(D3D9CommonTexture* pTexture) {
|
||||||
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
|
if (pTexture->GetMapMode() != D3D9_COMMON_TEXTURE_MAP_MODE_UNMAPPABLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
D3D9DeviceLock lock = LockDevice();
|
||||||
|
m_mappedTextures.remove(pTexture);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D9DeviceEx::UnmapTextures() {
|
||||||
|
// Will only be called inside the device lock
|
||||||
|
|
||||||
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
|
uint32_t mappedMemory = m_memoryAllocator.MappedMemory();
|
||||||
|
if (likely(mappedMemory < uint32_t(m_d3d9Options.textureMemory)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t threshold = (m_d3d9Options.textureMemory / 4) * 3;
|
||||||
|
|
||||||
|
auto iter = m_mappedTextures.leastRecentlyUsedIter();
|
||||||
|
while (m_memoryAllocator.MappedMemory() >= threshold && iter != m_mappedTextures.leastRecentlyUsedEndIter()) {
|
||||||
|
if (unlikely((*iter)->IsAnySubresourceLocked() != 0)) {
|
||||||
|
iter++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(*iter)->UnmapData();
|
||||||
|
|
||||||
|
iter = m_mappedTextures.remove(iter);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,13 @@
|
||||||
|
|
||||||
#include "d3d9_shader_permutations.h"
|
#include "d3d9_shader_permutations.h"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "../util/util_lru.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
class D3D9InterfaceEx;
|
class D3D9InterfaceEx;
|
||||||
|
@ -934,6 +937,10 @@ namespace dxvk {
|
||||||
return &m_memoryAllocator;
|
return &m_memoryAllocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* MapTexture(D3D9CommonTexture* pTexture, UINT Subresource);
|
||||||
|
void TouchMappedTexture(D3D9CommonTexture* pTexture);
|
||||||
|
void RemoveMappedTexture(D3D9CommonTexture* pTexture);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DxvkCsChunkRef AllocCsChunk() {
|
DxvkCsChunkRef AllocCsChunk() {
|
||||||
|
@ -1142,6 +1149,8 @@ namespace dxvk {
|
||||||
D3D9CommonTexture* pResource,
|
D3D9CommonTexture* pResource,
|
||||||
UINT Subresource);
|
UINT Subresource);
|
||||||
|
|
||||||
|
void UnmapTextures();
|
||||||
|
|
||||||
uint64_t GetCurrentSequenceNumber();
|
uint64_t GetCurrentSequenceNumber();
|
||||||
|
|
||||||
Com<D3D9InterfaceEx> m_parent;
|
Com<D3D9InterfaceEx> m_parent;
|
||||||
|
@ -1282,6 +1291,9 @@ namespace dxvk {
|
||||||
|
|
||||||
Direct3DState9 m_state;
|
Direct3DState9 m_state;
|
||||||
|
|
||||||
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
|
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ namespace dxvk {
|
||||||
this->deviceLocalConstantBuffers = config.getOption<bool> ("d3d9.deviceLocalConstantBuffers", false);
|
this->deviceLocalConstantBuffers = config.getOption<bool> ("d3d9.deviceLocalConstantBuffers", false);
|
||||||
this->allowDirectBufferMapping = config.getOption<bool> ("d3d9.allowDirectBufferMapping", true);
|
this->allowDirectBufferMapping = config.getOption<bool> ("d3d9.allowDirectBufferMapping", true);
|
||||||
this->seamlessCubes = config.getOption<bool> ("d3d9.seamlessCubes", false);
|
this->seamlessCubes = config.getOption<bool> ("d3d9.seamlessCubes", false);
|
||||||
|
this->textureMemory = config.getOption<int32_t> ("d3d9.textureMemory", 100) << 20;
|
||||||
|
|
||||||
// If we are not Nvidia, enable general hazards.
|
// If we are not Nvidia, enable general hazards.
|
||||||
this->generalHazards = adapter != nullptr
|
this->generalHazards = adapter != nullptr
|
||||||
|
|
|
@ -157,6 +157,9 @@ namespace dxvk {
|
||||||
|
|
||||||
/// Don't use non seamless cube maps
|
/// Don't use non seamless cube maps
|
||||||
bool seamlessCubes;
|
bool seamlessCubes;
|
||||||
|
|
||||||
|
/// How much virtual memory will be used for textures (in MB).
|
||||||
|
int32_t textureMemory;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ namespace dxvk {
|
||||||
if (m_texture.IsManaged())
|
if (m_texture.IsManaged())
|
||||||
m_texture.SetAllNeedUpload();
|
m_texture.SetAllNeedUpload();
|
||||||
|
|
||||||
|
m_parent->TouchMappedTexture(&m_texture);
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +175,7 @@ namespace dxvk {
|
||||||
if (m_texture.IsManaged())
|
if (m_texture.IsManaged())
|
||||||
m_texture.SetAllNeedUpload();
|
m_texture.SetAllNeedUpload();
|
||||||
|
|
||||||
|
m_parent->TouchMappedTexture(&m_texture);
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,6 +269,7 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_parent->TouchMappedTexture(&m_texture);
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue