Skip to content

Commit

Permalink
[d3d9] Unmap unused textures after some time
Browse files Browse the repository at this point in the history
  • Loading branch information
K0bin committed Mar 5, 2022
1 parent 532932a commit 2438b0c
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/d3d9/d3d9_common_texture.cpp
Expand Up @@ -75,6 +75,8 @@ namespace dxvk {
D3D9CommonTexture::~D3D9CommonTexture() {
if (m_size != 0)
m_device->ChangeReportedMemory(m_size);

m_device->RemoveMappedTexture(this);
}


Expand Down Expand Up @@ -155,7 +157,7 @@ namespace dxvk {
}

void* D3D9CommonTexture::GetLockingData(UINT Subresource) {
if (unlikely(m_buffers[Subresource] != nullptr)) {
if (m_buffers[Subresource] != nullptr) {
return m_buffers[Subresource]->getSliceHandle().mapPtr;
}

Expand Down
17 changes: 17 additions & 0 deletions src/d3d9/d3d9_common_texture.h
Expand Up @@ -226,6 +226,13 @@ namespace dxvk {
*/
const Rc<DxvkBuffer>& CreateBufferSubresource(UINT Subresource, bool Clear, bool& Allocated);

void UnmapLockingData() {
const uint32_t subresources = CountSubresources();
for (uint32_t i = 0; i < subresources; i++) {
m_lockingData[i].Unmap();
}
}

/**
* \brief Destroys locking data
* Frees the locking data for a given subresources
Expand Down Expand Up @@ -461,6 +468,14 @@ namespace dxvk {
: 0ull;
}

void SetMappingFrame(uint64_t Frame) {
m_mappingFrame = Frame;
}

uint64_t GetMappingFrame() const {
return m_mappingFrame;
}

private:

D3D9DeviceEx* m_device;
Expand Down Expand Up @@ -506,6 +521,8 @@ namespace dxvk {

std::array<D3DBOX, 6> m_dirtyBoxes;

uint64_t m_mappingFrame;


Rc<DxvkImage> CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT) const;

Expand Down
54 changes: 52 additions & 2 deletions src/d3d9/d3d9_device.cpp
Expand Up @@ -4074,7 +4074,7 @@ namespace dxvk {

auto& desc = *(pResource->Desc());

void* lockingData = pResource->GetLockingData(Subresource);
void* lockingData = MapTexture(pResource, Subresource);

auto& formatMapping = pResource->GetFormatMapping();
const DxvkFormatInfo* formatInfo = formatMapping.IsValid()
Expand Down Expand Up @@ -4350,7 +4350,7 @@ namespace dxvk {

// Now that data has been written into the buffer,
// we need to copy its contents into the image
const void* textureSrcData = pSrcTexture->GetLockingData(SrcSubresource);
const void* textureSrcData = MapTexture(pSrcTexture, SrcSubresource);

auto formatInfo = imageFormatInfo(image->info().format);
auto srcSubresource = pSrcTexture->GetSubresourceFromIndex(
Expand Down Expand Up @@ -7274,4 +7274,54 @@ namespace dxvk {
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->GetLockingData(Subresource);

if (env::is32BitHostPlatform() && pTexture->IsManaged()) {
m_mappedTextures.insert(pTexture);
pTexture->SetMappingFrame(m_frameCounter);
}

return ptr;
}

void D3D9DeviceEx::TouchMappedTexture(D3D9CommonTexture* pTexture) {
if constexpr (!env::is32BitHostPlatform())
return;

if (!pTexture->IsManaged())
return;

D3D9DeviceLock lock = LockDevice();

pTexture->SetMappingFrame(m_frameCounter);
}

void D3D9DeviceEx::RemoveMappedTexture(D3D9CommonTexture* pTexture) {
if constexpr (!env::is32BitHostPlatform())
return;

if (!pTexture->IsManaged())
return;

D3D9DeviceLock lock = LockDevice();
m_mappedTextures.erase(pTexture);
}

void D3D9DeviceEx::UnmapTextures() {
const bool force = m_memoryAllocator.MappedMemory() > 512 << 20;
for (auto iter = m_mappedTextures.begin(); iter != m_mappedTextures.end();) {
const bool mappingBufferUnused = (m_frameCounter - (*iter)->GetMappingFrame() > 16 || force) && !(*iter)->IsAnySubresourceLocked();
if (!mappingBufferUnused) {
iter++;
continue;
}

(*iter)->UnmapLockingData();
iter = m_mappedTextures.erase(iter);
}
}

}
10 changes: 10 additions & 0 deletions src/d3d9/d3d9_device.h
Expand Up @@ -26,6 +26,7 @@

#include "d3d9_shader_permutations.h"

#include <unordered_set>
#include <vector>
#include <type_traits>
#include <unordered_map>
Expand Down Expand Up @@ -933,8 +934,13 @@ namespace dxvk {

void BumpFrame() {
m_frameCounter++;
UnmapTextures();
}

void* MapTexture(D3D9CommonTexture* pTexture, UINT Subresource);
void TouchMappedTexture(D3D9CommonTexture* pTexture);
void RemoveMappedTexture(D3D9CommonTexture* pTexture);

private:

DxvkCsChunkRef AllocCsChunk() {
Expand Down Expand Up @@ -1146,6 +1152,8 @@ namespace dxvk {
D3D9CommonTexture* pResource,
UINT Subresource);

void UnmapTextures();

uint64_t GetCurrentSequenceNumber();

Com<D3D9InterfaceEx> m_parent;
Expand Down Expand Up @@ -1282,6 +1290,8 @@ namespace dxvk {

uint64_t m_frameCounter = 0;

std::unordered_set<D3D9CommonTexture*> m_mappedTextures;

};

}
3 changes: 3 additions & 0 deletions src/d3d9/d3d9_texture.cpp
Expand Up @@ -87,6 +87,7 @@ namespace dxvk {
// and purely rely on AddDirtyRect to notify D3D9 that contents have changed.
// We have no way of knowing which mip levels were actually changed.
m_texture.SetAllNeedUpload();
m_parent->TouchMappedTexture(&m_texture);
return D3D_OK;
}

Expand Down Expand Up @@ -169,6 +170,7 @@ namespace dxvk {
// and purely rely on AddDirtyBox to notify D3D9 that contents have changed.
// We have no way of knowing which mip levels were actually changed.
m_texture.SetAllNeedUpload();
m_parent->TouchMappedTexture(&m_texture);
return D3D_OK;
}

Expand Down Expand Up @@ -259,6 +261,7 @@ namespace dxvk {
for (uint32_t m = 0; m < m_texture.Desc()->MipLevels; m++) {
m_texture.SetNeedsUpload(m_texture.CalcSubresource(Face, m), true);
}
m_parent->TouchMappedTexture(&m_texture);
return D3D_OK;
}

Expand Down

0 comments on commit 2438b0c

Please sign in to comment.