From 0b426a09426d7808a0a418d55cfa61172b4a9fba Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 20 Jan 2018 13:22:44 +0100 Subject: [PATCH] [d3d11] Added new D3D11ImmediateContext class Initial prep work for both CSMT and Deferred Contexts. --- src/d3d11/d3d11_context.cpp | 196 ------------------------------ src/d3d11/d3d11_context.h | 40 +------ src/d3d11/d3d11_context_imm.cpp | 206 ++++++++++++++++++++++++++++++++ src/d3d11/d3d11_context_imm.h | 51 ++++++++ src/d3d11/d3d11_device.cpp | 4 +- src/d3d11/d3d11_device.h | 3 +- src/d3d11/meson.build | 1 + 7 files changed, 263 insertions(+), 238 deletions(-) create mode 100644 src/d3d11/d3d11_context_imm.cpp create mode 100644 src/d3d11/d3d11_context_imm.h diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index d43c696d..d37aa5aa 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -53,16 +53,6 @@ namespace dxvk { } - ULONG STDMETHODCALLTYPE D3D11DeviceContext::AddRef() { - return m_parent->AddRef(); - } - - - ULONG STDMETHODCALLTYPE D3D11DeviceContext::Release() { - return m_parent->Release(); - } - - HRESULT STDMETHODCALLTYPE D3D11DeviceContext::QueryInterface( REFIID riid, void** ppvObject) { @@ -80,16 +70,6 @@ namespace dxvk { } - D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE D3D11DeviceContext::GetType() { - return m_type; - } - - - UINT STDMETHODCALLTYPE D3D11DeviceContext::GetContextFlags() { - return m_flags; - } - - void STDMETHODCALLTYPE D3D11DeviceContext::ClearState() { this->IASetInputLayout(nullptr); this->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED); @@ -163,177 +143,6 @@ namespace dxvk { } - void STDMETHODCALLTYPE D3D11DeviceContext::Flush() { - if (m_type == D3D11_DEVICE_CONTEXT_IMMEDIATE) { - m_parent->FlushInitContext(); - m_drawCount = 0; - - m_device->submitCommandList( - m_context->endRecording(), - nullptr, nullptr); - - m_context->beginRecording( - m_device->createCommandList()); - } else { - Logger::err("D3D11DeviceContext::Flush: Not supported on deferred context"); - } - } - - - void STDMETHODCALLTYPE D3D11DeviceContext::ExecuteCommandList( - ID3D11CommandList* pCommandList, - WINBOOL RestoreContextState) { - Logger::err("D3D11DeviceContext::ExecuteCommandList: Not implemented"); - } - - - HRESULT STDMETHODCALLTYPE D3D11DeviceContext::FinishCommandList( - WINBOOL RestoreDeferredContextState, - ID3D11CommandList **ppCommandList) { - if (m_type == D3D11_DEVICE_CONTEXT_DEFERRED) { - Logger::err("D3D11DeviceContext::FinishCommandList: Not implemented"); - return E_NOTIMPL; - } else { - Logger::err("D3D11DeviceContext::FinishCommandList: Not supported on immediate context"); - return DXGI_ERROR_INVALID_CALL; - } - } - - - HRESULT STDMETHODCALLTYPE D3D11DeviceContext::Map( - ID3D11Resource* pResource, - UINT Subresource, - D3D11_MAP MapType, - UINT MapFlags, - D3D11_MAPPED_SUBRESOURCE* pMappedResource) { - D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; - pResource->GetType(&resourceDim); - - if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { - const D3D11Buffer* resource = static_cast(pResource); - const Rc buffer = resource->GetBufferSlice().buffer(); - - 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_OK; - - if (buffer->isInUse()) { - // Don't wait if the application tells us not to - if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) - return DXGI_ERROR_WAS_STILL_DRAWING; - - // Invalidate the buffer in order to avoid synchronization - // if the application does not need the buffer contents to - // be preserved. The No Overwrite mode does not require any - // sort of synchronization, but should be used with care. - if (MapType == D3D11_MAP_WRITE_DISCARD) { - m_context->invalidateBuffer(buffer); - } else if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) { - this->Flush(); - this->Synchronize(); - } - } - - pMappedResource->pData = buffer->mapPtr(0); - pMappedResource->RowPitch = buffer->info().size; - pMappedResource->DepthPitch = buffer->info().size; - return S_OK; - } else { - // Mapping an image is sadly not as simple as mapping a buffer - // because applications tend to ignore row and layer strides. - // We use a buffer instead and then perform a copy. - D3D11TextureInfo* textureInfo - = GetCommonTextureInfo(pResource); - - if (textureInfo->imageBuffer == nullptr) { - Logger::err("D3D11DeviceContext: Cannot map a device-local image"); - return E_INVALIDARG; - } - - if (pMappedResource == nullptr) - return S_FALSE; - - // Query format and subresource in order to compute - // the row pitch and layer pitch properly. - const DxvkImageCreateInfo& imageInfo = textureInfo->image->info(); - const DxvkFormatInfo* formatInfo = imageFormatInfo(imageInfo.format); - - textureInfo->mappedSubresource = - GetSubresourceFromIndex(VK_IMAGE_ASPECT_COLOR_BIT, - imageInfo.mipLevels, Subresource); - - const VkExtent3D levelExtent = textureInfo->image - ->mipLevelExtent(textureInfo->mappedSubresource.mipLevel); - - const VkExtent3D blockCount = { - levelExtent.width / formatInfo->blockSize.width, - levelExtent.height / formatInfo->blockSize.height, - levelExtent.depth / formatInfo->blockSize.depth }; - - // When using any map mode which requires the image contents - // to be preserved, copy image contents into the buffer. - if (MapType != D3D11_MAP_WRITE_DISCARD) { - const VkImageSubresourceLayers subresourceLayers = { - textureInfo->mappedSubresource.aspectMask, - textureInfo->mappedSubresource.mipLevel, - textureInfo->mappedSubresource.arrayLayer, 1 }; - - m_context->copyImageToBuffer( - textureInfo->imageBuffer, 0, { 0u, 0u }, - textureInfo->image, subresourceLayers, - VkOffset3D { 0, 0, 0 }, levelExtent); - } - - if (textureInfo->imageBuffer->isInUse()) { - if (MapType == D3D11_MAP_WRITE_DISCARD) { - m_context->invalidateBuffer(textureInfo->imageBuffer); - } else { - this->Flush(); - this->Synchronize(); - } - } - - // Set up map pointer. Data is tightly packed within the mapped buffer. - pMappedResource->pData = textureInfo->imageBuffer->mapPtr(0); - pMappedResource->RowPitch = formatInfo->elementSize * blockCount.width; - pMappedResource->DepthPitch = formatInfo->elementSize * blockCount.width * blockCount.height; - return S_OK; - } - } - - - void STDMETHODCALLTYPE D3D11DeviceContext::Unmap( - ID3D11Resource* pResource, - UINT Subresource) { - D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; - pResource->GetType(&resourceDim); - - if (resourceDim != D3D11_RESOURCE_DIMENSION_BUFFER) { - // Now that data has been written into the buffer, - // we need to copy its contents into the image - const D3D11TextureInfo* textureInfo - = GetCommonTextureInfo(pResource); - - const VkExtent3D levelExtent = textureInfo->image - ->mipLevelExtent(textureInfo->mappedSubresource.mipLevel); - - const VkImageSubresourceLayers subresourceLayers = { - textureInfo->mappedSubresource.aspectMask, - textureInfo->mappedSubresource.mipLevel, - textureInfo->mappedSubresource.arrayLayer, 1 }; - - m_context->copyBufferToImage( - textureInfo->image, subresourceLayers, - VkOffset3D { 0, 0, 0 }, levelExtent, - textureInfo->imageBuffer, 0, { 0u, 0u }); - } - } - - void STDMETHODCALLTYPE D3D11DeviceContext::Begin(ID3D11Asynchronous *pAsync) { // Logger::err("D3D11DeviceContext::Begin: Not implemented"); } @@ -1865,11 +1674,6 @@ namespace dxvk { } - void D3D11DeviceContext::Synchronize() { - m_device->waitForIdle(); - } - - void D3D11DeviceContext::BindConstantBuffers( DxbcProgramType ShaderStage, D3D11ConstantBufferBindings& Bindings, diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index f55eb874..81343925 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -20,43 +20,14 @@ namespace dxvk { Rc device); ~D3D11DeviceContext(); - ULONG STDMETHODCALLTYPE AddRef() final; - - ULONG STDMETHODCALLTYPE Release() final; - HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void** ppvObject) final; void STDMETHODCALLTYPE GetDevice(ID3D11Device **ppDevice) final; - D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType() final; - - UINT STDMETHODCALLTYPE GetContextFlags() final; - void STDMETHODCALLTYPE ClearState() final; - void STDMETHODCALLTYPE Flush() final; - - void STDMETHODCALLTYPE ExecuteCommandList( - ID3D11CommandList* pCommandList, - WINBOOL RestoreContextState) final; - - HRESULT STDMETHODCALLTYPE FinishCommandList( - WINBOOL RestoreDeferredContextState, - ID3D11CommandList **ppCommandList) final; - - HRESULT STDMETHODCALLTYPE Map( - ID3D11Resource* pResource, - UINT Subresource, - D3D11_MAP MapType, - UINT MapFlags, - D3D11_MAPPED_SUBRESOURCE* pMappedResource) final; - - void STDMETHODCALLTYPE Unmap( - ID3D11Resource* pResource, - UINT Subresource) final; - void STDMETHODCALLTYPE Begin(ID3D11Asynchronous *pAsync) final; void STDMETHODCALLTYPE End(ID3D11Asynchronous *pAsync) final; @@ -541,19 +512,10 @@ namespace dxvk { UINT NumBuffers, ID3D11Buffer** ppSOTargets) final; - void Synchronize(); - - Rc GetDXVKContext() const { - return m_context; - } - - private: + protected: D3D11Device* const m_parent; - const D3D11_DEVICE_CONTEXT_TYPE m_type = D3D11_DEVICE_CONTEXT_IMMEDIATE; - const UINT m_flags = 0; - Rc m_device; Rc m_context; Rc m_defaultSampler; diff --git a/src/d3d11/d3d11_context_imm.cpp b/src/d3d11/d3d11_context_imm.cpp new file mode 100644 index 00000000..a8f8884f --- /dev/null +++ b/src/d3d11/d3d11_context_imm.cpp @@ -0,0 +1,206 @@ +#include "d3d11_context_imm.h" +#include "d3d11_device.h" +#include "d3d11_texture.h" + +namespace dxvk { + + D3D11ImmediateContext::D3D11ImmediateContext( + D3D11Device* parent, + Rc device) + : D3D11DeviceContext(parent, device) { + + } + + + D3D11ImmediateContext::~D3D11ImmediateContext() { + + } + + + ULONG STDMETHODCALLTYPE D3D11ImmediateContext::AddRef() { + return m_parent->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11ImmediateContext::Release() { + return m_parent->Release(); + } + + + D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE D3D11ImmediateContext::GetType() { + return D3D11_DEVICE_CONTEXT_IMMEDIATE; + } + + + UINT STDMETHODCALLTYPE D3D11ImmediateContext::GetContextFlags() { + return 0; + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::Flush() { + m_parent->FlushInitContext(); + m_drawCount = 0; + + m_device->submitCommandList( + m_context->endRecording(), + nullptr, nullptr); + + m_context->beginRecording( + m_device->createCommandList()); + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::ExecuteCommandList( + ID3D11CommandList* pCommandList, + WINBOOL RestoreContextState) { + Logger::err("D3D11ImmediateContext::ExecuteCommandList: Not implemented"); + } + + + HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::FinishCommandList( + WINBOOL RestoreDeferredContextState, + ID3D11CommandList **ppCommandList) { + Logger::err("D3D11: FinishCommandList called on immediate context"); + return DXGI_ERROR_INVALID_CALL; + } + + + HRESULT STDMETHODCALLTYPE D3D11ImmediateContext::Map( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) { + const D3D11Buffer* resource = static_cast(pResource); + const Rc buffer = resource->GetBufferSlice().buffer(); + + 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_OK; + + if (buffer->isInUse()) { + // Don't wait if the application tells us not to + if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT) + return DXGI_ERROR_WAS_STILL_DRAWING; + + // Invalidate the buffer in order to avoid synchronization + // if the application does not need the buffer contents to + // be preserved. The No Overwrite mode does not require any + // sort of synchronization, but should be used with care. + if (MapType == D3D11_MAP_WRITE_DISCARD) { + m_context->invalidateBuffer(buffer); + } else if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) { + this->Flush(); + this->Synchronize(); + } + } + + pMappedResource->pData = buffer->mapPtr(0); + pMappedResource->RowPitch = buffer->info().size; + pMappedResource->DepthPitch = buffer->info().size; + return S_OK; + } else { + // Mapping an image is sadly not as simple as mapping a buffer + // because applications tend to ignore row and layer strides. + // We use a buffer instead and then perform a copy. + D3D11TextureInfo* textureInfo + = GetCommonTextureInfo(pResource); + + if (textureInfo->imageBuffer == nullptr) { + Logger::err("D3D11DeviceContext: Cannot map a device-local image"); + return E_INVALIDARG; + } + + if (pMappedResource == nullptr) + return S_FALSE; + + // Query format and subresource in order to compute + // the row pitch and layer pitch properly. + const DxvkImageCreateInfo& imageInfo = textureInfo->image->info(); + const DxvkFormatInfo* formatInfo = imageFormatInfo(imageInfo.format); + + textureInfo->mappedSubresource = + GetSubresourceFromIndex(VK_IMAGE_ASPECT_COLOR_BIT, + imageInfo.mipLevels, Subresource); + + const VkExtent3D levelExtent = textureInfo->image + ->mipLevelExtent(textureInfo->mappedSubresource.mipLevel); + + const VkExtent3D blockCount = { + levelExtent.width / formatInfo->blockSize.width, + levelExtent.height / formatInfo->blockSize.height, + levelExtent.depth / formatInfo->blockSize.depth }; + + // When using any map mode which requires the image contents + // to be preserved, copy image contents into the buffer. + if (MapType != D3D11_MAP_WRITE_DISCARD) { + const VkImageSubresourceLayers subresourceLayers = { + textureInfo->mappedSubresource.aspectMask, + textureInfo->mappedSubresource.mipLevel, + textureInfo->mappedSubresource.arrayLayer, 1 }; + + m_context->copyImageToBuffer( + textureInfo->imageBuffer, 0, { 0u, 0u }, + textureInfo->image, subresourceLayers, + VkOffset3D { 0, 0, 0 }, levelExtent); + } + + if (textureInfo->imageBuffer->isInUse()) { + if (MapType == D3D11_MAP_WRITE_DISCARD) { + m_context->invalidateBuffer(textureInfo->imageBuffer); + } else { + this->Flush(); + this->Synchronize(); + } + } + + // Set up map pointer. Data is tightly packed within the mapped buffer. + pMappedResource->pData = textureInfo->imageBuffer->mapPtr(0); + pMappedResource->RowPitch = formatInfo->elementSize * blockCount.width; + pMappedResource->DepthPitch = formatInfo->elementSize * blockCount.width * blockCount.height; + return S_OK; + } + } + + + void STDMETHODCALLTYPE D3D11ImmediateContext::Unmap( + ID3D11Resource* pResource, + UINT Subresource) { + D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + pResource->GetType(&resourceDim); + + if (resourceDim != D3D11_RESOURCE_DIMENSION_BUFFER) { + // Now that data has been written into the buffer, + // we need to copy its contents into the image + const D3D11TextureInfo* textureInfo + = GetCommonTextureInfo(pResource); + + const VkExtent3D levelExtent = textureInfo->image + ->mipLevelExtent(textureInfo->mappedSubresource.mipLevel); + + const VkImageSubresourceLayers subresourceLayers = { + textureInfo->mappedSubresource.aspectMask, + textureInfo->mappedSubresource.mipLevel, + textureInfo->mappedSubresource.arrayLayer, 1 }; + + m_context->copyBufferToImage( + textureInfo->image, subresourceLayers, + VkOffset3D { 0, 0, 0 }, levelExtent, + textureInfo->imageBuffer, 0, { 0u, 0u }); + } + } + + + void D3D11ImmediateContext::Synchronize() { + m_device->waitForIdle(); + } + +} \ No newline at end of file diff --git a/src/d3d11/d3d11_context_imm.h b/src/d3d11/d3d11_context_imm.h new file mode 100644 index 00000000..32d2d902 --- /dev/null +++ b/src/d3d11/d3d11_context_imm.h @@ -0,0 +1,51 @@ +#pragma once + +#include "d3d11_context.h" + +namespace dxvk { + + class D3D11ImmediateContext : public D3D11DeviceContext { + + public: + + D3D11ImmediateContext( + D3D11Device* parent, + Rc device); + ~D3D11ImmediateContext(); + + ULONG STDMETHODCALLTYPE AddRef() final; + + ULONG STDMETHODCALLTYPE Release() final; + + D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType() final; + + UINT STDMETHODCALLTYPE GetContextFlags() final; + + void STDMETHODCALLTYPE Flush() final; + + void STDMETHODCALLTYPE ExecuteCommandList( + ID3D11CommandList* pCommandList, + WINBOOL RestoreContextState) final; + + HRESULT STDMETHODCALLTYPE FinishCommandList( + WINBOOL RestoreDeferredContextState, + ID3D11CommandList **ppCommandList) final; + + HRESULT STDMETHODCALLTYPE Map( + ID3D11Resource* pResource, + UINT Subresource, + D3D11_MAP MapType, + UINT MapFlags, + D3D11_MAPPED_SUBRESOURCE* pMappedResource) final; + + void STDMETHODCALLTYPE Unmap( + ID3D11Resource* pResource, + UINT Subresource) final; + + void Synchronize(); + + private: + + }; + +} \ No newline at end of file diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 2cba39a7..8caf7eb3 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -2,7 +2,7 @@ #include "d3d11_buffer.h" #include "d3d11_class_linkage.h" -#include "d3d11_context.h" +#include "d3d11_context_imm.h" #include "d3d11_device.h" #include "d3d11_input_layout.h" #include "d3d11_present.h" @@ -35,7 +35,7 @@ namespace dxvk { m_dxgiDevice->SetDeviceLayer(this); m_presentDevice->SetDeviceLayer(this); - m_context = new D3D11DeviceContext(this, m_dxvkDevice); + m_context = new D3D11ImmediateContext(this, m_dxvkDevice); m_resourceInitContext = m_dxvkDevice->createContext(); m_resourceInitContext->beginRecording( diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index f570a1f4..014a6077 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -19,6 +19,7 @@ namespace dxvk { class D3D11Buffer; class D3D11Counter; class D3D11DeviceContext; + class D3D11ImmediateContext; class D3D11Predicate; class D3D11PresentDevice; class D3D11Query; @@ -269,7 +270,7 @@ namespace dxvk { const DxbcOptions m_dxbcOptions; - D3D11DeviceContext* m_context = nullptr; + D3D11ImmediateContext* m_context = nullptr; std::mutex m_counterMutex; std::vector m_counterSlices; diff --git a/src/d3d11/meson.build b/src/d3d11/meson.build index e720d90f..78906ee8 100644 --- a/src/d3d11/meson.build +++ b/src/d3d11/meson.build @@ -3,6 +3,7 @@ d3d11_src = [ 'd3d11_buffer.cpp', 'd3d11_class_linkage.cpp', 'd3d11_context.cpp', + 'd3d11_context_imm.cpp', 'd3d11_depth_stencil.cpp', 'd3d11_device.cpp', 'd3d11_enums.cpp',