mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-15 07:29:17 +01:00
[d3d11] Implemented naive Map() optimization when used with D3D11_MAP_WRITE_DISCARD
This commit is contained in:
parent
a4eb807215
commit
4172b99952
@ -1,6 +1,9 @@
|
|||||||
#include "d3d11_buffer.h"
|
#include "d3d11_buffer.h"
|
||||||
|
#include "d3d11_context.h"
|
||||||
#include "d3d11_device.h"
|
#include "d3d11_device.h"
|
||||||
|
|
||||||
|
#include "../dxvk/dxvk_data.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
D3D11Buffer::D3D11Buffer(
|
D3D11Buffer::D3D11Buffer(
|
||||||
@ -61,6 +64,74 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT D3D11Buffer::Map(
|
||||||
|
D3D11DeviceContext* pContext,
|
||||||
|
D3D11_MAP MapType,
|
||||||
|
UINT MapFlags,
|
||||||
|
D3D11_MAPPED_SUBRESOURCE* pMappedSubresource) {
|
||||||
|
const Rc<DxvkBuffer> buffer = GetDXVKBuffer();
|
||||||
|
|
||||||
|
if (buffer->mapPtr(0) == nullptr) {
|
||||||
|
Logger::err("D3D11: Cannot map a device-local buffer");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pMappedSubresource == nullptr)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
if (!buffer->isInUse()) {
|
||||||
|
// Simple case: The buffer is currently not being
|
||||||
|
// used by the device, we can return the pointer.
|
||||||
|
pMappedSubresource->pData = buffer->mapPtr(0);
|
||||||
|
pMappedSubresource->RowPitch = buffer->info().size;
|
||||||
|
pMappedSubresource->DepthPitch = buffer->info().size;
|
||||||
|
return S_OK;
|
||||||
|
} else {
|
||||||
|
// Don't wait if the application tells us not to
|
||||||
|
if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT)
|
||||||
|
return DXGI_ERROR_WAS_STILL_DRAWING;
|
||||||
|
|
||||||
|
if (MapType == D3D11_MAP_WRITE_DISCARD) {
|
||||||
|
// Instead of synchronizing with the device, which is
|
||||||
|
// highly inefficient, return a host-local buffer to
|
||||||
|
// the application and upload its contents on unmap()
|
||||||
|
// TODO evaluate whether this improves performance
|
||||||
|
m_mapData = new DxvkDataBuffer(buffer->info().size);
|
||||||
|
|
||||||
|
pMappedSubresource->pData = m_mapData->data();
|
||||||
|
pMappedSubresource->RowPitch = buffer->info().size;
|
||||||
|
pMappedSubresource->DepthPitch = buffer->info().size;
|
||||||
|
return S_OK;
|
||||||
|
} else {
|
||||||
|
// We have to wait for the device to complete
|
||||||
|
pContext->Flush();
|
||||||
|
pContext->Synchronize();
|
||||||
|
|
||||||
|
pMappedSubresource->pData = buffer->mapPtr(0);
|
||||||
|
pMappedSubresource->RowPitch = buffer->info().size;
|
||||||
|
pMappedSubresource->DepthPitch = buffer->info().size;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11Buffer::Unmap(
|
||||||
|
D3D11DeviceContext* pContext) {
|
||||||
|
if (m_mapData != nullptr) {
|
||||||
|
const Rc<DxvkContext> context
|
||||||
|
= pContext->GetDXVKContext();
|
||||||
|
|
||||||
|
context->updateBuffer(
|
||||||
|
m_resource->GetDXVKBuffer(),
|
||||||
|
0, m_mapData->size(),
|
||||||
|
m_mapData->data());
|
||||||
|
|
||||||
|
m_mapData = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkBuffer> D3D11Buffer::GetDXVKBuffer() {
|
Rc<DxvkBuffer> D3D11Buffer::GetDXVKBuffer() {
|
||||||
return m_resource->GetDXVKBuffer();
|
return m_resource->GetDXVKBuffer();
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
class D3D11Device;
|
class D3D11Device;
|
||||||
|
class D3D11DeviceContext;
|
||||||
|
|
||||||
|
|
||||||
class D3D11Buffer : public D3D11DeviceChild<ID3D11Buffer> {
|
class D3D11Buffer : public D3D11DeviceChild<ID3D11Buffer> {
|
||||||
@ -37,6 +38,15 @@ namespace dxvk {
|
|||||||
void STDMETHODCALLTYPE GetDesc(
|
void STDMETHODCALLTYPE GetDesc(
|
||||||
D3D11_BUFFER_DESC *pDesc) final;
|
D3D11_BUFFER_DESC *pDesc) final;
|
||||||
|
|
||||||
|
HRESULT Map(
|
||||||
|
D3D11DeviceContext* pContext,
|
||||||
|
D3D11_MAP MapType,
|
||||||
|
UINT MapFlags,
|
||||||
|
D3D11_MAPPED_SUBRESOURCE* pMappedSubresource);
|
||||||
|
|
||||||
|
void Unmap(
|
||||||
|
D3D11DeviceContext* pContext);
|
||||||
|
|
||||||
Rc<DxvkBuffer> GetDXVKBuffer();
|
Rc<DxvkBuffer> GetDXVKBuffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -45,6 +55,8 @@ namespace dxvk {
|
|||||||
Com<IDXGIBufferResourcePrivate> m_resource;
|
Com<IDXGIBufferResourcePrivate> m_resource;
|
||||||
D3D11_BUFFER_DESC m_desc;
|
D3D11_BUFFER_DESC m_desc;
|
||||||
|
|
||||||
|
Rc<DxvkDataBuffer> m_mapData;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -179,30 +179,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
|
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
|
||||||
D3D11Buffer* resource = static_cast<D3D11Buffer*>(pResource);
|
D3D11Buffer* resource = static_cast<D3D11Buffer*>(pResource);
|
||||||
|
return resource->Map(this, MapType, MapFlags, pMappedResource);
|
||||||
const Rc<DxvkBuffer> buffer = resource->GetDXVKBuffer();
|
|
||||||
|
|
||||||
if (buffer->mapPtr(0) == nullptr) {
|
|
||||||
Logger::err("D3D11: Cannot map a device-local buffer");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pMappedResource == nullptr)
|
|
||||||
return S_OK;
|
|
||||||
|
|
||||||
if (buffer->isInUse()) {
|
|
||||||
if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT)
|
|
||||||
return DXGI_ERROR_WAS_STILL_DRAWING;
|
|
||||||
|
|
||||||
this->Flush();
|
|
||||||
m_device->waitForIdle();
|
|
||||||
// TODO properly synchronize
|
|
||||||
}
|
|
||||||
|
|
||||||
pMappedResource->pData = buffer->mapPtr(0);
|
|
||||||
pMappedResource->RowPitch = buffer->info().size;
|
|
||||||
pMappedResource->DepthPitch = buffer->info().size;
|
|
||||||
return S_OK;
|
|
||||||
} else {
|
} else {
|
||||||
Logger::err("D3D11: Mapping of image resources currently not supported");
|
Logger::err("D3D11: Mapping of image resources currently not supported");
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
@ -213,7 +190,15 @@ namespace dxvk {
|
|||||||
void STDMETHODCALLTYPE D3D11DeviceContext::Unmap(
|
void STDMETHODCALLTYPE D3D11DeviceContext::Unmap(
|
||||||
ID3D11Resource* pResource,
|
ID3D11Resource* pResource,
|
||||||
UINT Subresource) {
|
UINT Subresource) {
|
||||||
// There's literally nothing we have to do here at the moment
|
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
|
||||||
|
pResource->GetType(&resourceDim);
|
||||||
|
|
||||||
|
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
|
||||||
|
D3D11Buffer* resource = static_cast<D3D11Buffer*>(pResource);
|
||||||
|
return resource->Unmap(this);
|
||||||
|
} else {
|
||||||
|
// We already displayed an error on Map()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1456,6 +1441,11 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D11DeviceContext::Synchronize() {
|
||||||
|
m_device->waitForIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D11DeviceContext::BindConstantBuffers(
|
void D3D11DeviceContext::BindConstantBuffers(
|
||||||
DxbcProgramType ShaderStage,
|
DxbcProgramType ShaderStage,
|
||||||
D3D11ConstantBufferBindings* pBindings,
|
D3D11ConstantBufferBindings* pBindings,
|
||||||
|
@ -541,6 +541,12 @@ namespace dxvk {
|
|||||||
UINT NumBuffers,
|
UINT NumBuffers,
|
||||||
ID3D11Buffer** ppSOTargets) final;
|
ID3D11Buffer** ppSOTargets) final;
|
||||||
|
|
||||||
|
void Synchronize();
|
||||||
|
|
||||||
|
Rc<DxvkContext> GetDXVKContext() const {
|
||||||
|
return m_context;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ID3D11Device* const m_parent;
|
ID3D11Device* const m_parent;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user