1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[d3d11] Fix flush condition and CS thread synchronization

If chunks have been sent to the CS thread, we need to
flush even if the current chunk is empty.
This commit is contained in:
Philip Rebohle 2018-03-22 12:58:26 +01:00
parent 5eedbc0546
commit 7f6c8dff95
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 30 additions and 26 deletions

View File

@ -70,6 +70,12 @@ namespace dxvk {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim); pResource->GetType(&resourceDim);
if (pMappedResource != nullptr) {
pMappedResource->pData = nullptr;
pMappedResource->RowPitch = 0;
pMappedResource->DepthPitch = 0;
}
if (MapType != D3D11_MAP_WRITE_DISCARD if (MapType != D3D11_MAP_WRITE_DISCARD
&& MapType != D3D11_MAP_WRITE_NO_OVERWRITE) && MapType != D3D11_MAP_WRITE_NO_OVERWRITE)
return E_INVALIDARG; return E_INVALIDARG;
@ -115,9 +121,6 @@ namespace dxvk {
return E_INVALIDARG; return E_INVALIDARG;
} }
if (pMappedResource == nullptr)
return S_FALSE;
auto entry = FindMapEntry(pResource, 0); auto entry = FindMapEntry(pResource, 0);
if (MapType == D3D11_MAP_WRITE_DISCARD) { if (MapType == D3D11_MAP_WRITE_DISCARD) {

View File

@ -44,7 +44,8 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() { void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() {
m_parent->FlushInitContext(); m_parent->FlushInitContext();
if (m_csChunk->commandCount() != 0) { if (m_csIsBusy || m_csChunk->commandCount() != 0) {
m_csIsBusy = false;
m_drawCount = 0; m_drawCount = 0;
// Add commands to flush the threaded // Add commands to flush the threaded
@ -74,6 +75,8 @@ namespace dxvk {
RestoreState(); RestoreState();
else else
ClearState(); ClearState();
m_csIsBusy = true;
} }
@ -95,7 +98,13 @@ namespace dxvk {
Logger::warn("D3D11ImmediateContext::Map() application tried to map a nullptr resource"); Logger::warn("D3D11ImmediateContext::Map() application tried to map a nullptr resource");
return DXGI_ERROR_INVALID_CALL; return DXGI_ERROR_INVALID_CALL;
} }
if (pMappedResource != nullptr) {
pMappedResource->pData = nullptr;
pMappedResource->RowPitch = 0;
pMappedResource->DepthPitch = 0;
}
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim); pResource->GetType(&resourceDim);
@ -199,9 +208,6 @@ namespace dxvk {
return E_INVALIDARG; return E_INVALIDARG;
} }
if (pMappedResource == nullptr)
return S_FALSE;
// Parameter validation was successful // Parameter validation was successful
VkImageSubresource subresource = VkImageSubresource subresource =
pResource->GetSubresourceFromIndex( pResource->GetSubresourceFromIndex(
@ -218,8 +224,7 @@ namespace dxvk {
// Query the subresource's memory layout and hope that // Query the subresource's memory layout and hope that
// the application respects the returned pitch values. // the application respects the returned pitch values.
VkSubresourceLayout layout = mappedImage->querySubresourceLayout(subresource); VkSubresourceLayout layout = mappedImage->querySubresourceLayout(subresource);
pMappedResource->pData = mappedImage->mapPtr(layout.offset); pMappedResource->pData = mappedImage->mapPtr(layout.offset);
pMappedResource->RowPitch = imageType >= VK_IMAGE_TYPE_2D ? layout.rowPitch : layout.size; pMappedResource->RowPitch = imageType >= VK_IMAGE_TYPE_2D ? layout.rowPitch : layout.size;
pMappedResource->DepthPitch = imageType >= VK_IMAGE_TYPE_3D ? layout.depthPitch : layout.size; pMappedResource->DepthPitch = imageType >= VK_IMAGE_TYPE_3D ? layout.depthPitch : layout.size;
@ -239,14 +244,12 @@ namespace dxvk {
// We do not have to preserve the contents of the // We do not have to preserve the contents of the
// buffer if the entire image gets discarded. // buffer if the entire image gets discarded.
physicalSlice = mappedBuffer->allocPhysicalSlice(); physicalSlice = mappedBuffer->allocPhysicalSlice();
physicalSlice.resource()->acquire();
EmitCs([ EmitCs([
cImageBuffer = mappedBuffer, cImageBuffer = mappedBuffer,
cPhysicalSlice = physicalSlice cPhysicalSlice = physicalSlice
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
ctx->invalidateBuffer(cImageBuffer, cPhysicalSlice); ctx->invalidateBuffer(cImageBuffer, cPhysicalSlice);
cPhysicalSlice.resource()->release();
}); });
} else { } else {
// When using any map mode which requires the image contents // When using any map mode which requires the image contents
@ -273,9 +276,7 @@ namespace dxvk {
}); });
} }
if (!WaitForResource(mappedBuffer->resource(), MapFlags)) WaitForResource(mappedBuffer->resource(), 0);
return DXGI_ERROR_WAS_STILL_DRAWING;
physicalSlice = mappedBuffer->slice(); physicalSlice = mappedBuffer->slice();
} }
@ -361,6 +362,7 @@ namespace dxvk {
void D3D11ImmediateContext::EmitCsChunk(Rc<DxvkCsChunk>&& chunk) { void D3D11ImmediateContext::EmitCsChunk(Rc<DxvkCsChunk>&& chunk) {
m_csThread.dispatchChunk(std::move(chunk)); m_csThread.dispatchChunk(std::move(chunk));
m_csIsBusy = true;
} }
} }

View File

@ -55,6 +55,7 @@ namespace dxvk {
private: private:
DxvkCsThread m_csThread; DxvkCsThread m_csThread;
bool m_csIsBusy = false;
HRESULT MapBuffer( HRESULT MapBuffer(
D3D11Buffer* pResource, D3D11Buffer* pResource,

View File

@ -53,19 +53,17 @@ namespace dxvk {
void DxvkCsThread::dispatchChunk(Rc<DxvkCsChunk>&& chunk) { void DxvkCsThread::dispatchChunk(Rc<DxvkCsChunk>&& chunk) {
{ std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
m_chunksQueued.push(std::move(chunk)); m_chunksPending += 1;
m_chunksPending += 1; m_chunksQueued.push(std::move(chunk));
if (m_chunksPending > MaxChunksInFlight) { if (m_chunksPending > MaxChunksInFlight) {
m_condOnSync.wait(lock, [this] { m_condOnSync.wait(lock, [this] {
return (m_chunksPending <= MaxChunksInFlight ) return (m_chunksPending <= MaxChunksInFlight )
|| (m_stopped.load()); || (m_stopped.load());
}); });
}
} }
// Wake CS thread
m_condOnAdd.notify_one(); m_condOnAdd.notify_one();
} }