2022-08-03 16:33:54 +02:00
|
|
|
#include "d3d11_context_common.h"
|
|
|
|
#include "d3d11_context_def.h"
|
|
|
|
#include "d3d11_context_imm.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
template<typename ContextType>
|
|
|
|
D3D11CommonContext<ContextType>::D3D11CommonContext(
|
|
|
|
D3D11Device* pParent,
|
|
|
|
const Rc<DxvkDevice>& Device,
|
|
|
|
DxvkCsChunkFlags CsFlags)
|
2022-08-03 17:13:32 +02:00
|
|
|
: D3D11DeviceContext(pParent, Device, CsFlags),
|
|
|
|
m_annotation(static_cast<ContextType*>(this), Device) {
|
2022-08-03 16:33:54 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename ContextType>
|
|
|
|
D3D11CommonContext<ContextType>::~D3D11CommonContext() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-08-03 16:41:50 +02:00
|
|
|
|
2022-08-03 17:09:30 +02:00
|
|
|
template<typename ContextType>
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D11CommonContext<ContextType>::QueryInterface(REFIID riid, void** ppvObject) {
|
|
|
|
if (ppvObject == nullptr)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
*ppvObject = nullptr;
|
|
|
|
|
|
|
|
if (riid == __uuidof(IUnknown)
|
|
|
|
|| riid == __uuidof(ID3D11DeviceChild)
|
|
|
|
|| riid == __uuidof(ID3D11DeviceContext)
|
|
|
|
|| riid == __uuidof(ID3D11DeviceContext1)
|
|
|
|
|| riid == __uuidof(ID3D11DeviceContext2)
|
|
|
|
|| riid == __uuidof(ID3D11DeviceContext3)
|
|
|
|
|| riid == __uuidof(ID3D11DeviceContext4)) {
|
|
|
|
*ppvObject = ref(this);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (riid == __uuidof(ID3D11VkExtContext)
|
|
|
|
|| riid == __uuidof(ID3D11VkExtContext1)) {
|
|
|
|
*ppvObject = ref(&m_contextExt);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (riid == __uuidof(ID3DUserDefinedAnnotation)
|
|
|
|
|| riid == __uuidof(IDXVKUserDefinedAnnotation)) {
|
|
|
|
*ppvObject = ref(&m_annotation);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (riid == __uuidof(ID3D10Multithread)) {
|
|
|
|
*ppvObject = ref(&m_multithread);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
Logger::warn("D3D11DeviceContext::QueryInterface: Unknown interface query");
|
|
|
|
Logger::warn(str::format(riid));
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-03 16:41:50 +02:00
|
|
|
template<typename ContextType>
|
|
|
|
void STDMETHODCALLTYPE D3D11CommonContext<ContextType>::UpdateSubresource(
|
|
|
|
ID3D11Resource* pDstResource,
|
|
|
|
UINT DstSubresource,
|
|
|
|
const D3D11_BOX* pDstBox,
|
|
|
|
const void* pSrcData,
|
|
|
|
UINT SrcRowPitch,
|
|
|
|
UINT SrcDepthPitch) {
|
|
|
|
UpdateResource(pDstResource, DstSubresource, pDstBox,
|
|
|
|
pSrcData, SrcRowPitch, SrcDepthPitch, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename ContextType>
|
|
|
|
void STDMETHODCALLTYPE D3D11CommonContext<ContextType>::UpdateSubresource1(
|
|
|
|
ID3D11Resource* pDstResource,
|
|
|
|
UINT DstSubresource,
|
|
|
|
const D3D11_BOX* pDstBox,
|
|
|
|
const void* pSrcData,
|
|
|
|
UINT SrcRowPitch,
|
|
|
|
UINT SrcDepthPitch,
|
|
|
|
UINT CopyFlags) {
|
|
|
|
UpdateResource(pDstResource, DstSubresource, pDstBox,
|
|
|
|
pSrcData, SrcRowPitch, SrcDepthPitch, CopyFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-03 17:13:32 +02:00
|
|
|
template<typename ContextType>
|
|
|
|
BOOL STDMETHODCALLTYPE D3D11CommonContext<ContextType>::IsAnnotationEnabled() {
|
|
|
|
return m_annotation.GetStatus();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-03 16:41:50 +02:00
|
|
|
template<typename ContextType>
|
|
|
|
void D3D11CommonContext<ContextType>::UpdateResource(
|
|
|
|
ID3D11Resource* pDstResource,
|
|
|
|
UINT DstSubresource,
|
|
|
|
const D3D11_BOX* pDstBox,
|
|
|
|
const void* pSrcData,
|
|
|
|
UINT SrcRowPitch,
|
|
|
|
UINT SrcDepthPitch,
|
|
|
|
UINT CopyFlags) {
|
|
|
|
auto context = static_cast<ContextType*>(this);
|
|
|
|
D3D10DeviceLock lock = context->LockContext();
|
|
|
|
|
|
|
|
if (!pDstResource)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// We need a different code path for buffers
|
|
|
|
D3D11_RESOURCE_DIMENSION resourceType;
|
|
|
|
pDstResource->GetType(&resourceType);
|
|
|
|
|
|
|
|
if (likely(resourceType == D3D11_RESOURCE_DIMENSION_BUFFER)) {
|
|
|
|
const auto bufferResource = static_cast<D3D11Buffer*>(pDstResource);
|
|
|
|
uint64_t bufferSize = bufferResource->Desc()->ByteWidth;
|
|
|
|
|
|
|
|
// Provide a fast path for mapped buffer updates since some
|
|
|
|
// games use UpdateSubresource to update constant buffers.
|
|
|
|
if (likely(bufferResource->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_DIRECT) && likely(!pDstBox)) {
|
|
|
|
context->UpdateMappedBuffer(bufferResource, 0, bufferSize, pSrcData, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate buffer range to update
|
|
|
|
uint64_t offset = 0;
|
|
|
|
uint64_t length = bufferSize;
|
|
|
|
|
|
|
|
if (pDstBox) {
|
|
|
|
offset = pDstBox->left;
|
|
|
|
length = pDstBox->right - offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unlikely(offset + length > bufferSize))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Still try to be fast if a box is provided but we update the full buffer
|
|
|
|
if (likely(bufferResource->GetMapMode() == D3D11_COMMON_BUFFER_MAP_MODE_DIRECT)) {
|
|
|
|
CopyFlags &= D3D11_COPY_DISCARD | D3D11_COPY_NO_OVERWRITE;
|
|
|
|
|
|
|
|
if (likely(length == bufferSize) || unlikely(CopyFlags != 0)) {
|
|
|
|
context->UpdateMappedBuffer(bufferResource, offset, length, pSrcData, CopyFlags);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise we can't really do anything fancy, so just do a GPU copy
|
|
|
|
context->UpdateBuffer(bufferResource, offset, length, pSrcData);
|
|
|
|
} else {
|
|
|
|
D3D11CommonTexture* textureResource = GetCommonTexture(pDstResource);
|
|
|
|
|
|
|
|
context->UpdateTexture(textureResource,
|
|
|
|
DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-03 16:33:54 +02:00
|
|
|
// Explicitly instantiate here
|
|
|
|
template class D3D11CommonContext<D3D11DeferredContext>;
|
|
|
|
template class D3D11CommonContext<D3D11ImmediateContext>;
|
|
|
|
|
|
|
|
}
|