1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-11-30 22:24:15 +01:00

[d3d11] Implemented buffer mapping on deferred contexts

Allows the MultiThreadedRendering demo from the Microsoft SDK to run.
This commit is contained in:
Philip Rebohle 2018-03-19 03:19:13 +01:00
parent 0eaa3fea3b
commit f1c3b59e87
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 169 additions and 8 deletions

View File

@ -48,10 +48,10 @@ namespace dxvk {
void STDMETHODCALLTYPE GetDesc( void STDMETHODCALLTYPE GetDesc(
D3D11_BUFFER_DESC *pDesc) final; D3D11_BUFFER_DESC *pDesc) final;
/** Rc<DxvkBuffer> GetBuffer() const {
* \brief Retrieves buffer slice return m_buffer;
* \returns Buffer slice containing the entire buffer }
*/
DxvkBufferSlice GetBufferSlice() const { DxvkBufferSlice GetBufferSlice() const {
return DxvkBufferSlice(m_buffer, 0, m_buffer->info().size); return DxvkBufferSlice(m_buffer, 0, m_buffer->info().size);
} }

View File

@ -56,6 +56,7 @@ namespace dxvk {
else else
ClearState(); ClearState();
m_mappedResources.clear();
return S_OK; return S_OK;
} }
@ -66,15 +67,130 @@ namespace dxvk {
D3D11_MAP MapType, D3D11_MAP MapType,
UINT MapFlags, UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource) { D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
Logger::err("D3D11DeferredContext::Map: Not implemented"); D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
return E_NOTIMPL; pResource->GetType(&resourceDim);
if (MapType != D3D11_MAP_WRITE_DISCARD
&& MapType != D3D11_MAP_WRITE_NO_OVERWRITE)
return E_INVALIDARG;
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
return MapBuffer(
static_cast<D3D11Buffer*>(pResource),
MapType, MapFlags, pMappedResource);
} else {
return MapImage(
GetCommonTexture(pResource),
Subresource, MapType, MapFlags,
pMappedResource);
}
} }
void STDMETHODCALLTYPE D3D11DeferredContext::Unmap( void STDMETHODCALLTYPE D3D11DeferredContext::Unmap(
ID3D11Resource* pResource, ID3D11Resource* pResource,
UINT Subresource) { UINT Subresource) {
Logger::err("D3D11DeferredContext::Unmap: Not implemented"); D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
UnmapBuffer(static_cast<D3D11Buffer*>(pResource));
} else {
UnmapImage(
GetCommonTexture(pResource),
Subresource);
}
}
HRESULT D3D11DeferredContext::MapBuffer(
D3D11Buffer* pResource,
D3D11_MAP MapType,
UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
Rc<DxvkBuffer> buffer = pResource->GetBuffer();
if (!(buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
Logger::err("D3D11: Cannot map a device-local buffer");
return E_INVALIDARG;
}
if (pMappedResource == nullptr)
return S_FALSE;
auto entry = FindMapEntry(pResource, 0);
if (MapType == D3D11_MAP_WRITE_DISCARD) {
if (entry != m_mappedResources.end())
m_mappedResources.erase(entry);
D3D11DeferredContextMapEntry mapEntry;
mapEntry.pResource = pResource;
mapEntry.Subresource = 0;
mapEntry.MapType = D3D11_MAP_WRITE_DISCARD;
mapEntry.RowPitch = pResource->GetSize();
mapEntry.DepthPitch = pResource->GetSize();
mapEntry.DataSlice = AllocUpdateBufferSlice(pResource->GetSize());
m_mappedResources.push_back(mapEntry);
pMappedResource->pData = mapEntry.DataSlice.ptr();
pMappedResource->RowPitch = mapEntry.RowPitch;
pMappedResource->DepthPitch = mapEntry.DepthPitch;
return S_OK;
} else {
// The resource must be mapped with D3D11_MAP_WRITE_DISCARD
// before it can be mapped with D3D11_MAP_WRITE_NO_OVERWRITE.
if (entry == m_mappedResources.end())
return E_INVALIDARG;
// Return same memory region as earlier
entry->MapType = D3D11_MAP_WRITE_NO_OVERWRITE;
pMappedResource->pData = entry->DataSlice.ptr();
pMappedResource->RowPitch = entry->RowPitch;
pMappedResource->DepthPitch = entry->DepthPitch;
return S_OK;
}
}
HRESULT D3D11DeferredContext::MapImage(
D3D11CommonTexture* pResource,
UINT Subresource,
D3D11_MAP MapType,
UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
Logger::err("D3D11DeferredContext::MapImage: Not implemented");
return E_NOTIMPL;
}
void D3D11DeferredContext::UnmapBuffer(
D3D11Buffer* pResource) {
auto entry = FindMapEntry(pResource, 0);
if (entry == m_mappedResources.end()) {
Logger::err("D3D11DeferredContext::Unmap: Buffer not mapped");
return;
}
if (entry->MapType == D3D11_MAP_WRITE_DISCARD) {
EmitCs([
cDstBuffer = pResource->GetBuffer(),
cDataSlice = entry->DataSlice
] (DxvkContext* ctx) {
DxvkPhysicalBufferSlice slice = cDstBuffer->allocPhysicalSlice();
std::memcpy(slice.mapPtr(0), cDataSlice.ptr(), cDataSlice.length());
ctx->invalidateBuffer(cDstBuffer, slice);
});
}
}
void D3D11DeferredContext::UnmapImage(
D3D11CommonTexture* pResource,
UINT Subresource) {
Logger::err("D3D11DeferredContext::UnmapImage: Not implemented");
} }

View File

@ -1,10 +1,21 @@
#pragma once #pragma once
#include "d3d11_buffer.h"
#include "d3d11_cmdlist.h" #include "d3d11_cmdlist.h"
#include "d3d11_context.h" #include "d3d11_context.h"
#include "d3d11_texture.h"
namespace dxvk { namespace dxvk {
struct D3D11DeferredContextMapEntry {
Com<ID3D11Resource> pResource;
UINT Subresource;
D3D11_MAP MapType;
UINT RowPitch;
UINT DepthPitch;
DxvkDataSlice DataSlice;
};
class D3D11DeferredContext : public D3D11DeviceContext { class D3D11DeferredContext : public D3D11DeviceContext {
public: public:
@ -43,12 +54,46 @@ namespace dxvk {
const UINT m_contextFlags; const UINT m_contextFlags;
// Command list that we're recording
Com<D3D11CommandList> m_commandList; Com<D3D11CommandList> m_commandList;
// Info about currently mapped (sub)resources. Using a vector
// here is reasonable since there will usually only be a small
// number of mapped resources per command list.
std::vector<D3D11DeferredContextMapEntry> m_mappedResources;
HRESULT MapBuffer(
D3D11Buffer* pResource,
D3D11_MAP MapType,
UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource);
HRESULT MapImage(
D3D11CommonTexture* pResource,
UINT Subresource,
D3D11_MAP MapType,
UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource);
void UnmapBuffer(
D3D11Buffer* pResource);
void UnmapImage(
D3D11CommonTexture* pResource,
UINT Subresource);
Com<D3D11CommandList> CreateCommandList(); Com<D3D11CommandList> CreateCommandList();
void EmitCsChunk(Rc<DxvkCsChunk>&& chunk) final; void EmitCsChunk(Rc<DxvkCsChunk>&& chunk) final;
auto FindMapEntry(ID3D11Resource* pResource, UINT Subresource) {
return std::find_if(m_mappedResources.begin(), m_mappedResources.end(),
[pResource, Subresource] (const D3D11DeferredContextMapEntry& entry) {
return entry.pResource == pResource
&& entry.Subresource == Subresource;
});
}
}; };
} }

View File

@ -128,7 +128,7 @@ namespace dxvk {
D3D11_MAP MapType, D3D11_MAP MapType,
UINT MapFlags, UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource) { D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
Rc<DxvkBuffer> buffer = pResource->GetBufferSlice().buffer(); Rc<DxvkBuffer> buffer = pResource->GetBuffer();
if (!(buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { if (!(buffer->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
Logger::err("D3D11: Cannot map a device-local buffer"); Logger::err("D3D11: Cannot map a device-local buffer");