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) {
LOG_ERROR(RSX, "CATCH SEGFAULT %x", addr);
for (auto tmp : texaddrs)
bool handled = false;
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);
vm::page_protect(tmp.first, tmp.second, 0, vm::page_writable, 0);
return true;
std::lock_guard<std::mutex> lock(mut);
u32 texadrr = std::get<0>(protectedTexture);
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 false;
return handled;
};
loadD3D12FunctionPointers();
if (Ini.GSDebugOutputEnable.GetValue())
@ -1041,7 +1052,6 @@ void D3D12GSRender::Flip()
m_commandQueueGraphic->Signal(storage.m_frameFinishedFence, 1);
// Flush
m_texturesCache.clear();
m_texturesRTTs.clear();
std::vector<std::function<void()> > cleaningFunction =
@ -1052,7 +1062,11 @@ void D3D12GSRender::Flip()
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);
CloseHandle(storage.m_frameFinishedHandle);
@ -1061,6 +1075,9 @@ void D3D12GSRender::Flip()
for (unsigned i = 0; i < 4; i++)
cleaningFunction[i]();
storage.Reset();
for (auto tmp : textoclean)
tmp->Release();
});
while (getCurrentResourceStorage().m_frameFinishedHandle)

View File

@ -202,7 +202,14 @@ struct GarbageCollectionThread
class D3D12GSRender : public GSRender
{
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;
// Copy of RTT to be used as texture
std::unordered_map<u32, ID3D12Resource* > m_texturesRTTs;

View File

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