d3d12: enable texture caching

Bring a little more perf in arkedo 2
This commit is contained in:
vlj 2015-06-21 18:13:28 +02:00 committed by Vincent Lejeune
parent 8cc9642b96
commit c6a5e905bc
3 changed files with 47 additions and 25 deletions

View file

@ -399,18 +399,29 @@ D3D12GSRender::D3D12GSRender()
{ {
gfxHandler = [this](u32 addr) { gfxHandler = [this](u32 addr) {
LOG_ERROR(RSX, "CATCH SEGFAULT %x", addr); bool handled = false;
for (auto tmp : texaddrs) auto It = m_protectedTextures.begin(), E = m_protectedTextures.end();
for (; It != E;)
{ {
if (addr - tmp.first < tmp.second) auto currentIt = It;
++It;
auto protectedTexture = *currentIt;
u32 protectedRangeStart = std::get<1>(protectedTexture), protectedRangeSize = std::get<2>(protectedTexture);
if (addr - protectedRangeStart < protectedRangeSize)
{ {
LOG_ERROR(RSX, "Modified %x range, starting again", tmp.first); std::lock_guard<std::mutex> lock(mut);
vm::page_protect(tmp.first, tmp.second, 0, vm::page_writable, 0); u32 texadrr = std::get<0>(protectedTexture);
return true; LOG_WARNING(RSX, "Modified %x, starting again", texadrr);
ID3D12Resource *texToErase = m_texturesCache[texadrr];
m_texturesCache.erase(texadrr);
m_Textoclean.push_back(texToErase);
vm::page_protect(protectedRangeStart, protectedRangeSize, 0, vm::page_writable, 0);
m_protectedTextures.erase(currentIt);
handled = true;
} }
} }
return handled;
return false;
}; };
loadD3D12FunctionPointers(); loadD3D12FunctionPointers();
if (Ini.GSDebugOutputEnable.GetValue()) if (Ini.GSDebugOutputEnable.GetValue())
@ -1041,7 +1052,6 @@ void D3D12GSRender::Flip()
m_commandQueueGraphic->Signal(storage.m_frameFinishedFence, 1); m_commandQueueGraphic->Signal(storage.m_frameFinishedFence, 1);
// Flush // Flush
m_texturesCache.clear();
m_texturesRTTs.clear(); m_texturesRTTs.clear();
std::vector<std::function<void()> > cleaningFunction = std::vector<std::function<void()> > cleaningFunction =
@ -1052,7 +1062,11 @@ void D3D12GSRender::Flip()
m_textureData.getCleaningFunction() m_textureData.getCleaningFunction()
}; };
m_GC.pushWork([&, cleaningFunction]() std::lock_guard<std::mutex> lock(mut);
std::vector<ID3D12Resource *> textoclean = m_Textoclean;
m_Textoclean.clear();
m_GC.pushWork([&, cleaningFunction, textoclean]()
{ {
WaitForSingleObject(storage.m_frameFinishedHandle, INFINITE); WaitForSingleObject(storage.m_frameFinishedHandle, INFINITE);
CloseHandle(storage.m_frameFinishedHandle); CloseHandle(storage.m_frameFinishedHandle);
@ -1061,6 +1075,9 @@ void D3D12GSRender::Flip()
for (unsigned i = 0; i < 4; i++) for (unsigned i = 0; i < 4; i++)
cleaningFunction[i](); cleaningFunction[i]();
storage.Reset(); storage.Reset();
for (auto tmp : textoclean)
tmp->Release();
}); });
while (getCurrentResourceStorage().m_frameFinishedHandle) while (getCurrentResourceStorage().m_frameFinishedHandle)

View file

@ -202,7 +202,14 @@ struct GarbageCollectionThread
class D3D12GSRender : public GSRender class D3D12GSRender : public GSRender
{ {
private: private:
std::vector <std::pair<u32, u32> > texaddrs; // Address, size /**
* Mutex protecting m_texturesCache and m_Textoclean access
* Memory protection fault catch can be generated by any thread and
* modifies these two members.
*/
std::mutex mut;
std::list <std::tuple<u32, u32, u32> > m_protectedTextures; // Texaddress, start of protected range, size of protected range
std::vector<ID3D12Resource *> m_Textoclean;
GarbageCollectionThread m_GC; GarbageCollectionThread m_GC;
// Copy of RTT to be used as texture // Copy of RTT to be used as texture
std::unordered_map<u32, ID3D12Resource* > m_texturesRTTs; std::unordered_map<u32, ID3D12Resource* > m_texturesRTTs;

View file

@ -337,8 +337,7 @@ ID3D12Resource *uploadSingleTexture(
const RSXTexture &texture, const RSXTexture &texture,
ID3D12Device *device, ID3D12Device *device,
ID3D12GraphicsCommandList *commandList, ID3D12GraphicsCommandList *commandList,
DataHeap<ID3D12Heap, 65536> &textureBuffersHeap, DataHeap<ID3D12Heap, 65536> &textureBuffersHeap)
DataHeap<ID3D12Heap, 65536> &textureHeap)
{ {
ID3D12Resource *vramTexture; ID3D12Resource *vramTexture;
size_t w = texture.GetWidth(), h = texture.GetHeight(); size_t w = texture.GetWidth(), h = texture.GetHeight();
@ -552,19 +551,17 @@ ID3D12Resource *uploadSingleTexture(
D3D12_RESOURCE_DESC texturedesc = getTexture2DResourceDesc(w, h, dxgiFormat, texture.GetMipmap()); D3D12_RESOURCE_DESC texturedesc = getTexture2DResourceDesc(w, h, dxgiFormat, texture.GetMipmap());
textureSize = device->GetResourceAllocationInfo(0, 1, &texturedesc).SizeInBytes; textureSize = device->GetResourceAllocationInfo(0, 1, &texturedesc).SizeInBytes;
assert(textureHeap.canAlloc(textureSize)); D3D12_HEAP_PROPERTIES heapProp = {};
size_t heapOffset2 = textureHeap.alloc(textureSize); heapProp.Type = D3D12_HEAP_TYPE_DEFAULT;
check(device->CreatePlacedResource( check(device->CreateCommittedResource(
textureHeap.m_heap, &heapProp,
heapOffset2, D3D12_HEAP_FLAG_NONE,
&texturedesc, &texturedesc,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
nullptr, nullptr,
IID_PPV_ARGS(&vramTexture) IID_PPV_ARGS(&vramTexture)
)); ));
textureHeap.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset2, textureSize, vramTexture));
size_t miplevel = 0; size_t miplevel = 0;
for (const MipmapLevelInfo mli : mipInfos) for (const MipmapLevelInfo mli : mipInfos)
@ -597,6 +594,7 @@ ID3D12Resource *uploadSingleTexture(
size_t D3D12GSRender::UploadTextures() size_t D3D12GSRender::UploadTextures()
{ {
std::lock_guard<std::mutex> lock(mut);
size_t usedTexture = 0; size_t usedTexture = 0;
for (u32 i = 0; i < m_textures_count; ++i) for (u32 i = 0; i < m_textures_count; ++i)
@ -630,17 +628,17 @@ size_t D3D12GSRender::UploadTextures()
ID3D12GraphicsCommandList *commandList; ID3D12GraphicsCommandList *commandList;
check(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, getCurrentResourceStorage().m_textureUploadCommandAllocator, nullptr, IID_PPV_ARGS(&commandList))); check(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, getCurrentResourceStorage().m_textureUploadCommandAllocator, nullptr, IID_PPV_ARGS(&commandList)));
vramTexture = uploadSingleTexture(m_textures[i], m_device, commandList, m_textureUploadData, m_textureData); vramTexture = uploadSingleTexture(m_textures[i], m_device, commandList, m_textureUploadData);
commandList->Close(); commandList->Close();
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList); m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList);
getCurrentResourceStorage().m_inflightCommandList.push_back(commandList); getCurrentResourceStorage().m_inflightCommandList.push_back(commandList);
m_texturesCache[texaddr] = vramTexture; m_texturesCache[texaddr] = vramTexture;
size_t s = powerOf2Align(w * h * 4, 4096); u32 s = align(w * h * 4, 4096);
LOG_ERROR(RSX, "PROTECTING %x of size %d", powerOf2Align(texaddr, 4096), s); LOG_WARNING(RSX, "PROTECTING %x of size %d", align(texaddr, 4096), s);
texaddrs.push_back(std::make_pair(texaddr & ~0xfff, s)); m_protectedTextures.push_back(std::make_tuple(texaddr, align(texaddr, 4096), s));
vm::page_protect(texaddr & ~0xfff, s, 0, 0, vm::page_writable); vm::page_protect(align(texaddr, 4096), s, 0, 0, vm::page_writable);
} }
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};