1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-05 20:52:11 +01:00
dxvk/src/d3d11/d3d11_context.cpp

4504 lines
153 KiB
C++
Raw Normal View History

#include <cstring>
2017-10-11 09:51:48 +02:00
#include "d3d11_context.h"
#include "d3d11_device.h"
#include "d3d11_query.h"
#include "d3d11_texture.h"
#include "d3d11_video.h"
2017-10-11 09:51:48 +02:00
#include "../dxbc/dxbc_util.h"
2017-10-11 09:51:48 +02:00
namespace dxvk {
D3D11DeviceContext::D3D11DeviceContext(
D3D11Device* pParent,
const Rc<DxvkDevice>& Device,
DxvkCsChunkFlags CsFlags)
2021-01-07 20:08:55 +00:00
: D3D11DeviceChild<ID3D11DeviceContext4>(pParent),
m_contextExt(this),
m_annotation(this),
m_multithread(this, false),
m_device (Device),
m_csFlags (CsFlags),
m_csChunk (AllocCsChunk()),
m_cmdData (nullptr) {
2017-10-11 09:51:48 +02:00
}
D3D11DeviceContext::~D3D11DeviceContext() {
2017-11-26 14:01:41 +01:00
2017-10-11 09:51:48 +02:00
}
HRESULT STDMETHODCALLTYPE D3D11DeviceContext::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)
2019-09-16 13:12:13 +02:00
|| riid == __uuidof(ID3D11DeviceContext2)
2019-09-16 13:17:00 +02:00
|| riid == __uuidof(ID3D11DeviceContext3)
|| riid == __uuidof(ID3D11DeviceContext4)) {
*ppvObject = ref(this);
return S_OK;
}
2017-10-11 09:51:48 +02:00
if (riid == __uuidof(ID3D11VkExtContext)) {
*ppvObject = ref(&m_contextExt);
return S_OK;
}
if (riid == __uuidof(ID3DUserDefinedAnnotation)) {
*ppvObject = ref(&m_annotation);
return S_OK;
}
if (riid == __uuidof(ID3D10Multithread)) {
*ppvObject = ref(&m_multithread);
return S_OK;
}
2017-10-11 09:51:48 +02:00
Logger::warn("D3D11DeviceContext::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
2017-10-11 09:51:48 +02:00
return E_NOINTERFACE;
}
void STDMETHODCALLTYPE D3D11DeviceContext::DiscardResource(ID3D11Resource* pResource) {
D3D10DeviceLock lock = LockContext();
if (!pResource)
return;
// We don't support the Discard API for images
D3D11_RESOURCE_DIMENSION resType = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resType);
if (resType == D3D11_RESOURCE_DIMENSION_BUFFER) {
DiscardBuffer(pResource);
} else {
auto texture = GetCommonTexture(pResource);
for (uint32_t i = 0; i < texture->CountSubresources(); i++)
DiscardTexture(pResource, i);
}
}
void STDMETHODCALLTYPE D3D11DeviceContext::DiscardView(ID3D11View* pResourceView) {
DiscardView1(pResourceView, nullptr, 0);
}
void STDMETHODCALLTYPE D3D11DeviceContext::DiscardView1(
ID3D11View* pResourceView,
const D3D11_RECT* pRects,
UINT NumRects) {
D3D10DeviceLock lock = LockContext();
// We don't support discarding individual rectangles
if (!pResourceView || (NumRects && pRects))
return;
// ID3D11View has no methods to query the exact type of
// the view, so we'll have to check each possible class
auto dsv = dynamic_cast<D3D11DepthStencilView*>(pResourceView);
auto rtv = dynamic_cast<D3D11RenderTargetView*>(pResourceView);
auto uav = dynamic_cast<D3D11UnorderedAccessView*>(pResourceView);
Rc<DxvkImageView> view;
if (dsv) view = dsv->GetImageView();
if (rtv) view = rtv->GetImageView();
if (uav) view = uav->GetImageView();
if (view == nullptr)
return;
// Get information about underlying resource
Com<ID3D11Resource> resource;
pResourceView->GetResource(&resource);
uint32_t mipCount = GetCommonTexture(resource.ptr())->Desc()->MipLevels;
// Discard mip levels one by one
VkImageSubresourceRange sr = view->subresources();
for (uint32_t layer = 0; layer < sr.layerCount; layer++) {
for (uint32_t mip = 0; mip < sr.levelCount; mip++) {
DiscardTexture(resource.ptr(), D3D11CalcSubresource(
sr.baseMipLevel + mip, sr.baseArrayLayer + layer, mipCount));
}
}
// Since we don't handle SRVs here, we can assume that the
// view covers all aspects of the underlying resource.
EmitCs([cView = view] (DxvkContext* ctx) {
ctx->discardImageView(cView, cView->formatInfo()->aspectMask);
});
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::ClearState() {
D3D10DeviceLock lock = LockContext();
// Default shaders
m_state.vs.shader = nullptr;
m_state.hs.shader = nullptr;
m_state.ds.shader = nullptr;
m_state.gs.shader = nullptr;
m_state.ps.shader = nullptr;
m_state.cs.shader = nullptr;
// Default constant buffers
for (uint32_t i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) {
m_state.vs.constantBuffers[i] = { nullptr, 0, 0 };
m_state.hs.constantBuffers[i] = { nullptr, 0, 0 };
m_state.ds.constantBuffers[i] = { nullptr, 0, 0 };
m_state.gs.constantBuffers[i] = { nullptr, 0, 0 };
m_state.ps.constantBuffers[i] = { nullptr, 0, 0 };
m_state.cs.constantBuffers[i] = { nullptr, 0, 0 };
}
// Default samplers
for (uint32_t i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; i++) {
m_state.vs.samplers[i] = nullptr;
m_state.hs.samplers[i] = nullptr;
m_state.ds.samplers[i] = nullptr;
m_state.gs.samplers[i] = nullptr;
m_state.ps.samplers[i] = nullptr;
m_state.cs.samplers[i] = nullptr;
}
// Default shader resources
for (uint32_t i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++) {
m_state.vs.shaderResources.views[i] = nullptr;
m_state.hs.shaderResources.views[i] = nullptr;
m_state.ds.shaderResources.views[i] = nullptr;
m_state.gs.shaderResources.views[i] = nullptr;
m_state.ps.shaderResources.views[i] = nullptr;
m_state.cs.shaderResources.views[i] = nullptr;
}
m_state.vs.shaderResources.hazardous.clear();
m_state.hs.shaderResources.hazardous.clear();
m_state.ds.shaderResources.hazardous.clear();
m_state.gs.shaderResources.hazardous.clear();
m_state.ps.shaderResources.hazardous.clear();
m_state.cs.shaderResources.hazardous.clear();
// Default UAVs
for (uint32_t i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++) {
m_state.ps.unorderedAccessViews[i] = nullptr;
m_state.cs.unorderedAccessViews[i] = nullptr;
}
m_state.cs.uavMask.clear();
// Default ID state
m_state.id.argBuffer = nullptr;
// Default IA state
m_state.ia.inputLayout = nullptr;
m_state.ia.primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
for (uint32_t i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) {
m_state.ia.vertexBuffers[i].buffer = nullptr;
m_state.ia.vertexBuffers[i].offset = 0;
m_state.ia.vertexBuffers[i].stride = 0;
}
m_state.ia.indexBuffer.buffer = nullptr;
m_state.ia.indexBuffer.offset = 0;
m_state.ia.indexBuffer.format = DXGI_FORMAT_UNKNOWN;
// Default OM State
for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
m_state.om.renderTargetViews[i] = nullptr;
m_state.om.depthStencilView = nullptr;
m_state.om.cbState = nullptr;
m_state.om.dsState = nullptr;
for (uint32_t i = 0; i < 4; i++)
2019-06-13 04:15:23 +02:00
m_state.om.blendFactor[i] = 1.0f;
m_state.om.sampleMask = D3D11_DEFAULT_SAMPLE_MASK;
m_state.om.stencilRef = D3D11_DEFAULT_STENCIL_REFERENCE;
m_state.om.maxRtv = 0;
m_state.om.maxUav = 0;
// Default RS state
m_state.rs.state = nullptr;
m_state.rs.numViewports = 0;
m_state.rs.numScissors = 0;
for (uint32_t i = 0; i < D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; i++) {
m_state.rs.viewports[i] = D3D11_VIEWPORT { };
m_state.rs.scissors [i] = D3D11_RECT { };
}
// Default SO state
for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) {
m_state.so.targets[i].buffer = nullptr;
m_state.so.targets[i].offset = 0;
}
// Default predication
m_state.pr.predicateObject = nullptr;
m_state.pr.predicateValue = FALSE;
// Make sure to apply all state
ResetState();
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::SetPredication(
2017-10-11 09:51:48 +02:00
ID3D11Predicate* pPredicate,
BOOL PredicateValue) {
D3D10DeviceLock lock = LockContext();
2019-09-16 15:13:48 +02:00
auto predicate = D3D11Query::FromPredicate(pPredicate);
m_state.pr.predicateObject = predicate;
m_state.pr.predicateValue = PredicateValue;
static bool s_errorShown = false;
if (pPredicate && !std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::SetPredication: Stub");
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GetPredication(
2017-10-11 09:51:48 +02:00
ID3D11Predicate** ppPredicate,
BOOL* pPredicateValue) {
D3D10DeviceLock lock = LockContext();
2019-09-25 20:55:43 +02:00
if (ppPredicate)
*ppPredicate = D3D11Query::AsPredicate(m_state.pr.predicateObject.ref());
2019-09-25 20:55:43 +02:00
if (pPredicateValue)
*pPredicateValue = m_state.pr.predicateValue;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CopySubresourceRegion(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pDstResource,
UINT DstSubresource,
UINT DstX,
UINT DstY,
UINT DstZ,
ID3D11Resource* pSrcResource,
UINT SrcSubresource,
const D3D11_BOX* pSrcBox) {
CopySubresourceRegion1(
pDstResource, DstSubresource, DstX, DstY, DstZ,
pSrcResource, SrcSubresource, pSrcBox, 0);
}
void STDMETHODCALLTYPE D3D11DeviceContext::CopySubresourceRegion1(
ID3D11Resource* pDstResource,
UINT DstSubresource,
UINT DstX,
UINT DstY,
UINT DstZ,
ID3D11Resource* pSrcResource,
UINT SrcSubresource,
const D3D11_BOX* pSrcBox,
UINT CopyFlags) {
D3D10DeviceLock lock = LockContext();
if (!pDstResource || !pSrcResource)
return;
if (pSrcBox
&& (pSrcBox->left >= pSrcBox->right
|| pSrcBox->top >= pSrcBox->bottom
|| pSrcBox->front >= pSrcBox->back))
return;
D3D11_RESOURCE_DIMENSION dstResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
D3D11_RESOURCE_DIMENSION srcResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pDstResource->GetType(&dstResourceDim);
pSrcResource->GetType(&srcResourceDim);
2021-06-22 02:53:13 +02:00
if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER && srcResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
auto dstBuffer = static_cast<D3D11Buffer*>(pDstResource);
auto srcBuffer = static_cast<D3D11Buffer*>(pSrcResource);
VkDeviceSize dstOffset = DstX;
VkDeviceSize srcOffset = 0;
VkDeviceSize byteCount = -1;
if (pSrcBox) {
srcOffset = pSrcBox->left;
byteCount = pSrcBox->right - pSrcBox->left;
}
CopyBuffer(dstBuffer, dstOffset, srcBuffer, srcOffset, byteCount);
2021-06-22 02:53:13 +02:00
} else if (dstResourceDim != D3D11_RESOURCE_DIMENSION_BUFFER && srcResourceDim != D3D11_RESOURCE_DIMENSION_BUFFER) {
auto dstTexture = GetCommonTexture(pDstResource);
auto srcTexture = GetCommonTexture(pSrcResource);
2021-06-22 02:53:13 +02:00
if (DstSubresource >= dstTexture->CountSubresources()
|| SrcSubresource >= srcTexture->CountSubresources())
return;
2021-06-22 02:53:13 +02:00
auto dstFormatInfo = imageFormatInfo(dstTexture->GetPackedFormat());
auto srcFormatInfo = imageFormatInfo(srcTexture->GetPackedFormat());
2021-06-22 02:53:13 +02:00
auto dstLayers = vk::makeSubresourceLayers(dstTexture->GetSubresourceFromIndex(dstFormatInfo->aspectMask, DstSubresource));
auto srcLayers = vk::makeSubresourceLayers(srcTexture->GetSubresourceFromIndex(srcFormatInfo->aspectMask, SrcSubresource));
VkOffset3D srcOffset = { 0, 0, 0 };
VkOffset3D dstOffset = { int32_t(DstX), int32_t(DstY), int32_t(DstZ) };
2021-06-22 02:53:13 +02:00
VkExtent3D srcExtent = srcTexture->MipLevelExtent(srcLayers.mipLevel);
if (pSrcBox != nullptr) {
srcOffset.x = pSrcBox->left;
srcOffset.y = pSrcBox->top;
srcOffset.z = pSrcBox->front;
2021-06-22 02:53:13 +02:00
srcExtent.width = pSrcBox->right - pSrcBox->left;
srcExtent.height = pSrcBox->bottom - pSrcBox->top;
srcExtent.depth = pSrcBox->back - pSrcBox->front;
}
2021-06-22 02:53:13 +02:00
CopyImage(
dstTexture, &dstLayers, dstOffset,
srcTexture, &srcLayers, srcOffset,
srcExtent);
} else {
Logger::err(str::format(
"D3D11: CopySubresourceRegion1: Incompatible resources",
"\n Dst resource type: ", dstResourceDim,
"\n Src resource type: ", srcResourceDim));
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CopyResource(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pDstResource,
ID3D11Resource* pSrcResource) {
D3D10DeviceLock lock = LockContext();
if (!pDstResource || !pSrcResource || (pDstResource == pSrcResource))
return;
D3D11_RESOURCE_DIMENSION dstResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
D3D11_RESOURCE_DIMENSION srcResourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pDstResource->GetType(&dstResourceDim);
pSrcResource->GetType(&srcResourceDim);
if (dstResourceDim != srcResourceDim) {
Logger::err(str::format(
"D3D11: CopyResource: Incompatible resources",
"\n Dst resource type: ", dstResourceDim,
"\n Src resource type: ", srcResourceDim));
return;
}
if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
auto dstBuffer = static_cast<D3D11Buffer*>(pDstResource);
auto srcBuffer = static_cast<D3D11Buffer*>(pSrcResource);
if (dstBuffer->Desc()->ByteWidth != srcBuffer->Desc()->ByteWidth)
return;
CopyBuffer(dstBuffer, 0, srcBuffer, 0, -1);
} else {
auto dstTexture = GetCommonTexture(pDstResource);
auto srcTexture = GetCommonTexture(pSrcResource);
2021-06-22 02:53:13 +02:00
auto dstDesc = dstTexture->Desc();
auto srcDesc = srcTexture->Desc();
2021-06-22 02:53:13 +02:00
// The subresource count must match as well
if (dstDesc->ArraySize != srcDesc->ArraySize
|| dstDesc->MipLevels != srcDesc->MipLevels) {
Logger::err("D3D11: CopyResource: Incompatible images");
return;
}
2021-06-22 02:53:13 +02:00
auto dstFormatInfo = imageFormatInfo(dstTexture->GetPackedFormat());
auto srcFormatInfo = imageFormatInfo(srcTexture->GetPackedFormat());
for (uint32_t i = 0; i < dstDesc->MipLevels; i++) {
VkImageSubresourceLayers dstLayers = { dstFormatInfo->aspectMask, i, 0, dstDesc->ArraySize };
VkImageSubresourceLayers srcLayers = { srcFormatInfo->aspectMask, i, 0, srcDesc->ArraySize };
2021-06-22 02:53:13 +02:00
CopyImage(
dstTexture, &dstLayers, VkOffset3D(),
srcTexture, &srcLayers, VkOffset3D(),
srcTexture->MipLevelExtent(i));
}
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CopyStructureCount(
2017-10-11 09:51:48 +02:00
ID3D11Buffer* pDstBuffer,
UINT DstAlignedByteOffset,
ID3D11UnorderedAccessView* pSrcView) {
D3D10DeviceLock lock = LockContext();
auto buf = static_cast<D3D11Buffer*>(pDstBuffer);
auto uav = static_cast<D3D11UnorderedAccessView*>(pSrcView);
if (!buf || !uav)
return;
auto counterSlice = uav->GetCounterSlice();
if (!counterSlice.defined())
return;
EmitCs([
cDstSlice = buf->GetBufferSlice(DstAlignedByteOffset),
cSrcSlice = std::move(counterSlice)
] (DxvkContext* ctx) {
ctx->copyBuffer(
cDstSlice.buffer(),
cDstSlice.offset(),
cSrcSlice.buffer(),
cSrcSlice.offset(),
sizeof(uint32_t));
});
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::CopyTiles(
ID3D11Resource* pTiledResource,
const D3D11_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate,
const D3D11_TILE_REGION_SIZE* pTileRegionSize,
ID3D11Buffer* pBuffer,
UINT64 BufferStartOffsetInBytes,
UINT Flags) {
static bool s_errorShown = false;
if (!std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::CopyTiles: Not implemented");
}
HRESULT STDMETHODCALLTYPE D3D11DeviceContext::CopyTileMappings(
ID3D11Resource* pDestTiledResource,
const D3D11_TILED_RESOURCE_COORDINATE* pDestRegionStartCoordinate,
ID3D11Resource* pSourceTiledResource,
const D3D11_TILED_RESOURCE_COORDINATE* pSourceRegionStartCoordinate,
const D3D11_TILE_REGION_SIZE* pTileRegionSize,
UINT Flags) {
static bool s_errorShown = false;
if (!std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::CopyTileMappings: Not implemented");
return DXGI_ERROR_INVALID_CALL;
}
HRESULT STDMETHODCALLTYPE D3D11DeviceContext::ResizeTilePool(
ID3D11Buffer* pTilePool,
UINT64 NewSizeInBytes) {
static bool s_errorShown = false;
if (!std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::ResizeTilePool: Not implemented");
return DXGI_ERROR_INVALID_CALL;
}
void STDMETHODCALLTYPE D3D11DeviceContext::TiledResourceBarrier(
ID3D11DeviceChild* pTiledResourceOrViewAccessBeforeBarrier,
ID3D11DeviceChild* pTiledResourceOrViewAccessAfterBarrier) {
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::ClearRenderTargetView(
2017-10-11 09:51:48 +02:00
ID3D11RenderTargetView* pRenderTargetView,
const FLOAT ColorRGBA[4]) {
D3D10DeviceLock lock = LockContext();
2017-12-04 13:39:37 +01:00
auto rtv = static_cast<D3D11RenderTargetView*>(pRenderTargetView);
if (!rtv)
return;
auto view = rtv->GetImageView();
auto color = ConvertColorValue(ColorRGBA, view->formatInfo());
EmitCs([
cClearValue = color,
cImageView = std::move(view)
] (DxvkContext* ctx) {
ctx->clearRenderTarget(
cImageView,
VK_IMAGE_ASPECT_COLOR_BIT,
cClearValue);
});
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::ClearUnorderedAccessViewUint(
2017-10-11 09:51:48 +02:00
ID3D11UnorderedAccessView* pUnorderedAccessView,
const UINT Values[4]) {
D3D10DeviceLock lock = LockContext();
auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
if (!uav)
return;
// Gather UAV format info. We'll use this to determine
// whether we need to create a temporary view or not.
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
uav->GetDesc(&uavDesc);
VkFormat uavFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_ANY).Format;
VkFormat rawFormat = m_parent->LookupFormat(uavDesc.Format, DXGI_VK_FORMAT_MODE_RAW).Format;
if (uavFormat != rawFormat && rawFormat == VK_FORMAT_UNDEFINED) {
Logger::err(str::format("D3D11: ClearUnorderedAccessViewUint: No raw format found for ", uavFormat));
return;
}
// Set up clear color struct
VkClearValue clearValue;
clearValue.color.uint32[0] = Values[0];
clearValue.color.uint32[1] = Values[1];
clearValue.color.uint32[2] = Values[2];
clearValue.color.uint32[3] = Values[3];
// This is the only packed format that has UAV support
if (uavFormat == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
clearValue.color.uint32[0] = ((Values[0] & 0x7FF) << 0)
| ((Values[1] & 0x7FF) << 11)
| ((Values[2] & 0x3FF) << 22);
}
if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
// In case of raw and structured buffers as well as typed
// buffers that can be used for atomic operations, we can
// use the fast Vulkan buffer clear function.
Rc<DxvkBufferView> bufferView = uav->GetBufferView();
if (bufferView->info().format == VK_FORMAT_R32_UINT
|| bufferView->info().format == VK_FORMAT_R32_SINT
|| bufferView->info().format == VK_FORMAT_R32_SFLOAT) {
EmitCs([
cClearValue = Values[0],
cDstSlice = bufferView->slice()
] (DxvkContext* ctx) {
ctx->clearBuffer(
cDstSlice.buffer(),
cDstSlice.offset(),
cDstSlice.length(),
cClearValue);
});
} else {
// Create a view with an integer format if necessary
if (uavFormat != rawFormat) {
DxvkBufferViewCreateInfo info = bufferView->info();
info.format = rawFormat;
bufferView = m_device->createBufferView(
bufferView->buffer(), info);
}
EmitCs([
cClearValue = clearValue,
cDstView = bufferView
] (DxvkContext* ctx) {
ctx->clearBufferView(
cDstView, 0,
cDstView->elementCount(),
cClearValue.color);
});
}
} else {
// Create a view with an integer format if necessary
Rc<DxvkImageView> imageView = uav->GetImageView();
if (uavFormat != rawFormat) {
DxvkImageViewCreateInfo info = imageView->info();
info.format = rawFormat;
imageView = m_device->createImageView(
imageView->image(), info);
}
EmitCs([
cClearValue = clearValue,
cDstView = imageView
] (DxvkContext* ctx) {
ctx->clearImageView(cDstView,
VkOffset3D { 0, 0, 0 },
cDstView->mipLevelExtent(0),
VK_IMAGE_ASPECT_COLOR_BIT,
cClearValue);
});
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::ClearUnorderedAccessViewFloat(
2017-10-11 09:51:48 +02:00
ID3D11UnorderedAccessView* pUnorderedAccessView,
const FLOAT Values[4]) {
D3D10DeviceLock lock = LockContext();
auto uav = static_cast<D3D11UnorderedAccessView*>(pUnorderedAccessView);
if (!uav)
return;
auto imgView = uav->GetImageView();
auto bufView = uav->GetBufferView();
const DxvkFormatInfo* info = nullptr;
if (imgView != nullptr) info = imgView->formatInfo();
if (bufView != nullptr) info = bufView->formatInfo();
if (!info || info->flags.any(DxvkFormatFlag::SampledSInt, DxvkFormatFlag::SampledUInt))
return;
VkClearValue clearValue;
clearValue.color.float32[0] = Values[0];
clearValue.color.float32[1] = Values[1];
clearValue.color.float32[2] = Values[2];
clearValue.color.float32[3] = Values[3];
if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
EmitCs([
cClearValue = clearValue,
cDstView = std::move(bufView)
] (DxvkContext* ctx) {
ctx->clearBufferView(
cDstView, 0,
cDstView->elementCount(),
cClearValue.color);
});
} else {
EmitCs([
cClearValue = clearValue,
cDstView = std::move(imgView)
] (DxvkContext* ctx) {
ctx->clearImageView(cDstView,
VkOffset3D { 0, 0, 0 },
cDstView->mipLevelExtent(0),
VK_IMAGE_ASPECT_COLOR_BIT,
cClearValue);
});
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::ClearDepthStencilView(
2017-10-11 09:51:48 +02:00
ID3D11DepthStencilView* pDepthStencilView,
UINT ClearFlags,
FLOAT Depth,
UINT8 Stencil) {
D3D10DeviceLock lock = LockContext();
auto dsv = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
if (!dsv)
return;
// Figure out which aspects to clear based on
// the image view properties and clear flags.
VkImageAspectFlags aspectMask = 0;
if (ClearFlags & D3D11_CLEAR_DEPTH)
aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (ClearFlags & D3D11_CLEAR_STENCIL)
aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
aspectMask &= dsv->GetWritableAspectMask();
if (!aspectMask)
return;
VkClearValue clearValue;
clearValue.depthStencil.depth = Depth;
clearValue.depthStencil.stencil = Stencil;
EmitCs([
cClearValue = clearValue,
cAspectMask = aspectMask,
cImageView = dsv->GetImageView()
] (DxvkContext* ctx) {
ctx->clearRenderTarget(
cImageView,
cAspectMask,
cClearValue);
});
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::ClearView(
ID3D11View* pView,
const FLOAT Color[4],
const D3D11_RECT* pRect,
UINT NumRects) {
D3D10DeviceLock lock = LockContext();
if (NumRects && !pRect)
return;
// ID3D11View has no methods to query the exact type of
// the view, so we'll have to check each possible class
auto dsv = dynamic_cast<D3D11DepthStencilView*>(pView);
auto rtv = dynamic_cast<D3D11RenderTargetView*>(pView);
auto uav = dynamic_cast<D3D11UnorderedAccessView*>(pView);
auto vov = dynamic_cast<D3D11VideoProcessorOutputView*>(pView);
// Retrieve underlying resource view
Rc<DxvkBufferView> bufView;
Rc<DxvkImageView> imgView;
if (dsv != nullptr)
imgView = dsv->GetImageView();
if (rtv != nullptr)
imgView = rtv->GetImageView();
if (uav != nullptr) {
bufView = uav->GetBufferView();
imgView = uav->GetImageView();
}
if (vov != nullptr)
imgView = vov->GetView();
// 3D views are unsupported
if (imgView != nullptr
&& imgView->info().type == VK_IMAGE_VIEW_TYPE_3D)
return;
// Query the view format. We'll have to convert
// the clear color based on the format's data type.
VkFormat format = VK_FORMAT_UNDEFINED;
if (bufView != nullptr)
format = bufView->info().format;
if (imgView != nullptr)
format = imgView->info().format;
if (format == VK_FORMAT_UNDEFINED)
return;
// We'll need the format info to determine the buffer
// element size, and we also need it for depth images.
const DxvkFormatInfo* formatInfo = imageFormatInfo(format);
// Convert the clear color format. ClearView takes
// the clear value for integer formats as a set of
// integral floats, so we'll have to convert.
VkClearValue clearValue = ConvertColorValue(Color, formatInfo);
VkImageAspectFlags clearAspect = formatInfo->aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT);
// Clear all the rectangles that are specified
for (uint32_t i = 0; i < NumRects || i < 1; i++) {
if (pRect) {
if (pRect[i].left >= pRect[i].right
|| pRect[i].top >= pRect[i].bottom)
continue;
}
if (bufView != nullptr) {
VkDeviceSize offset = 0;
VkDeviceSize length = bufView->info().rangeLength / formatInfo->elementSize;
if (pRect) {
offset = pRect[i].left;
length = pRect[i].right - pRect[i].left;
}
EmitCs([
cBufferView = bufView,
cRangeOffset = offset,
cRangeLength = length,
cClearValue = clearValue
] (DxvkContext* ctx) {
ctx->clearBufferView(
cBufferView,
cRangeOffset,
cRangeLength,
cClearValue.color);
});
}
if (imgView != nullptr) {
VkOffset3D offset = { 0, 0, 0 };
VkExtent3D extent = imgView->mipLevelExtent(0);
if (pRect) {
offset = { pRect[i].left, pRect[i].top, 0 };
extent = {
uint32_t(pRect[i].right - pRect[i].left),
uint32_t(pRect[i].bottom - pRect[i].top), 1 };
}
EmitCs([
cImageView = imgView,
cAreaOffset = offset,
cAreaExtent = extent,
cClearAspect = clearAspect,
cClearValue = clearValue
] (DxvkContext* ctx) {
const VkImageUsageFlags rtUsage =
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
bool isFullSize = cImageView->mipLevelExtent(0) == cAreaExtent;
if ((cImageView->info().usage & rtUsage) && isFullSize) {
ctx->clearRenderTarget(
cImageView,
cClearAspect,
cClearValue);
} else {
ctx->clearImageView(
cImageView,
cAreaOffset,
cAreaExtent,
cClearAspect,
cClearValue);
}
});
}
}
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GenerateMips(ID3D11ShaderResourceView* pShaderResourceView) {
D3D10DeviceLock lock = LockContext();
2018-01-20 09:46:54 +01:00
auto view = static_cast<D3D11ShaderResourceView*>(pShaderResourceView);
if (!view || view->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER)
return;
D3D11_COMMON_RESOURCE_DESC resourceDesc = view->GetResourceDesc();
if (!(resourceDesc.MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS))
return;
EmitCs([cDstImageView = view->GetImageView()]
(DxvkContext* ctx) {
ctx->generateMipmaps(cDstImageView, VK_FILTER_LINEAR);
});
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::UpdateSubresource(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pDstResource,
UINT DstSubresource,
const D3D11_BOX* pDstBox,
const void* pSrcData,
UINT SrcRowPitch,
UINT SrcDepthPitch) {
UpdateSubresource1(pDstResource,
DstSubresource, pDstBox, pSrcData,
SrcRowPitch, SrcDepthPitch, 0);
}
void STDMETHODCALLTYPE D3D11DeviceContext::UpdateSubresource1(
ID3D11Resource* pDstResource,
UINT DstSubresource,
const D3D11_BOX* pDstBox,
const void* pSrcData,
UINT SrcRowPitch,
UINT SrcDepthPitch,
UINT CopyFlags) {
D3D10DeviceLock lock = LockContext();
if (!pDstResource)
return;
// Filter out invalid copy flags
CopyFlags &= D3D11_COPY_NO_OVERWRITE | D3D11_COPY_DISCARD;
// We need a different code path for buffers
D3D11_RESOURCE_DIMENSION resourceType;
pDstResource->GetType(&resourceType);
if (resourceType == D3D11_RESOURCE_DIMENSION_BUFFER) {
const auto bufferResource = static_cast<D3D11Buffer*>(pDstResource);
2017-12-15 19:11:10 +01:00
const auto bufferSlice = bufferResource->GetBufferSlice();
VkDeviceSize offset = bufferSlice.offset();
VkDeviceSize size = bufferSlice.length();
if (pDstBox != nullptr) {
offset = pDstBox->left;
size = pDstBox->right - pDstBox->left;
}
if (!size || offset + size > bufferSlice.length())
return;
bool useMap = (bufferSlice.buffer()->memFlags() & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
&& (size == bufferSlice.length() || CopyFlags);
if (useMap) {
D3D11_MAP mapType = (CopyFlags & D3D11_COPY_NO_OVERWRITE)
? D3D11_MAP_WRITE_NO_OVERWRITE
: D3D11_MAP_WRITE_DISCARD;
D3D11_MAPPED_SUBRESOURCE mappedSr;
if (likely(useMap = SUCCEEDED(Map(pDstResource, 0, mapType, 0, &mappedSr)))) {
std::memcpy(reinterpret_cast<char*>(mappedSr.pData) + offset, pSrcData, size);
Unmap(pDstResource, 0);
}
}
if (!useMap) {
DxvkDataSlice dataSlice = AllocUpdateBufferSlice(size);
std::memcpy(dataSlice.ptr(), pSrcData, size);
EmitCs([
cDataBuffer = std::move(dataSlice),
cBufferSlice = bufferSlice.subSlice(offset, size)
] (DxvkContext* ctx) {
ctx->updateBuffer(
cBufferSlice.buffer(),
cBufferSlice.offset(),
cBufferSlice.length(),
cDataBuffer.ptr());
});
}
} else {
2021-06-24 01:41:48 +02:00
D3D11CommonTexture* dstTexture = GetCommonTexture(pDstResource);
2021-06-24 01:41:48 +02:00
if (DstSubresource >= dstTexture->CountSubresources())
return;
2021-06-24 01:41:48 +02:00
VkFormat packedFormat = dstTexture->GetPackedFormat();
auto formatInfo = imageFormatInfo(packedFormat);
2021-06-24 01:41:48 +02:00
auto subresource = dstTexture->GetSubresourceFromIndex(
formatInfo->aspectMask, DstSubresource);
2021-06-24 01:41:48 +02:00
VkExtent3D mipExtent = dstTexture->MipLevelExtent(subresource.mipLevel);
VkOffset3D offset = { 0, 0, 0 };
VkExtent3D extent = mipExtent;
if (pDstBox != nullptr) {
if (pDstBox->left >= pDstBox->right
|| pDstBox->top >= pDstBox->bottom
|| pDstBox->front >= pDstBox->back)
return; // no-op, but legal
offset.x = pDstBox->left;
offset.y = pDstBox->top;
offset.z = pDstBox->front;
extent.width = pDstBox->right - pDstBox->left;
extent.height = pDstBox->bottom - pDstBox->top;
extent.depth = pDstBox->back - pDstBox->front;
}
2021-06-22 02:53:13 +02:00
if (!util::isBlockAligned(offset, extent, formatInfo->blockSize, mipExtent)) {
Logger::err("D3D11: UpdateSubresource1: Unaligned region");
return;
2021-06-22 02:53:13 +02:00
}
auto stagingSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, extent));
util::packImageData(stagingSlice.mapPtr(0),
pSrcData, SrcRowPitch, SrcDepthPitch, 0, 0,
2021-06-24 01:41:48 +02:00
dstTexture->GetVkImageType(), extent, 1,
formatInfo, formatInfo->aspectMask);
2021-06-24 01:41:48 +02:00
UpdateImage(dstTexture, &subresource,
offset, extent, std::move(stagingSlice));
}
2017-10-11 09:51:48 +02:00
}
HRESULT STDMETHODCALLTYPE D3D11DeviceContext::UpdateTileMappings(
ID3D11Resource* pTiledResource,
UINT NumTiledResourceRegions,
const D3D11_TILED_RESOURCE_COORDINATE* pTiledResourceRegionStartCoordinates,
const D3D11_TILE_REGION_SIZE* pTiledResourceRegionSizes,
ID3D11Buffer* pTilePool,
UINT NumRanges,
const UINT* pRangeFlags,
const UINT* pTilePoolStartOffsets,
const UINT* pRangeTileCounts,
UINT Flags) {
bool s_errorShown = false;
if (std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::UpdateTileMappings: Not implemented");
return DXGI_ERROR_INVALID_CALL;
}
void STDMETHODCALLTYPE D3D11DeviceContext::UpdateTiles(
ID3D11Resource* pDestTiledResource,
const D3D11_TILED_RESOURCE_COORDINATE* pDestTileRegionStartCoordinate,
const D3D11_TILE_REGION_SIZE* pDestTileRegionSize,
const void* pSourceTileData,
UINT Flags) {
bool s_errorShown = false;
if (std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::UpdateTiles: Not implemented");
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::SetResourceMinLOD(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pResource,
FLOAT MinLOD) {
bool s_errorShown = false;
if (std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::SetResourceMinLOD: Not implemented");
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
FLOAT STDMETHODCALLTYPE D3D11DeviceContext::GetResourceMinLOD(ID3D11Resource* pResource) {
bool s_errorShown = false;
if (std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::GetResourceMinLOD: Not implemented");
2017-10-11 09:51:48 +02:00
return 0.0f;
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::ResolveSubresource(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pDstResource,
UINT DstSubresource,
ID3D11Resource* pSrcResource,
UINT SrcSubresource,
DXGI_FORMAT Format) {
D3D10DeviceLock lock = LockContext();
bool isSameSubresource = pDstResource == pSrcResource
&& DstSubresource == SrcSubresource;
if (!pDstResource || !pSrcResource || isSameSubresource)
return;
D3D11_RESOURCE_DIMENSION dstResourceType;
D3D11_RESOURCE_DIMENSION srcResourceType;
pDstResource->GetType(&dstResourceType);
pSrcResource->GetType(&srcResourceType);
if (dstResourceType != D3D11_RESOURCE_DIMENSION_TEXTURE2D
|| srcResourceType != D3D11_RESOURCE_DIMENSION_TEXTURE2D) {
Logger::err(str::format(
"D3D11: ResolveSubresource: Incompatible resources",
"\n Dst resource type: ", dstResourceType,
"\n Src resource type: ", srcResourceType));
return;
}
auto dstTexture = static_cast<D3D11Texture2D*>(pDstResource);
auto srcTexture = static_cast<D3D11Texture2D*>(pSrcResource);
D3D11_TEXTURE2D_DESC dstDesc;
D3D11_TEXTURE2D_DESC srcDesc;
dstTexture->GetDesc(&dstDesc);
srcTexture->GetDesc(&srcDesc);
if (dstDesc.SampleDesc.Count != 1) {
Logger::err(str::format(
"D3D11: ResolveSubresource: Invalid sample counts",
"\n Dst sample count: ", dstDesc.SampleDesc.Count,
"\n Src sample count: ", srcDesc.SampleDesc.Count));
return;
}
const D3D11CommonTexture* dstTextureInfo = GetCommonTexture(pDstResource);
const D3D11CommonTexture* srcTextureInfo = GetCommonTexture(pSrcResource);
const DXGI_VK_FORMAT_INFO dstFormatInfo = m_parent->LookupFormat(dstDesc.Format, DXGI_VK_FORMAT_MODE_ANY);
const DXGI_VK_FORMAT_INFO srcFormatInfo = m_parent->LookupFormat(srcDesc.Format, DXGI_VK_FORMAT_MODE_ANY);
auto dstVulkanFormatInfo = imageFormatInfo(dstFormatInfo.Format);
auto srcVulkanFormatInfo = imageFormatInfo(srcFormatInfo.Format);
if (DstSubresource >= dstTextureInfo->CountSubresources()
|| SrcSubresource >= srcTextureInfo->CountSubresources())
return;
const VkImageSubresource dstSubresource =
dstTextureInfo->GetSubresourceFromIndex(
dstVulkanFormatInfo->aspectMask, DstSubresource);
const VkImageSubresource srcSubresource =
srcTextureInfo->GetSubresourceFromIndex(
srcVulkanFormatInfo->aspectMask, SrcSubresource);
const VkImageSubresourceLayers dstSubresourceLayers = {
dstSubresource.aspectMask,
dstSubresource.mipLevel,
dstSubresource.arrayLayer, 1 };
const VkImageSubresourceLayers srcSubresourceLayers = {
srcSubresource.aspectMask,
srcSubresource.mipLevel,
srcSubresource.arrayLayer, 1 };
if (srcDesc.SampleDesc.Count == 1 || m_parent->GetOptions()->disableMsaa) {
EmitCs([
cDstImage = dstTextureInfo->GetImage(),
cSrcImage = srcTextureInfo->GetImage(),
cDstLayers = dstSubresourceLayers,
cSrcLayers = srcSubresourceLayers
] (DxvkContext* ctx) {
ctx->copyImage(
cDstImage, cDstLayers, VkOffset3D { 0, 0, 0 },
cSrcImage, cSrcLayers, VkOffset3D { 0, 0, 0 },
cDstImage->mipLevelExtent(cDstLayers.mipLevel));
});
} else {
const VkFormat format = m_parent->LookupFormat(
Format, DXGI_VK_FORMAT_MODE_ANY).Format;
EmitCs([
cDstImage = dstTextureInfo->GetImage(),
cSrcImage = srcTextureInfo->GetImage(),
cDstSubres = dstSubresourceLayers,
cSrcSubres = srcSubresourceLayers,
cFormat = format
] (DxvkContext* ctx) {
VkImageResolve region;
region.srcSubresource = cSrcSubres;
region.srcOffset = VkOffset3D { 0, 0, 0 };
region.dstSubresource = cDstSubres;
region.dstOffset = VkOffset3D { 0, 0, 0 };
region.extent = cDstImage->mipLevelExtent(cDstSubres.mipLevel);
ctx->resolveImage(cDstImage, cSrcImage, region, cFormat);
});
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DrawAuto() {
D3D10DeviceLock lock = LockContext();
2018-09-04 02:17:21 +02:00
D3D11Buffer* buffer = m_state.ia.vertexBuffers[0].buffer.ptr();
if (buffer == nullptr)
return;
DxvkBufferSlice vtxBuf = buffer->GetBufferSlice();
DxvkBufferSlice ctrBuf = buffer->GetSOCounter();
if (!ctrBuf.defined())
return;
EmitCs([=] (DxvkContext* ctx) {
ctx->drawIndirectXfb(ctrBuf,
vtxBuf.buffer()->getXfbVertexStride(),
vtxBuf.offset());
2018-09-04 02:17:21 +02:00
});
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::Draw(
2017-10-11 09:51:48 +02:00
UINT VertexCount,
UINT StartVertexLocation) {
D3D10DeviceLock lock = LockContext();
EmitCs([=] (DxvkContext* ctx) {
ctx->draw(
VertexCount, 1,
StartVertexLocation, 0);
});
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DrawIndexed(
2017-10-11 09:51:48 +02:00
UINT IndexCount,
UINT StartIndexLocation,
INT BaseVertexLocation) {
D3D10DeviceLock lock = LockContext();
EmitCs([=] (DxvkContext* ctx) {
ctx->drawIndexed(
IndexCount, 1,
StartIndexLocation,
BaseVertexLocation, 0);
});
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DrawInstanced(
2017-10-11 09:51:48 +02:00
UINT VertexCountPerInstance,
UINT InstanceCount,
UINT StartVertexLocation,
UINT StartInstanceLocation) {
D3D10DeviceLock lock = LockContext();
EmitCs([=] (DxvkContext* ctx) {
ctx->draw(
VertexCountPerInstance,
InstanceCount,
StartVertexLocation,
StartInstanceLocation);
});
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DrawIndexedInstanced(
2017-10-11 09:51:48 +02:00
UINT IndexCountPerInstance,
UINT InstanceCount,
UINT StartIndexLocation,
INT BaseVertexLocation,
UINT StartInstanceLocation) {
D3D10DeviceLock lock = LockContext();
EmitCs([=] (DxvkContext* ctx) {
ctx->drawIndexed(
IndexCountPerInstance,
InstanceCount,
StartIndexLocation,
BaseVertexLocation,
StartInstanceLocation);
});
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DrawIndexedInstancedIndirect(
2017-10-11 09:51:48 +02:00
ID3D11Buffer* pBufferForArgs,
UINT AlignedByteOffsetForArgs) {
D3D10DeviceLock lock = LockContext();
SetDrawBuffers(pBufferForArgs, nullptr);
if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDrawIndexedIndirectCommand)))
return;
// If possible, batch up multiple indirect draw calls of
// the same type into one single multiDrawIndirect call
auto cmdData = static_cast<D3D11CmdDrawIndirectData*>(m_cmdData);
auto stride = 0u;
if (cmdData && cmdData->type == D3D11CmdType::DrawIndirectIndexed)
stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndexedIndirectCommand));
if (stride) {
cmdData->count += 1;
cmdData->stride = stride;
} else {
cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>(
[] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) {
ctx->drawIndexedIndirect(data->offset, data->count, data->stride);
});
cmdData->type = D3D11CmdType::DrawIndirectIndexed;
cmdData->offset = AlignedByteOffsetForArgs;
cmdData->count = 1;
cmdData->stride = 0;
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DrawInstancedIndirect(
2017-10-11 09:51:48 +02:00
ID3D11Buffer* pBufferForArgs,
UINT AlignedByteOffsetForArgs) {
D3D10DeviceLock lock = LockContext();
SetDrawBuffers(pBufferForArgs, nullptr);
if (!ValidateDrawBufferSize(pBufferForArgs, AlignedByteOffsetForArgs, sizeof(VkDrawIndirectCommand)))
return;
// If possible, batch up multiple indirect draw calls of
// the same type into one single multiDrawIndirect call
auto cmdData = static_cast<D3D11CmdDrawIndirectData*>(m_cmdData);
auto stride = 0u;
if (cmdData && cmdData->type == D3D11CmdType::DrawIndirect)
stride = GetIndirectCommandStride(cmdData, AlignedByteOffsetForArgs, sizeof(VkDrawIndirectCommand));
if (stride) {
cmdData->count += 1;
cmdData->stride = stride;
} else {
cmdData = EmitCsCmd<D3D11CmdDrawIndirectData>(
[] (DxvkContext* ctx, const D3D11CmdDrawIndirectData* data) {
ctx->drawIndirect(data->offset, data->count, data->stride);
});
cmdData->type = D3D11CmdType::DrawIndirect;
cmdData->offset = AlignedByteOffsetForArgs;
cmdData->count = 1;
cmdData->stride = 0;
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::Dispatch(
2017-10-11 09:51:48 +02:00
UINT ThreadGroupCountX,
UINT ThreadGroupCountY,
UINT ThreadGroupCountZ) {
D3D10DeviceLock lock = LockContext();
EmitCs([=] (DxvkContext* ctx) {
ctx->dispatch(
ThreadGroupCountX,
ThreadGroupCountY,
ThreadGroupCountZ);
});
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DispatchIndirect(
2017-10-11 09:51:48 +02:00
ID3D11Buffer* pBufferForArgs,
UINT AlignedByteOffsetForArgs) {
D3D10DeviceLock lock = LockContext();
SetDrawBuffers(pBufferForArgs, nullptr);
EmitCs([cOffset = AlignedByteOffsetForArgs]
(DxvkContext* ctx) {
ctx->dispatchIndirect(cOffset);
});
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IASetInputLayout(ID3D11InputLayout* pInputLayout) {
D3D10DeviceLock lock = LockContext();
2018-03-10 11:44:27 +01:00
auto inputLayout = static_cast<D3D11InputLayout*>(pInputLayout);
if (m_state.ia.inputLayout != inputLayout) {
bool equal = false;
// Some games (e.g. Grim Dawn) create lots and lots of
// identical input layouts, so we'll only apply the state
// if the input layouts has actually changed between calls.
if (m_state.ia.inputLayout != nullptr && inputLayout != nullptr)
equal = m_state.ia.inputLayout->Compare(inputLayout);
m_state.ia.inputLayout = inputLayout;
if (!equal)
ApplyInputLayout();
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY Topology) {
D3D10DeviceLock lock = LockContext();
if (m_state.ia.primitiveTopology != Topology) {
m_state.ia.primitiveTopology = Topology;
2018-03-10 11:44:27 +01:00
ApplyPrimitiveTopology();
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IASetVertexBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppVertexBuffers,
const UINT* pStrides,
const UINT* pOffsets) {
D3D10DeviceLock lock = LockContext();
for (uint32_t i = 0; i < NumBuffers; i++) {
auto newBuffer = static_cast<D3D11Buffer*>(ppVertexBuffers[i]);
bool needsUpdate = m_state.ia.vertexBuffers[StartSlot + i].buffer != newBuffer;
if (needsUpdate)
m_state.ia.vertexBuffers[StartSlot + i].buffer = newBuffer;
needsUpdate |= m_state.ia.vertexBuffers[StartSlot + i].offset != pOffsets[i]
|| m_state.ia.vertexBuffers[StartSlot + i].stride != pStrides[i];
if (needsUpdate) {
m_state.ia.vertexBuffers[StartSlot + i].offset = pOffsets[i];
m_state.ia.vertexBuffers[StartSlot + i].stride = pStrides[i];
BindVertexBuffer(StartSlot + i, newBuffer, pOffsets[i], pStrides[i]);
}
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IASetIndexBuffer(
2017-10-11 09:51:48 +02:00
ID3D11Buffer* pIndexBuffer,
DXGI_FORMAT Format,
UINT Offset) {
D3D10DeviceLock lock = LockContext();
auto newBuffer = static_cast<D3D11Buffer*>(pIndexBuffer);
bool needsUpdate = m_state.ia.indexBuffer.buffer != newBuffer;
if (needsUpdate)
m_state.ia.indexBuffer.buffer = newBuffer;
needsUpdate |= m_state.ia.indexBuffer.offset != Offset
|| m_state.ia.indexBuffer.format != Format;
if (needsUpdate) {
m_state.ia.indexBuffer.offset = Offset;
m_state.ia.indexBuffer.format = Format;
BindIndexBuffer(newBuffer, Offset, Format);
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IAGetInputLayout(ID3D11InputLayout** ppInputLayout) {
D3D10DeviceLock lock = LockContext();
*ppInputLayout = m_state.ia.inputLayout.ref();
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IAGetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY* pTopology) {
D3D10DeviceLock lock = LockContext();
*pTopology = m_state.ia.primitiveTopology;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IAGetVertexBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppVertexBuffers,
UINT* pStrides,
UINT* pOffsets) {
D3D10DeviceLock lock = LockContext();
for (uint32_t i = 0; i < NumBuffers; i++) {
const bool inRange = StartSlot + i < m_state.ia.vertexBuffers.size();
if (ppVertexBuffers != nullptr) {
ppVertexBuffers[i] = inRange
? m_state.ia.vertexBuffers[StartSlot + i].buffer.ref()
: nullptr;
}
if (pStrides != nullptr) {
pStrides[i] = inRange
? m_state.ia.vertexBuffers[StartSlot + i].stride
: 0u;
}
if (pOffsets != nullptr) {
pOffsets[i] = inRange
? m_state.ia.vertexBuffers[StartSlot + i].offset
: 0u;
}
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IAGetIndexBuffer(
ID3D11Buffer** ppIndexBuffer,
DXGI_FORMAT* pFormat,
UINT* pOffset) {
D3D10DeviceLock lock = LockContext();
if (ppIndexBuffer != nullptr)
*ppIndexBuffer = m_state.ia.indexBuffer.buffer.ref();
if (pFormat != nullptr)
*pFormat = m_state.ia.indexBuffer.format;
if (pOffset != nullptr)
*pOffset = m_state.ia.indexBuffer.offset;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::VSSetShader(
2017-10-11 09:51:48 +02:00
ID3D11VertexShader* pVertexShader,
ID3D11ClassInstance* const* ppClassInstances,
UINT NumClassInstances) {
D3D10DeviceLock lock = LockContext();
2017-12-07 10:12:48 +01:00
auto shader = static_cast<D3D11VertexShader*>(pVertexShader);
if (NumClassInstances != 0)
Logger::err("D3D11: Class instances not supported");
2017-12-07 10:12:48 +01:00
if (m_state.vs.shader != shader) {
m_state.vs.shader = shader;
BindShader<DxbcProgramType::VertexShader>(GetCommonShader(shader));
2017-12-07 10:12:48 +01:00
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::VSSetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers<DxbcProgramType::VertexShader>(
m_state.vs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::VSSetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers,
const UINT* pFirstConstant,
const UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers1<DxbcProgramType::VertexShader>(
m_state.vs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::VSSetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView* const* ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
SetShaderResources<DxbcProgramType::VertexShader>(
m_state.vs.shaderResources,
StartSlot, NumViews,
ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::VSSetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState* const* ppSamplers) {
D3D10DeviceLock lock = LockContext();
SetSamplers<DxbcProgramType::VertexShader>(
m_state.vs.samplers,
2017-12-09 21:17:26 +01:00
StartSlot, NumSamplers,
ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::VSGetShader(
2017-10-11 09:51:48 +02:00
ID3D11VertexShader** ppVertexShader,
ID3D11ClassInstance** ppClassInstances,
UINT* pNumClassInstances) {
D3D10DeviceLock lock = LockContext();
2017-12-11 14:21:24 +01:00
if (ppVertexShader != nullptr)
*ppVertexShader = m_state.vs.shader.ref();
if (pNumClassInstances != nullptr)
2017-12-11 14:21:24 +01:00
*pNumClassInstances = 0;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::VSGetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.vs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
nullptr, nullptr);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::VSGetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers,
UINT* pFirstConstant,
UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.vs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::VSGetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView** ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
GetShaderResources(m_state.vs.shaderResources,
StartSlot, NumViews, ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::VSGetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState** ppSamplers) {
D3D10DeviceLock lock = LockContext();
GetSamplers(m_state.vs.samplers,
StartSlot, NumSamplers, ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::HSSetShader(
2017-10-11 09:51:48 +02:00
ID3D11HullShader* pHullShader,
ID3D11ClassInstance* const* ppClassInstances,
UINT NumClassInstances) {
D3D10DeviceLock lock = LockContext();
auto shader = static_cast<D3D11HullShader*>(pHullShader);
if (NumClassInstances != 0)
Logger::err("D3D11: Class instances not supported");
if (m_state.hs.shader != shader) {
m_state.hs.shader = shader;
BindShader<DxbcProgramType::HullShader>(GetCommonShader(shader));
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::HSSetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView* const* ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
SetShaderResources<DxbcProgramType::HullShader>(
m_state.hs.shaderResources,
StartSlot, NumViews,
ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::HSSetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers<DxbcProgramType::HullShader>(
m_state.hs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::HSSetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers,
const UINT* pFirstConstant,
const UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers1<DxbcProgramType::HullShader>(
m_state.hs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::HSSetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState* const* ppSamplers) {
D3D10DeviceLock lock = LockContext();
SetSamplers<DxbcProgramType::HullShader>(
m_state.hs.samplers,
StartSlot, NumSamplers,
ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::HSGetShader(
2017-10-11 09:51:48 +02:00
ID3D11HullShader** ppHullShader,
ID3D11ClassInstance** ppClassInstances,
UINT* pNumClassInstances) {
D3D10DeviceLock lock = LockContext();
if (ppHullShader != nullptr)
*ppHullShader = m_state.hs.shader.ref();
if (pNumClassInstances != nullptr)
*pNumClassInstances = 0;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::HSGetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.hs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
nullptr, nullptr);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::HSGetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers,
UINT* pFirstConstant,
UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.hs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::HSGetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView** ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
GetShaderResources(m_state.hs.shaderResources,
StartSlot, NumViews, ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::HSGetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState** ppSamplers) {
D3D10DeviceLock lock = LockContext();
GetSamplers(m_state.hs.samplers,
StartSlot, NumSamplers, ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DSSetShader(
2017-10-11 09:51:48 +02:00
ID3D11DomainShader* pDomainShader,
ID3D11ClassInstance* const* ppClassInstances,
UINT NumClassInstances) {
D3D10DeviceLock lock = LockContext();
auto shader = static_cast<D3D11DomainShader*>(pDomainShader);
if (NumClassInstances != 0)
Logger::err("D3D11: Class instances not supported");
if (m_state.ds.shader != shader) {
m_state.ds.shader = shader;
BindShader<DxbcProgramType::DomainShader>(GetCommonShader(shader));
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DSSetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView* const* ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
SetShaderResources<DxbcProgramType::DomainShader>(
m_state.ds.shaderResources,
StartSlot, NumViews,
ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DSSetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers<DxbcProgramType::DomainShader>(
m_state.ds.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::DSSetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers,
const UINT* pFirstConstant,
const UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers1<DxbcProgramType::DomainShader>(
m_state.ds.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DSSetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState* const* ppSamplers) {
D3D10DeviceLock lock = LockContext();
SetSamplers<DxbcProgramType::DomainShader>(
m_state.ds.samplers,
StartSlot, NumSamplers,
ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DSGetShader(
2017-10-11 09:51:48 +02:00
ID3D11DomainShader** ppDomainShader,
ID3D11ClassInstance** ppClassInstances,
UINT* pNumClassInstances) {
D3D10DeviceLock lock = LockContext();
if (ppDomainShader != nullptr)
*ppDomainShader = m_state.ds.shader.ref();
if (pNumClassInstances != nullptr)
*pNumClassInstances = 0;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DSGetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.ds.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
nullptr, nullptr);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::DSGetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers,
UINT* pFirstConstant,
UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.ds.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DSGetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView** ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
GetShaderResources(m_state.ds.shaderResources,
StartSlot, NumViews, ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DSGetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState** ppSamplers) {
D3D10DeviceLock lock = LockContext();
GetSamplers(m_state.ds.samplers,
StartSlot, NumSamplers, ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GSSetShader(
2017-10-11 09:51:48 +02:00
ID3D11GeometryShader* pShader,
ID3D11ClassInstance* const* ppClassInstances,
UINT NumClassInstances) {
D3D10DeviceLock lock = LockContext();
2017-12-18 12:53:53 +01:00
auto shader = static_cast<D3D11GeometryShader*>(pShader);
if (NumClassInstances != 0)
Logger::err("D3D11: Class instances not supported");
2017-12-18 12:53:53 +01:00
if (m_state.gs.shader != shader) {
m_state.gs.shader = shader;
BindShader<DxbcProgramType::GeometryShader>(GetCommonShader(shader));
2017-12-18 12:53:53 +01:00
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GSSetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers<DxbcProgramType::GeometryShader>(
m_state.gs.constantBuffers,
2017-12-18 12:53:53 +01:00
StartSlot, NumBuffers,
ppConstantBuffers);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::GSSetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers,
const UINT* pFirstConstant,
const UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers1<DxbcProgramType::GeometryShader>(
m_state.gs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GSSetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView* const* ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
SetShaderResources<DxbcProgramType::GeometryShader>(
m_state.gs.shaderResources,
2017-12-18 12:53:53 +01:00
StartSlot, NumViews,
ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GSSetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState* const* ppSamplers) {
D3D10DeviceLock lock = LockContext();
SetSamplers<DxbcProgramType::GeometryShader>(
m_state.gs.samplers,
2017-12-18 12:53:53 +01:00
StartSlot, NumSamplers,
ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GSGetShader(
2017-10-11 09:51:48 +02:00
ID3D11GeometryShader** ppGeometryShader,
ID3D11ClassInstance** ppClassInstances,
UINT* pNumClassInstances) {
D3D10DeviceLock lock = LockContext();
2017-12-18 12:53:53 +01:00
if (ppGeometryShader != nullptr)
*ppGeometryShader = m_state.gs.shader.ref();
if (pNumClassInstances != nullptr)
2017-12-18 12:53:53 +01:00
*pNumClassInstances = 0;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GSGetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.gs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
nullptr, nullptr);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::GSGetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers,
UINT* pFirstConstant,
UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.gs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GSGetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView** ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
GetShaderResources(m_state.gs.shaderResources,
StartSlot, NumViews, ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GSGetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState** ppSamplers) {
D3D10DeviceLock lock = LockContext();
GetSamplers(m_state.gs.samplers,
StartSlot, NumSamplers, ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::PSSetShader(
2017-10-11 09:51:48 +02:00
ID3D11PixelShader* pPixelShader,
ID3D11ClassInstance* const* ppClassInstances,
UINT NumClassInstances) {
D3D10DeviceLock lock = LockContext();
2017-12-07 10:12:48 +01:00
auto shader = static_cast<D3D11PixelShader*>(pPixelShader);
if (NumClassInstances != 0)
Logger::err("D3D11: Class instances not supported");
2017-12-07 10:12:48 +01:00
if (m_state.ps.shader != shader) {
m_state.ps.shader = shader;
BindShader<DxbcProgramType::PixelShader>(GetCommonShader(shader));
2017-12-07 10:12:48 +01:00
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::PSSetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers<DxbcProgramType::PixelShader>(
m_state.ps.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::PSSetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers,
const UINT* pFirstConstant,
const UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers1<DxbcProgramType::PixelShader>(
m_state.ps.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::PSSetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView* const* ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
SetShaderResources<DxbcProgramType::PixelShader>(
m_state.ps.shaderResources,
StartSlot, NumViews,
ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::PSSetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState* const* ppSamplers) {
D3D10DeviceLock lock = LockContext();
SetSamplers<DxbcProgramType::PixelShader>(
m_state.ps.samplers,
2017-12-09 21:17:26 +01:00
StartSlot, NumSamplers,
ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::PSGetShader(
2017-10-11 09:51:48 +02:00
ID3D11PixelShader** ppPixelShader,
ID3D11ClassInstance** ppClassInstances,
UINT* pNumClassInstances) {
D3D10DeviceLock lock = LockContext();
2017-12-11 14:21:24 +01:00
if (ppPixelShader != nullptr)
*ppPixelShader = m_state.ps.shader.ref();
if (pNumClassInstances != nullptr)
2017-12-11 14:21:24 +01:00
*pNumClassInstances = 0;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::PSGetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.ps.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
nullptr, nullptr);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::PSGetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers,
UINT* pFirstConstant,
UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.ps.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::PSGetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView** ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
GetShaderResources(m_state.ps.shaderResources,
StartSlot, NumViews, ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::PSGetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState** ppSamplers) {
D3D10DeviceLock lock = LockContext();
GetSamplers(m_state.ps.samplers,
StartSlot, NumSamplers, ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSSetShader(
2017-10-11 09:51:48 +02:00
ID3D11ComputeShader* pComputeShader,
ID3D11ClassInstance* const* ppClassInstances,
UINT NumClassInstances) {
D3D10DeviceLock lock = LockContext();
2017-12-21 17:27:40 +01:00
auto shader = static_cast<D3D11ComputeShader*>(pComputeShader);
if (NumClassInstances != 0)
Logger::err("D3D11: Class instances not supported");
2017-12-21 17:27:40 +01:00
if (m_state.cs.shader != shader) {
m_state.cs.shader = shader;
BindShader<DxbcProgramType::ComputeShader>(GetCommonShader(shader));
2017-12-21 17:27:40 +01:00
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSSetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers<DxbcProgramType::ComputeShader>(
m_state.cs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::CSSetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers,
const UINT* pFirstConstant,
const UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
SetConstantBuffers1<DxbcProgramType::ComputeShader>(
m_state.cs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSSetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView* const* ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
SetShaderResources<DxbcProgramType::ComputeShader>(
m_state.cs.shaderResources,
StartSlot, NumViews,
ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSSetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState* const* ppSamplers) {
D3D10DeviceLock lock = LockContext();
SetSamplers<DxbcProgramType::ComputeShader>(
m_state.cs.samplers,
StartSlot, NumSamplers,
ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSSetUnorderedAccessViews(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
const UINT* pUAVInitialCounts) {
D3D10DeviceLock lock = LockContext();
if (TestRtvUavHazards(0, nullptr, NumUAVs, ppUnorderedAccessViews))
return;
// Unbind previously bound conflicting UAVs
uint32_t uavSlotId = computeUavBinding (DxbcProgramType::ComputeShader, 0);
uint32_t ctrSlotId = computeUavCounterBinding(DxbcProgramType::ComputeShader, 0);
int32_t uavId = m_state.cs.uavMask.findNext(0);
while (uavId >= 0) {
if (uint32_t(uavId) < StartSlot || uint32_t(uavId) >= StartSlot + NumUAVs) {
for (uint32_t i = 0; i < NumUAVs; i++) {
auto uav = static_cast<D3D11UnorderedAccessView*>(ppUnorderedAccessViews[i]);
if (CheckViewOverlap(uav, m_state.cs.unorderedAccessViews[uavId].ptr())) {
m_state.cs.unorderedAccessViews[uavId] = nullptr;
m_state.cs.uavMask.clr(uavId);
BindUnorderedAccessView(
uavSlotId + uavId, nullptr,
ctrSlotId + uavId, ~0u);
}
}
uavId = m_state.cs.uavMask.findNext(uavId + 1);
} else {
uavId = m_state.cs.uavMask.findNext(StartSlot + NumUAVs);
}
}
// Actually bind the given UAVs
for (uint32_t i = 0; i < NumUAVs; i++) {
auto uav = static_cast<D3D11UnorderedAccessView*>(ppUnorderedAccessViews[i]);
auto ctr = pUAVInitialCounts ? pUAVInitialCounts[i] : ~0u;
if (m_state.cs.unorderedAccessViews[StartSlot + i] != uav || ctr != ~0u) {
m_state.cs.unorderedAccessViews[StartSlot + i] = uav;
m_state.cs.uavMask.set(StartSlot + i, uav != nullptr);
BindUnorderedAccessView(
uavSlotId + StartSlot + i, uav,
ctrSlotId + StartSlot + i, ctr);
ResolveCsSrvHazards(uav);
}
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSGetShader(
2017-10-11 09:51:48 +02:00
ID3D11ComputeShader** ppComputeShader,
ID3D11ClassInstance** ppClassInstances,
UINT* pNumClassInstances) {
D3D10DeviceLock lock = LockContext();
if (ppComputeShader != nullptr)
*ppComputeShader = m_state.cs.shader.ref();
if (pNumClassInstances != nullptr)
*pNumClassInstances = 0;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSGetConstantBuffers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.cs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
nullptr, nullptr);
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::CSGetConstantBuffers1(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers,
UINT* pFirstConstant,
UINT* pNumConstants) {
D3D10DeviceLock lock = LockContext();
GetConstantBuffers(
m_state.cs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers,
pFirstConstant,
pNumConstants);
}
2017-10-11 09:51:48 +02:00
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSGetShaderResources(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView** ppShaderResourceViews) {
D3D10DeviceLock lock = LockContext();
GetShaderResources(m_state.cs.shaderResources,
StartSlot, NumViews, ppShaderResourceViews);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSGetSamplers(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState** ppSamplers) {
D3D10DeviceLock lock = LockContext();
GetSamplers(m_state.cs.samplers,
StartSlot, NumSamplers, ppSamplers);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::CSGetUnorderedAccessViews(
2017-10-11 09:51:48 +02:00
UINT StartSlot,
UINT NumUAVs,
ID3D11UnorderedAccessView** ppUnorderedAccessViews) {
D3D10DeviceLock lock = LockContext();
for (uint32_t i = 0; i < NumUAVs; i++) {
ppUnorderedAccessViews[i] = StartSlot + i < m_state.cs.unorderedAccessViews.size()
? m_state.cs.unorderedAccessViews[StartSlot + i].ref()
: nullptr;
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::OMSetRenderTargets(
2017-10-11 09:51:48 +02:00
UINT NumViews,
ID3D11RenderTargetView* const* ppRenderTargetViews,
ID3D11DepthStencilView* pDepthStencilView) {
OMSetRenderTargetsAndUnorderedAccessViews(
NumViews, ppRenderTargetViews, pDepthStencilView,
NumViews, 0, nullptr, nullptr);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews(
2017-10-11 09:51:48 +02:00
UINT NumRTVs,
ID3D11RenderTargetView* const* ppRenderTargetViews,
ID3D11DepthStencilView* pDepthStencilView,
UINT UAVStartSlot,
UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
const UINT* pUAVInitialCounts) {
D3D10DeviceLock lock = LockContext();
if (TestRtvUavHazards(NumRTVs, ppRenderTargetViews, NumUAVs, ppUnorderedAccessViews))
return;
bool needsUpdate = false;
if (likely(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)) {
// Native D3D11 does not change the render targets if
// the parameters passed to this method are invalid.
if (!ValidateRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView))
return;
for (uint32_t i = 0; i < m_state.om.renderTargetViews.size(); i++) {
auto rtv = i < NumRTVs
? static_cast<D3D11RenderTargetView*>(ppRenderTargetViews[i])
: nullptr;
if (m_state.om.renderTargetViews[i] != rtv) {
m_state.om.renderTargetViews[i] = rtv;
needsUpdate = true;
ResolveOmSrvHazards(rtv);
if (NumUAVs == D3D11_KEEP_UNORDERED_ACCESS_VIEWS)
ResolveOmUavHazards(rtv);
}
}
auto dsv = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
if (m_state.om.depthStencilView != dsv) {
m_state.om.depthStencilView = dsv;
needsUpdate = true;
ResolveOmSrvHazards(dsv);
}
m_state.om.maxRtv = NumRTVs;
}
if (unlikely(NumUAVs || m_state.om.maxUav)) {
uint32_t uavSlotId = computeUavBinding (DxbcProgramType::PixelShader, 0);
uint32_t ctrSlotId = computeUavCounterBinding(DxbcProgramType::PixelShader, 0);
if (likely(NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS)) {
uint32_t newMaxUav = NumUAVs ? UAVStartSlot + NumUAVs : 0;
uint32_t oldMaxUav = std::exchange(m_state.om.maxUav, newMaxUav);
for (uint32_t i = 0; i < std::max(oldMaxUav, newMaxUav); i++) {
D3D11UnorderedAccessView* uav = nullptr;
uint32_t ctr = ~0u;
if (i >= UAVStartSlot && i < UAVStartSlot + NumUAVs) {
uav = static_cast<D3D11UnorderedAccessView*>(ppUnorderedAccessViews[i - UAVStartSlot]);
ctr = pUAVInitialCounts ? pUAVInitialCounts[i - UAVStartSlot] : ~0u;
}
if (m_state.ps.unorderedAccessViews[i] != uav || ctr != ~0u) {
m_state.ps.unorderedAccessViews[i] = uav;
BindUnorderedAccessView(
uavSlotId + i, uav,
ctrSlotId + i, ctr);
ResolveOmSrvHazards(uav);
if (NumRTVs == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)
needsUpdate |= ResolveOmRtvHazards(uav);
}
}
}
}
if (needsUpdate)
BindFramebuffer();
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::OMSetBlendState(
2017-10-11 09:51:48 +02:00
ID3D11BlendState* pBlendState,
const FLOAT BlendFactor[4],
UINT SampleMask) {
D3D10DeviceLock lock = LockContext();
2018-03-10 12:11:17 +01:00
auto blendState = static_cast<D3D11BlendState*>(pBlendState);
if (m_state.om.cbState != blendState
|| m_state.om.sampleMask != SampleMask) {
m_state.om.cbState = blendState;
m_state.om.sampleMask = SampleMask;
ApplyBlendState();
}
if (BlendFactor != nullptr) {
for (uint32_t i = 0; i < 4; i++)
m_state.om.blendFactor[i] = BlendFactor[i];
ApplyBlendFactor();
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::OMSetDepthStencilState(
2017-10-11 09:51:48 +02:00
ID3D11DepthStencilState* pDepthStencilState,
UINT StencilRef) {
D3D10DeviceLock lock = LockContext();
2018-03-10 12:11:17 +01:00
auto depthStencilState = static_cast<D3D11DepthStencilState*>(pDepthStencilState);
if (m_state.om.dsState != depthStencilState) {
m_state.om.dsState = depthStencilState;
ApplyDepthStencilState();
}
if (m_state.om.stencilRef != StencilRef) {
m_state.om.stencilRef = StencilRef;
ApplyStencilRef();
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::OMGetRenderTargets(
2017-10-11 09:51:48 +02:00
UINT NumViews,
ID3D11RenderTargetView** ppRenderTargetViews,
ID3D11DepthStencilView** ppDepthStencilView) {
D3D10DeviceLock lock = LockContext();
if (ppRenderTargetViews != nullptr) {
for (UINT i = 0; i < NumViews; i++) {
ppRenderTargetViews[i] = i < m_state.om.renderTargetViews.size()
? m_state.om.renderTargetViews[i].ref()
: nullptr;
}
}
if (ppDepthStencilView != nullptr)
*ppDepthStencilView = m_state.om.depthStencilView.ref();
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::OMGetRenderTargetsAndUnorderedAccessViews(
2017-10-11 09:51:48 +02:00
UINT NumRTVs,
ID3D11RenderTargetView** ppRenderTargetViews,
ID3D11DepthStencilView** ppDepthStencilView,
UINT UAVStartSlot,
UINT NumUAVs,
ID3D11UnorderedAccessView** ppUnorderedAccessViews) {
OMGetRenderTargets(NumRTVs, ppRenderTargetViews, ppDepthStencilView);
D3D10DeviceLock lock = LockContext();
if (ppUnorderedAccessViews != nullptr) {
for (UINT i = 0; i < NumUAVs; i++) {
ppUnorderedAccessViews[i] = UAVStartSlot + i < m_state.ps.unorderedAccessViews.size()
? m_state.ps.unorderedAccessViews[UAVStartSlot + i].ref()
: nullptr;
}
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::OMGetBlendState(
2017-10-11 09:51:48 +02:00
ID3D11BlendState** ppBlendState,
FLOAT BlendFactor[4],
UINT* pSampleMask) {
D3D10DeviceLock lock = LockContext();
2017-12-11 14:21:24 +01:00
if (ppBlendState != nullptr)
*ppBlendState = ref(m_state.om.cbState);
2017-12-11 14:21:24 +01:00
if (BlendFactor != nullptr)
std::memcpy(BlendFactor, m_state.om.blendFactor, sizeof(FLOAT) * 4);
if (pSampleMask != nullptr)
*pSampleMask = m_state.om.sampleMask;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::OMGetDepthStencilState(
2017-10-11 09:51:48 +02:00
ID3D11DepthStencilState** ppDepthStencilState,
UINT* pStencilRef) {
D3D10DeviceLock lock = LockContext();
2017-12-11 14:21:24 +01:00
if (ppDepthStencilState != nullptr)
*ppDepthStencilState = ref(m_state.om.dsState);
2017-12-11 14:21:24 +01:00
if (pStencilRef != nullptr)
*pStencilRef = m_state.om.stencilRef;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::RSSetState(ID3D11RasterizerState* pRasterizerState) {
D3D10DeviceLock lock = LockContext();
2018-03-10 12:11:17 +01:00
auto rasterizerState = static_cast<D3D11RasterizerState*>(pRasterizerState);
bool currScissorEnable = m_state.rs.state != nullptr
? m_state.rs.state->Desc()->ScissorEnable
: false;
bool nextScissorEnable = rasterizerState != nullptr
? rasterizerState->Desc()->ScissorEnable
: false;
if (m_state.rs.state != rasterizerState) {
m_state.rs.state = rasterizerState;
// In D3D11, the rasterizer state defines whether the
// scissor test is enabled, so we have to update the
// scissor rectangles as well.
ApplyRasterizerState();
if (currScissorEnable != nextScissorEnable)
ApplyViewportState();
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::RSSetViewports(
2017-10-11 09:51:48 +02:00
UINT NumViewports,
const D3D11_VIEWPORT* pViewports) {
D3D10DeviceLock lock = LockContext();
if (unlikely(NumViewports > m_state.rs.viewports.size()))
return;
bool dirty = m_state.rs.numViewports != NumViewports;
m_state.rs.numViewports = NumViewports;
for (uint32_t i = 0; i < NumViewports; i++) {
const D3D11_VIEWPORT& vp = m_state.rs.viewports[i];
dirty |= vp.TopLeftX != pViewports[i].TopLeftX
|| vp.TopLeftY != pViewports[i].TopLeftY
|| vp.Width != pViewports[i].Width
|| vp.Height != pViewports[i].Height
|| vp.MinDepth != pViewports[i].MinDepth
|| vp.MaxDepth != pViewports[i].MaxDepth;
m_state.rs.viewports[i] = pViewports[i];
}
if (dirty)
ApplyViewportState();
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::RSSetScissorRects(
2017-10-11 09:51:48 +02:00
UINT NumRects,
const D3D11_RECT* pRects) {
D3D10DeviceLock lock = LockContext();
if (unlikely(NumRects > m_state.rs.scissors.size()))
return;
bool dirty = m_state.rs.numScissors != NumRects;
m_state.rs.numScissors = NumRects;
for (uint32_t i = 0; i < NumRects; i++) {
if (pRects[i].bottom >= pRects[i].top
&& pRects[i].right >= pRects[i].left) {
const D3D11_RECT& sr = m_state.rs.scissors[i];
dirty |= sr.top != pRects[i].top
|| sr.left != pRects[i].left
|| sr.bottom != pRects[i].bottom
|| sr.right != pRects[i].right;
m_state.rs.scissors[i] = pRects[i];
}
}
if (m_state.rs.state != nullptr && dirty) {
D3D11_RASTERIZER_DESC rsDesc;
m_state.rs.state->GetDesc(&rsDesc);
if (rsDesc.ScissorEnable)
ApplyViewportState();
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::RSGetState(ID3D11RasterizerState** ppRasterizerState) {
D3D10DeviceLock lock = LockContext();
2017-12-11 14:21:24 +01:00
if (ppRasterizerState != nullptr)
*ppRasterizerState = ref(m_state.rs.state);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::RSGetViewports(
2017-10-11 09:51:48 +02:00
UINT* pNumViewports,
D3D11_VIEWPORT* pViewports) {
D3D10DeviceLock lock = LockContext();
uint32_t numWritten = m_state.rs.numViewports;
if (pViewports) {
numWritten = std::min(numWritten, *pNumViewports);
for (uint32_t i = 0; i < *pNumViewports; i++) {
if (i < m_state.rs.numViewports) {
2019-08-26 16:11:12 +02:00
pViewports[i] = m_state.rs.viewports[i];
} else {
pViewports[i].TopLeftX = 0.0f;
pViewports[i].TopLeftY = 0.0f;
pViewports[i].Width = 0.0f;
pViewports[i].Height = 0.0f;
pViewports[i].MinDepth = 0.0f;
pViewports[i].MaxDepth = 0.0f;
}
}
}
*pNumViewports = numWritten;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::RSGetScissorRects(
2017-10-11 09:51:48 +02:00
UINT* pNumRects,
D3D11_RECT* pRects) {
D3D10DeviceLock lock = LockContext();
uint32_t numWritten = m_state.rs.numScissors;
if (pRects) {
numWritten = std::min(numWritten, *pNumRects);
for (uint32_t i = 0; i < *pNumRects; i++) {
if (i < m_state.rs.numScissors) {
2019-08-26 16:11:12 +02:00
pRects[i] = m_state.rs.scissors[i];
} else {
pRects[i].left = 0;
pRects[i].top = 0;
pRects[i].right = 0;
pRects[i].bottom = 0;
}
}
}
*pNumRects = m_state.rs.numScissors;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::SOSetTargets(
2017-10-11 09:51:48 +02:00
UINT NumBuffers,
ID3D11Buffer* const* ppSOTargets,
const UINT* pOffsets) {
D3D10DeviceLock lock = LockContext();
for (uint32_t i = 0; i < NumBuffers; i++) {
D3D11Buffer* buffer = static_cast<D3D11Buffer*>(ppSOTargets[i]);
UINT offset = pOffsets != nullptr ? pOffsets[i] : 0;
m_state.so.targets[i].buffer = buffer;
m_state.so.targets[i].offset = offset;
}
for (uint32_t i = NumBuffers; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) {
m_state.so.targets[i].buffer = nullptr;
m_state.so.targets[i].offset = 0;
}
for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) {
BindXfbBuffer(i,
m_state.so.targets[i].buffer.ptr(),
m_state.so.targets[i].offset);
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::SOGetTargets(
2017-10-11 09:51:48 +02:00
UINT NumBuffers,
ID3D11Buffer** ppSOTargets) {
D3D10DeviceLock lock = LockContext();
for (uint32_t i = 0; i < NumBuffers; i++) {
ppSOTargets[i] = i < m_state.so.targets.size()
? m_state.so.targets[i].buffer.ref()
: nullptr;
}
2017-10-11 09:51:48 +02:00
}
void STDMETHODCALLTYPE D3D11DeviceContext::SOGetTargetsWithOffsets(
UINT NumBuffers,
ID3D11Buffer** ppSOTargets,
UINT* pOffsets) {
D3D10DeviceLock lock = LockContext();
for (uint32_t i = 0; i < NumBuffers; i++) {
const bool inRange = i < m_state.so.targets.size();
if (ppSOTargets != nullptr) {
ppSOTargets[i] = inRange
? m_state.so.targets[i].buffer.ref()
: nullptr;
}
if (pOffsets != nullptr) {
pOffsets[i] = inRange
? m_state.so.targets[i].offset
: 0u;
}
}
}
BOOL STDMETHODCALLTYPE D3D11DeviceContext::IsAnnotationEnabled() {
return m_device->instance()->extensions().extDebugUtils;
}
void STDMETHODCALLTYPE D3D11DeviceContext::SetMarkerInt(
LPCWSTR pLabel,
INT Data) {
// Not implemented in the backend, ignore
}
void STDMETHODCALLTYPE D3D11DeviceContext::BeginEventInt(
LPCWSTR pLabel,
INT Data) {
// Not implemented in the backend, ignore
}
void STDMETHODCALLTYPE D3D11DeviceContext::EndEvent() {
// Not implemented in the backend, ignore
}
2019-09-16 13:12:13 +02:00
void STDMETHODCALLTYPE D3D11DeviceContext::GetHardwareProtectionState(
BOOL* pHwProtectionEnable) {
static bool s_errorShown = false;
if (!std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::GetHardwareProtectionState: Not implemented");
if (pHwProtectionEnable)
*pHwProtectionEnable = FALSE;
}
void STDMETHODCALLTYPE D3D11DeviceContext::SetHardwareProtectionState(
BOOL HwProtectionEnable) {
static bool s_errorShown = false;
if (!std::exchange(s_errorShown, true))
Logger::err("D3D11DeviceContext::SetHardwareProtectionState: Not implemented");
}
void STDMETHODCALLTYPE D3D11DeviceContext::TransitionSurfaceLayout(
IDXGIVkInteropSurface* pSurface,
const VkImageSubresourceRange* pSubresources,
VkImageLayout OldLayout,
VkImageLayout NewLayout) {
D3D10DeviceLock lock = LockContext();
// Get the underlying D3D11 resource
Com<ID3D11Resource> resource;
pSurface->QueryInterface(__uuidof(ID3D11Resource),
reinterpret_cast<void**>(&resource));
// Get the texture from that resource
D3D11CommonTexture* texture = GetCommonTexture(resource.ptr());
EmitCs([
cImage = texture->GetImage(),
cSubresources = *pSubresources,
cOldLayout = OldLayout,
cNewLayout = NewLayout
] (DxvkContext* ctx) {
ctx->transformImage(
cImage, cSubresources,
cOldLayout, cNewLayout);
});
}
2018-03-10 11:44:27 +01:00
void D3D11DeviceContext::ApplyInputLayout() {
auto inputLayout = m_state.ia.inputLayout.prvRef();
if (likely(inputLayout != nullptr)) {
EmitCs([
cInputLayout = std::move(inputLayout)
] (DxvkContext* ctx) {
2018-03-10 11:44:27 +01:00
cInputLayout->BindToContext(ctx);
});
} else {
EmitCs([] (DxvkContext* ctx) {
ctx->setInputLayout(0, nullptr, 0, nullptr);
});
}
}
void D3D11DeviceContext::ApplyPrimitiveTopology() {
D3D11_PRIMITIVE_TOPOLOGY topology = m_state.ia.primitiveTopology;
DxvkInputAssemblyState iaState = { };
if (topology <= D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ) {
static const std::array<DxvkInputAssemblyState, 14> s_iaStates = {{
{ VK_PRIMITIVE_TOPOLOGY_MAX_ENUM, VK_FALSE, 0 },
{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST, VK_FALSE, 0 },
{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_FALSE, 0 },
{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, VK_TRUE, 0 },
{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_FALSE, 0 },
{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, VK_TRUE, 0 },
{ }, { }, { }, { }, // Random gap that exists for no reason
{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, VK_FALSE, 0 },
{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, VK_TRUE, 0 },
{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, VK_FALSE, 0 },
{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, VK_TRUE, 0 },
}};
iaState = s_iaStates[uint32_t(topology)];
} else if (topology >= D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST
&& topology <= D3D11_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST) {
// The number of control points per patch can be inferred from the enum value in D3D11
uint32_t vertexCount = uint32_t(topology - D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + 1);
iaState = { VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE, vertexCount };
}
2018-03-10 11:44:27 +01:00
EmitCs([iaState] (DxvkContext* ctx) {
ctx->setInputAssemblyState(iaState);
});
}
void D3D11DeviceContext::ApplyBlendState() {
if (m_state.om.cbState != nullptr) {
EmitCs([
cBlendState = m_state.om.cbState,
cSampleMask = m_state.om.sampleMask
] (DxvkContext* ctx) {
cBlendState->BindToContext(ctx, cSampleMask);
});
} else {
EmitCs([
cSampleMask = m_state.om.sampleMask
] (DxvkContext* ctx) {
DxvkBlendMode cbState;
DxvkLogicOpState loState;
DxvkMultisampleState msState;
InitDefaultBlendState(&cbState, &loState, &msState, cSampleMask);
for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
ctx->setBlendMode(i, cbState);
ctx->setLogicOpState(loState);
ctx->setMultisampleState(msState);
});
}
}
void D3D11DeviceContext::ApplyBlendFactor() {
EmitCs([
cBlendConstants = DxvkBlendConstants {
m_state.om.blendFactor[0], m_state.om.blendFactor[1],
m_state.om.blendFactor[2], m_state.om.blendFactor[3] }
] (DxvkContext* ctx) {
ctx->setBlendConstants(cBlendConstants);
});
}
void D3D11DeviceContext::ApplyDepthStencilState() {
if (m_state.om.dsState != nullptr) {
EmitCs([
cDepthStencilState = m_state.om.dsState
] (DxvkContext* ctx) {
cDepthStencilState->BindToContext(ctx);
});
} else {
EmitCs([] (DxvkContext* ctx) {
DxvkDepthStencilState dsState;
InitDefaultDepthStencilState(&dsState);
ctx->setDepthStencilState(dsState);
});
}
}
void D3D11DeviceContext::ApplyStencilRef() {
EmitCs([
cStencilRef = m_state.om.stencilRef
] (DxvkContext* ctx) {
ctx->setStencilReference(cStencilRef);
});
}
void D3D11DeviceContext::ApplyRasterizerState() {
if (m_state.rs.state != nullptr) {
EmitCs([
cRasterizerState = m_state.rs.state
] (DxvkContext* ctx) {
cRasterizerState->BindToContext(ctx);
});
} else {
EmitCs([] (DxvkContext* ctx) {
DxvkRasterizerState rsState;
InitDefaultRasterizerState(&rsState);
ctx->setRasterizerState(rsState);
});
}
}
2018-03-10 11:44:27 +01:00
void D3D11DeviceContext::ApplyViewportState() {
std::array<VkViewport, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> viewports;
std::array<VkRect2D, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> scissors;
// The backend can't handle a viewport count of zero,
// so we should at least specify one empty viewport
uint32_t viewportCount = m_state.rs.numViewports;
if (unlikely(!viewportCount)) {
viewportCount = 1;
viewports[0] = VkViewport();
scissors [0] = VkRect2D();
}
2018-03-10 11:44:27 +01:00
// D3D11's coordinate system has its origin in the bottom left,
// but the viewport coordinates are aligned to the top-left
// corner so we can get away with flipping the viewport.
for (uint32_t i = 0; i < m_state.rs.numViewports; i++) {
2019-05-01 03:00:23 +02:00
const D3D11_VIEWPORT& vp = m_state.rs.viewports[i];
2018-03-10 11:44:27 +01:00
2019-05-01 03:00:23 +02:00
viewports[i] = VkViewport {
2018-03-10 11:44:27 +01:00
vp.TopLeftX, vp.Height + vp.TopLeftY,
vp.Width, -vp.Height,
vp.MinDepth, vp.MaxDepth,
};
}
// Scissor rectangles. Vulkan does not provide an easy way
// to disable the scissor test, so we'll have to set scissor
// rects that are at least as large as the framebuffer.
bool enableScissorTest = false;
if (m_state.rs.state != nullptr) {
D3D11_RASTERIZER_DESC rsDesc;
m_state.rs.state->GetDesc(&rsDesc);
enableScissorTest = rsDesc.ScissorEnable;
}
for (uint32_t i = 0; i < m_state.rs.numViewports; i++) {
if (!enableScissorTest) {
scissors[i] = VkRect2D {
VkOffset2D { 0, 0 },
VkExtent2D {
D3D11_VIEWPORT_BOUNDS_MAX,
D3D11_VIEWPORT_BOUNDS_MAX } };
} else if (i >= m_state.rs.numScissors) {
scissors[i] = VkRect2D {
VkOffset2D { 0, 0 },
VkExtent2D { 0, 0 } };
} else {
2019-05-01 03:00:23 +02:00
D3D11_RECT sr = m_state.rs.scissors[i];
2018-03-10 11:44:27 +01:00
VkOffset2D srPosA;
srPosA.x = std::max<int32_t>(0, sr.left);
srPosA.y = std::max<int32_t>(0, sr.top);
VkOffset2D srPosB;
srPosB.x = std::max<int32_t>(srPosA.x, sr.right);
srPosB.y = std::max<int32_t>(srPosA.y, sr.bottom);
VkExtent2D srSize;
srSize.width = uint32_t(srPosB.x - srPosA.x);
srSize.height = uint32_t(srPosB.y - srPosA.y);
2019-05-01 03:00:23 +02:00
scissors[i] = VkRect2D { srPosA, srSize };
2018-03-10 11:44:27 +01:00
}
}
if (likely(viewportCount == 1)) {
EmitCs([
cViewport = viewports[0],
cScissor = scissors[0]
] (DxvkContext* ctx) {
ctx->setViewports(1,
&cViewport,
&cScissor);
});
} else {
EmitCs([
cViewportCount = viewportCount,
cViewports = viewports,
cScissors = scissors
] (DxvkContext* ctx) {
ctx->setViewports(
cViewportCount,
cViewports.data(),
cScissors.data());
});
}
2018-03-10 11:44:27 +01:00
}
2018-03-10 11:44:27 +01:00
template<DxbcProgramType ShaderStage>
void D3D11DeviceContext::BindShader(
const D3D11CommonShader* pShaderModule) {
// Bind the shader and the ICB at once
EmitCs([
cSlice = pShaderModule != nullptr
&& pShaderModule->GetIcb() != nullptr
? DxvkBufferSlice(pShaderModule->GetIcb())
: DxvkBufferSlice(),
cShader = pShaderModule != nullptr
? pShaderModule->GetShader()
: nullptr
] (DxvkContext* ctx) {
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
uint32_t slotId = computeConstantBufferBinding(ShaderStage,
D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
ctx->bindShader (stage, cShader);
ctx->bindResourceBuffer(slotId, cSlice);
});
}
void D3D11DeviceContext::BindFramebuffer() {
DxvkRenderTargets attachments;
// D3D11 doesn't have the concept of a framebuffer object,
// so we'll just create a new one every time the render
// target bindings are updated. Set up the attachments.
for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) {
2019-05-01 03:00:23 +02:00
if (m_state.om.renderTargetViews[i] != nullptr) {
attachments.color[i] = {
2019-05-01 03:00:23 +02:00
m_state.om.renderTargetViews[i]->GetImageView(),
m_state.om.renderTargetViews[i]->GetRenderLayout() };
}
}
if (m_state.om.depthStencilView != nullptr) {
attachments.depth = {
m_state.om.depthStencilView->GetImageView(),
m_state.om.depthStencilView->GetRenderLayout() };
}
// Create and bind the framebuffer object to the context
EmitCs([
cAttachments = std::move(attachments)
] (DxvkContext* ctx) {
ctx->bindRenderTargets(cAttachments);
});
}
void D3D11DeviceContext::BindDrawBuffers(
D3D11Buffer* pBufferForArgs,
D3D11Buffer* pBufferForCount) {
EmitCs([
cArgBuffer = pBufferForArgs ? pBufferForArgs->GetBufferSlice() : DxvkBufferSlice(),
cCntBuffer = pBufferForCount ? pBufferForCount->GetBufferSlice() : DxvkBufferSlice()
] (DxvkContext* ctx) {
ctx->bindDrawBuffers(cArgBuffer, cCntBuffer);
});
}
void D3D11DeviceContext::BindVertexBuffer(
UINT Slot,
D3D11Buffer* pBuffer,
UINT Offset,
UINT Stride) {
EmitCs([
cSlotId = Slot,
cBufferSlice = pBuffer != nullptr ? pBuffer->GetBufferSlice(Offset) : DxvkBufferSlice(),
cStride = Stride
] (DxvkContext* ctx) {
ctx->bindVertexBuffer(cSlotId, cBufferSlice, cStride);
});
}
void D3D11DeviceContext::BindIndexBuffer(
D3D11Buffer* pBuffer,
UINT Offset,
DXGI_FORMAT Format) {
2019-07-17 14:41:00 +02:00
VkIndexType indexType = Format == DXGI_FORMAT_R16_UINT
? VK_INDEX_TYPE_UINT16
: VK_INDEX_TYPE_UINT32;
EmitCs([
cBufferSlice = pBuffer != nullptr ? pBuffer->GetBufferSlice(Offset) : DxvkBufferSlice(),
cIndexType = indexType
] (DxvkContext* ctx) {
ctx->bindIndexBuffer(cBufferSlice, cIndexType);
});
}
void D3D11DeviceContext::BindXfbBuffer(
UINT Slot,
D3D11Buffer* pBuffer,
UINT Offset) {
DxvkBufferSlice bufferSlice;
DxvkBufferSlice counterSlice;
if (pBuffer != nullptr) {
bufferSlice = pBuffer->GetBufferSlice();
counterSlice = pBuffer->GetSOCounter();
}
EmitCs([
cSlotId = Slot,
cOffset = Offset,
cBufferSlice = bufferSlice,
cCounterSlice = counterSlice
] (DxvkContext* ctx) {
if (cCounterSlice.defined() && cOffset != ~0u) {
ctx->updateBuffer(
cCounterSlice.buffer(),
cCounterSlice.offset(),
sizeof(cOffset),
&cOffset);
}
ctx->bindXfbBuffer(cSlotId, cBufferSlice, cCounterSlice);
});
}
void D3D11DeviceContext::BindConstantBuffer(
UINT Slot,
D3D11Buffer* pBuffer,
UINT Offset,
UINT Length) {
EmitCs([
cSlotId = Slot,
cBufferSlice = Length ? pBuffer->GetBufferSlice(16 * Offset, 16 * Length) : DxvkBufferSlice()
] (DxvkContext* ctx) {
ctx->bindResourceBuffer(cSlotId, cBufferSlice);
});
}
void D3D11DeviceContext::BindSampler(
UINT Slot,
D3D11SamplerState* pSampler) {
EmitCs([
cSlotId = Slot,
cSampler = pSampler != nullptr ? pSampler->GetDXVKSampler() : nullptr
] (DxvkContext* ctx) {
ctx->bindResourceSampler(cSlotId, cSampler);
});
}
void D3D11DeviceContext::BindShaderResource(
UINT Slot,
D3D11ShaderResourceView* pResource) {
EmitCs([
cSlotId = Slot,
cImageView = pResource != nullptr ? pResource->GetImageView() : nullptr,
cBufferView = pResource != nullptr ? pResource->GetBufferView() : nullptr
] (DxvkContext* ctx) {
ctx->bindResourceView(cSlotId, cImageView, cBufferView);
});
}
void D3D11DeviceContext::BindUnorderedAccessView(
UINT UavSlot,
D3D11UnorderedAccessView* pUav,
UINT CtrSlot,
UINT Counter) {
EmitCs([
cUavSlotId = UavSlot,
cCtrSlotId = CtrSlot,
cImageView = pUav != nullptr ? pUav->GetImageView() : nullptr,
cBufferView = pUav != nullptr ? pUav->GetBufferView() : nullptr,
cCounterSlice = pUav != nullptr ? pUav->GetCounterSlice() : DxvkBufferSlice(),
cCounterValue = Counter
] (DxvkContext* ctx) {
if (cCounterSlice.defined() && cCounterValue != ~0u) {
ctx->updateBuffer(
cCounterSlice.buffer(),
cCounterSlice.offset(),
sizeof(uint32_t),
&cCounterValue);
}
ctx->bindResourceView (cUavSlotId, cImageView, cBufferView);
ctx->bindResourceBuffer (cCtrSlotId, cCounterSlice);
});
}
void D3D11DeviceContext::CopyBuffer(
D3D11Buffer* pDstBuffer,
VkDeviceSize DstOffset,
D3D11Buffer* pSrcBuffer,
VkDeviceSize SrcOffset,
VkDeviceSize ByteCount) {
// Clamp copy region to prevent out-of-bounds access
VkDeviceSize dstLength = pDstBuffer->Desc()->ByteWidth;
VkDeviceSize srcLength = pSrcBuffer->Desc()->ByteWidth;
if (SrcOffset >= srcLength || DstOffset >= dstLength || !ByteCount)
return;
ByteCount = std::min(dstLength - DstOffset, ByteCount);
ByteCount = std::min(srcLength - SrcOffset, ByteCount);
EmitCs([
cDstBuffer = pDstBuffer->GetBufferSlice(DstOffset, ByteCount),
cSrcBuffer = pSrcBuffer->GetBufferSlice(SrcOffset, ByteCount)
] (DxvkContext* ctx) {
if (cDstBuffer.buffer() != cSrcBuffer.buffer()) {
ctx->copyBuffer(
cDstBuffer.buffer(),
cDstBuffer.offset(),
cSrcBuffer.buffer(),
cSrcBuffer.offset(),
cSrcBuffer.length());
} else {
ctx->copyBufferRegion(
cDstBuffer.buffer(),
cDstBuffer.offset(),
cSrcBuffer.offset(),
cSrcBuffer.length());
}
});
}
2021-06-22 02:53:13 +02:00
void D3D11DeviceContext::CopyImage(
D3D11CommonTexture* pDstTexture,
const VkImageSubresourceLayers* pDstLayers,
VkOffset3D DstOffset,
D3D11CommonTexture* pSrcTexture,
const VkImageSubresourceLayers* pSrcLayers,
VkOffset3D SrcOffset,
VkExtent3D SrcExtent) {
// Image formats must be size-compatible
auto dstFormatInfo = imageFormatInfo(pDstTexture->GetPackedFormat());
auto srcFormatInfo = imageFormatInfo(pSrcTexture->GetPackedFormat());
if (dstFormatInfo->elementSize != srcFormatInfo->elementSize) {
Logger::err("D3D11: CopyImage: Incompatible texel size");
return;
}
// Sample counts must match
if (pDstTexture->Desc()->SampleDesc.Count != pSrcTexture->Desc()->SampleDesc.Count) {
Logger::err("D3D11: CopyImage: Incompatible sample count");
return;
}
// Obviously, the copy region must not be empty
VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstLayers->mipLevel);
VkExtent3D srcMipExtent = pSrcTexture->MipLevelExtent(pSrcLayers->mipLevel);
if (uint32_t(DstOffset.x) >= dstMipExtent.width
|| uint32_t(DstOffset.y) >= dstMipExtent.height
|| uint32_t(DstOffset.z) >= dstMipExtent.depth)
return;
if (uint32_t(SrcOffset.x) >= srcMipExtent.width
|| uint32_t(SrcOffset.y) >= srcMipExtent.height
|| uint32_t(SrcOffset.z) >= srcMipExtent.depth)
return;
// Don't perform the copy if the offsets aren't block-aligned
if (!util::isBlockAligned(SrcOffset, srcFormatInfo->blockSize)
|| !util::isBlockAligned(DstOffset, dstFormatInfo->blockSize)) {
Logger::err(str::format("D3D11: CopyImage: Unaligned block offset"));
return;
}
// Clamp the image region in order to avoid out-of-bounds access
VkExtent3D blockCount = util::computeBlockCount(SrcExtent, srcFormatInfo->blockSize);
VkExtent3D dstBlockCount = util::computeMaxBlockCount(DstOffset, dstMipExtent, dstFormatInfo->blockSize);
VkExtent3D srcBlockCount = util::computeMaxBlockCount(SrcOffset, srcMipExtent, srcFormatInfo->blockSize);
blockCount = util::minExtent3D(blockCount, dstBlockCount);
blockCount = util::minExtent3D(blockCount, srcBlockCount);
SrcExtent = util::computeBlockExtent(blockCount, srcFormatInfo->blockSize);
SrcExtent = util::snapExtent3D(SrcOffset, SrcExtent, srcMipExtent);
if (!SrcExtent.width || !SrcExtent.height || !SrcExtent.depth)
return;
// While copying between 2D and 3D images is allowed in CopySubresourceRegion,
// copying more than one slice at a time is not suppoted. Layer counts are 1.
if ((pDstTexture->GetVkImageType() == VK_IMAGE_TYPE_3D)
!= (pSrcTexture->GetVkImageType() == VK_IMAGE_TYPE_3D))
SrcExtent.depth = 1;
// Certain types of copies require us to pass the destination extent to
// the backend. This may be different when copying between compressed
// and uncompressed image formats.
VkExtent3D dstExtent = util::computeBlockExtent(blockCount, dstFormatInfo->blockSize);
dstExtent = util::snapExtent3D(DstOffset, dstExtent, dstMipExtent);
// It is possible for any of the given images to be a staging image with
// no actual image, so we need to account for all possibilities here.
bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
bool srcIsImage = pSrcTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
if (dstIsImage && srcIsImage) {
EmitCs([
cDstImage = pDstTexture->GetImage(),
cSrcImage = pSrcTexture->GetImage(),
cDstLayers = *pDstLayers,
cSrcLayers = *pSrcLayers,
cDstOffset = DstOffset,
cSrcOffset = SrcOffset,
cExtent = SrcExtent
] (DxvkContext* ctx) {
// CopyResource can only copy between different images, and
// CopySubresourceRegion can only copy data from one single
// subresource at a time, so this check is safe.
if (cDstImage != cSrcImage || cDstLayers != cSrcLayers) {
ctx->copyImage(
cDstImage, cDstLayers, cDstOffset,
cSrcImage, cSrcLayers, cSrcOffset,
cExtent);
} else {
ctx->copyImageRegion(
cDstImage, cDstLayers, cDstOffset,
cSrcOffset, cExtent);
}
});
} else {
// Since each subresource uses a dedicated buffer, we are going
// to need one call per subresource for staging resource copies
for (uint32_t i = 0; i < pDstLayers->layerCount; i++) {
uint32_t dstSubresource = D3D11CalcSubresource(pDstLayers->mipLevel, pDstLayers->baseArrayLayer + i, pDstTexture->Desc()->MipLevels);
uint32_t srcSubresource = D3D11CalcSubresource(pSrcLayers->mipLevel, pSrcLayers->baseArrayLayer + i, pSrcTexture->Desc()->MipLevels);
// For multi-plane image data stored in a buffer, the backend
// assumes that the second plane immediately follows the first
// plane in memory, which is only true if we copy the full image.
uint32_t planeCount = 1;
if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
bool needsSeparateCopies = !dstIsImage && !srcIsImage;
if (!dstIsImage)
needsSeparateCopies |= pDstTexture->MipLevelExtent(pDstLayers->mipLevel) != SrcExtent;
if (!srcIsImage)
needsSeparateCopies |= pSrcTexture->MipLevelExtent(pSrcLayers->mipLevel) != SrcExtent;
if (needsSeparateCopies)
planeCount = vk::getPlaneCount(srcFormatInfo->aspectMask);
}
for (uint32_t j = 0; j < planeCount; j++) {
VkImageAspectFlags dstAspectMask = dstFormatInfo->aspectMask;
VkImageAspectFlags srcAspectMask = srcFormatInfo->aspectMask;
if (planeCount > 1) {
dstAspectMask = vk::getPlaneAspect(j);
srcAspectMask = dstAspectMask;
}
if (dstIsImage) {
VkImageSubresourceLayers dstLayer = { dstAspectMask,
pDstLayers->mipLevel, pDstLayers->baseArrayLayer + i, 1 };
EmitCs([
cDstImage = pDstTexture->GetImage(),
cDstLayers = dstLayer,
cDstOffset = DstOffset,
cDstExtent = dstExtent,
cSrcBuffer = pSrcTexture->GetMappedBuffer(srcSubresource),
cSrcLayout = pSrcTexture->GetSubresourceLayout(srcAspectMask, srcSubresource),
cSrcOffset = pSrcTexture->ComputeMappedOffset(srcSubresource, j, SrcOffset),
cSrcCoord = SrcOffset,
cSrcExtent = srcMipExtent,
cSrcFormat = pSrcTexture->GetPackedFormat()
] (DxvkContext* ctx) {
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
ctx->copyBufferToImage(cDstImage, cDstLayers, cDstOffset, cDstExtent,
cSrcBuffer, cSrcOffset, cSrcLayout.RowPitch, cSrcLayout.DepthPitch);
} else {
ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
VkOffset2D { cDstOffset.x, cDstOffset.y },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cSrcBuffer, cSrcLayout.Offset,
VkOffset2D { cSrcCoord.x, cSrcCoord.y },
VkExtent2D { cSrcExtent.width, cSrcExtent.height },
cSrcFormat);
}
});
} else if (srcIsImage) {
VkImageSubresourceLayers srcLayer = { srcAspectMask,
pSrcLayers->mipLevel, pSrcLayers->baseArrayLayer + i, 1 };
EmitCs([
cSrcImage = pSrcTexture->GetImage(),
cSrcLayers = srcLayer,
cSrcOffset = SrcOffset,
cSrcExtent = SrcExtent,
cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource),
cDstLayout = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource),
cDstOffset = pDstTexture->ComputeMappedOffset(dstSubresource, j, DstOffset),
cDstCoord = DstOffset,
cDstExtent = dstMipExtent,
cDstFormat = pDstTexture->GetPackedFormat()
] (DxvkContext* ctx) {
if (cSrcLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
ctx->copyImageToBuffer(cDstBuffer, cDstOffset, cDstLayout.RowPitch,
cDstLayout.DepthPitch, cSrcImage, cSrcLayers, cSrcOffset, cSrcExtent);
} else {
ctx->copyDepthStencilImageToPackedBuffer(cDstBuffer, cDstLayout.Offset,
VkOffset2D { cDstCoord.x, cDstCoord.y },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cSrcImage, cSrcLayers,
VkOffset2D { cSrcOffset.x, cSrcOffset.y },
VkExtent2D { cSrcExtent.width, cSrcExtent.height },
cDstFormat);
}
});
} else {
// The backend is not aware of image metadata in this case,
// so we need to handle image planes and block sizes here
VkDeviceSize elementSize = dstFormatInfo->elementSize;
VkExtent3D dstBlockSize = dstFormatInfo->blockSize;
VkExtent3D srcBlockSize = srcFormatInfo->blockSize;
VkExtent3D planeBlockSize = { 1u, 1u, 1u };
if (planeCount > 1) {
auto plane = &dstFormatInfo->planes[j];
dstBlockSize.width *= plane->blockSize.width;
dstBlockSize.height *= plane->blockSize.height;
srcBlockSize.width *= plane->blockSize.width;
srcBlockSize.height *= plane->blockSize.height;
planeBlockSize.width = plane->blockSize.width;
planeBlockSize.height = plane->blockSize.height;
elementSize = plane->elementSize;
}
EmitCs([
cPixelSize = elementSize,
cSrcBuffer = pSrcTexture->GetMappedBuffer(srcSubresource),
cSrcStart = pSrcTexture->GetSubresourceLayout(srcAspectMask, srcSubresource).Offset,
cSrcOffset = util::computeBlockOffset(SrcOffset, srcBlockSize),
cSrcSize = util::computeBlockCount(srcMipExtent, srcBlockSize),
cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource),
cDstStart = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource).Offset,
cDstOffset = util::computeBlockOffset(DstOffset, dstBlockSize),
cDstSize = util::computeBlockCount(dstMipExtent, dstBlockSize),
cExtent = util::computeBlockCount(blockCount, planeBlockSize)
] (DxvkContext* ctx) {
ctx->copyPackedBufferImage(
cDstBuffer, cDstStart, cDstOffset, cDstSize,
cSrcBuffer, cSrcStart, cSrcOffset, cSrcSize,
cExtent, cPixelSize);
});
}
}
}
}
}
void D3D11DeviceContext::DiscardBuffer(
ID3D11Resource* pResource) {
auto buffer = static_cast<D3D11Buffer*>(pResource);
if (buffer->GetMapMode() != D3D11_COMMON_BUFFER_MAP_MODE_NONE) {
D3D11_MAPPED_SUBRESOURCE sr;
Map(pResource, 0, D3D11_MAP_WRITE_DISCARD, 0, &sr);
Unmap(pResource, 0);
}
}
void D3D11DeviceContext::DiscardTexture(
ID3D11Resource* pResource,
UINT Subresource) {
auto texture = GetCommonTexture(pResource);
if (texture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
D3D11_MAPPED_SUBRESOURCE sr;
Map(pResource, Subresource, D3D11_MAP_WRITE_DISCARD, 0, &sr);
Unmap(pResource, Subresource);
}
}
2021-06-24 01:41:48 +02:00
void D3D11DeviceContext::UpdateImage(
D3D11CommonTexture* pDstTexture,
const VkImageSubresource* pDstSubresource,
VkOffset3D DstOffset,
VkExtent3D DstExtent,
DxvkBufferSlice StagingBuffer) {
bool dstIsImage = pDstTexture->GetMapMode() != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING;
if (dstIsImage) {
EmitCs([
cDstImage = pDstTexture->GetImage(),
cDstLayers = vk::makeSubresourceLayers(*pDstSubresource),
cDstOffset = DstOffset,
cDstExtent = DstExtent,
cStagingSlice = std::move(StagingBuffer),
cPackedFormat = pDstTexture->GetPackedFormat()
] (DxvkContext* ctx) {
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
ctx->copyBufferToImage(cDstImage,
cDstLayers, cDstOffset, cDstExtent,
cStagingSlice.buffer(),
cStagingSlice.offset(), 0, 0);
} else {
ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
VkOffset2D { cDstOffset.x, cDstOffset.y },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cStagingSlice.buffer(),
cStagingSlice.offset(),
VkOffset2D { 0, 0 },
VkExtent2D { cDstExtent.width, cDstExtent.height },
cPackedFormat);
}
});
} else {
// If the destination image is backed only by a buffer, we need to use
// the packed buffer copy function which does not know about planes and
// format metadata, so deal with it manually here.
VkExtent3D dstMipExtent = pDstTexture->MipLevelExtent(pDstSubresource->mipLevel);
uint32_t dstSubresource = D3D11CalcSubresource(pDstSubresource->mipLevel,
pDstSubresource->arrayLayer, pDstTexture->Desc()->MipLevels);
auto dstFormat = pDstTexture->GetPackedFormat();
auto dstFormatInfo = imageFormatInfo(dstFormat);
uint32_t planeCount = 1;
if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane))
planeCount = vk::getPlaneCount(dstFormatInfo->aspectMask);
// The source data isn't stored in an image so we'll also need to
// track the offset for that while iterating over the planes.
VkDeviceSize srcPlaneOffset = 0;
for (uint32_t i = 0; i < planeCount; i++) {
VkImageAspectFlags dstAspectMask = dstFormatInfo->aspectMask;
VkDeviceSize elementSize = dstFormatInfo->elementSize;
VkExtent3D blockSize = dstFormatInfo->blockSize;
if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
dstAspectMask = vk::getPlaneAspect(i);
auto plane = &dstFormatInfo->planes[i];
blockSize.width *= plane->blockSize.width;
blockSize.height *= plane->blockSize.height;
elementSize = plane->elementSize;
}
VkExtent3D blockCount = util::computeBlockCount(DstExtent, blockSize);
EmitCs([
cDstBuffer = pDstTexture->GetMappedBuffer(dstSubresource),
cDstStart = pDstTexture->GetSubresourceLayout(dstAspectMask, dstSubresource).Offset,
cDstOffset = util::computeBlockOffset(DstOffset, blockSize),
cDstSize = util::computeBlockCount(dstMipExtent, blockSize),
cDstExtent = blockCount,
cSrcBuffer = StagingBuffer.buffer(),
cSrcStart = StagingBuffer.offset() + srcPlaneOffset,
cPixelSize = elementSize
] (DxvkContext* ctx) {
ctx->copyPackedBufferImage(
cDstBuffer, cDstStart, cDstOffset, cDstSize,
cSrcBuffer, cSrcStart, VkOffset3D(), cDstExtent,
cDstExtent, cPixelSize);
});
srcPlaneOffset += util::flattenImageExtent(blockCount) * elementSize;
}
}
}
void D3D11DeviceContext::SetDrawBuffers(
ID3D11Buffer* pBufferForArgs,
ID3D11Buffer* pBufferForCount) {
auto argBuffer = static_cast<D3D11Buffer*>(pBufferForArgs);
auto cntBuffer = static_cast<D3D11Buffer*>(pBufferForCount);
if (m_state.id.argBuffer != argBuffer
|| m_state.id.cntBuffer != cntBuffer) {
m_state.id.argBuffer = argBuffer;
m_state.id.cntBuffer = cntBuffer;
BindDrawBuffers(argBuffer, cntBuffer);
}
}
template<DxbcProgramType ShaderStage>
void D3D11DeviceContext::SetConstantBuffers(
D3D11ConstantBufferBindings& Bindings,
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers) {
uint32_t slotId = computeConstantBufferBinding(ShaderStage, StartSlot);
for (uint32_t i = 0; i < NumBuffers; i++) {
auto newBuffer = static_cast<D3D11Buffer*>(ppConstantBuffers[i]);
UINT constantCount = 0;
if (likely(newBuffer != nullptr))
constantCount = std::min(newBuffer->Desc()->ByteWidth / 16, UINT(D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT));
if (Bindings[StartSlot + i].buffer != newBuffer
|| Bindings[StartSlot + i].constantCount != constantCount) {
Bindings[StartSlot + i].buffer = newBuffer;
Bindings[StartSlot + i].constantOffset = 0;
Bindings[StartSlot + i].constantCount = constantCount;
Bindings[StartSlot + i].constantBound = constantCount;
BindConstantBuffer(slotId + i, newBuffer, 0, constantCount);
}
}
}
template<DxbcProgramType ShaderStage>
void D3D11DeviceContext::SetConstantBuffers1(
D3D11ConstantBufferBindings& Bindings,
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers,
const UINT* pFirstConstant,
const UINT* pNumConstants) {
uint32_t slotId = computeConstantBufferBinding(ShaderStage, StartSlot);
for (uint32_t i = 0; i < NumBuffers; i++) {
auto newBuffer = static_cast<D3D11Buffer*>(ppConstantBuffers[i]);
UINT constantOffset;
UINT constantCount;
UINT constantBound;
if (likely(newBuffer != nullptr)) {
UINT bufferConstantsCount = newBuffer->Desc()->ByteWidth / 16;
constantBound = std::min(bufferConstantsCount, UINT(D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT));
if (likely(pFirstConstant && pNumConstants)) {
constantOffset = pFirstConstant[i];
constantCount = pNumConstants [i];
if (unlikely(constantCount > D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT))
continue;
constantBound = (constantOffset + constantCount > bufferConstantsCount)
? bufferConstantsCount - std::min(constantOffset, bufferConstantsCount)
: constantCount;
} else {
constantOffset = 0;
constantCount = constantBound;
}
} else {
constantOffset = 0;
constantCount = 0;
constantBound = 0;
}
bool needsUpdate = Bindings[StartSlot + i].buffer != newBuffer;
if (needsUpdate)
Bindings[StartSlot + i].buffer = newBuffer;
needsUpdate |= Bindings[StartSlot + i].constantOffset != constantOffset
|| Bindings[StartSlot + i].constantCount != constantCount;
if (needsUpdate) {
Bindings[StartSlot + i].constantOffset = constantOffset;
Bindings[StartSlot + i].constantCount = constantCount;
Bindings[StartSlot + i].constantBound = constantBound;
BindConstantBuffer(slotId + i, newBuffer, constantOffset, constantBound);
}
}
}
template<DxbcProgramType ShaderStage>
void D3D11DeviceContext::SetSamplers(
D3D11SamplerBindings& Bindings,
2017-12-09 21:17:26 +01:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState* const* ppSamplers) {
uint32_t slotId = computeSamplerBinding(ShaderStage, StartSlot);
2017-12-09 21:17:26 +01:00
for (uint32_t i = 0; i < NumSamplers; i++) {
auto sampler = static_cast<D3D11SamplerState*>(ppSamplers[i]);
2017-12-09 21:17:26 +01:00
if (Bindings[StartSlot + i] != sampler) {
Bindings[StartSlot + i] = sampler;
BindSampler(slotId + i, sampler);
2017-12-09 21:17:26 +01:00
}
}
}
template<DxbcProgramType ShaderStage>
void D3D11DeviceContext::SetShaderResources(
D3D11ShaderResourceBindings& Bindings,
UINT StartSlot,
UINT NumResources,
ID3D11ShaderResourceView* const* ppResources) {
uint32_t slotId = computeSrvBinding(ShaderStage, StartSlot);
for (uint32_t i = 0; i < NumResources; i++) {
auto resView = static_cast<D3D11ShaderResourceView*>(ppResources[i]);
if (Bindings.views[StartSlot + i] != resView) {
if (unlikely(resView && resView->TestHazards())) {
if (TestSrvHazards<ShaderStage>(resView))
resView = nullptr;
// Only set if necessary, but don't reset it on every
// bind as this would be more expensive than a few
// redundant checks in OMSetRenderTargets and friends.
Bindings.hazardous.set(StartSlot + i, resView);
}
Bindings.views[StartSlot + i] = resView;
BindShaderResource(slotId + i, resView);
}
}
}
void D3D11DeviceContext::GetConstantBuffers(
const D3D11ConstantBufferBindings& Bindings,
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer** ppConstantBuffers,
UINT* pFirstConstant,
UINT* pNumConstants) {
for (uint32_t i = 0; i < NumBuffers; i++) {
const bool inRange = StartSlot + i < Bindings.size();
if (ppConstantBuffers != nullptr) {
ppConstantBuffers[i] = inRange
? Bindings[StartSlot + i].buffer.ref()
: nullptr;
}
if (pFirstConstant != nullptr) {
pFirstConstant[i] = inRange
? Bindings[StartSlot + i].constantOffset
: 0u;
}
if (pNumConstants != nullptr) {
pNumConstants[i] = inRange
? Bindings[StartSlot + i].constantCount
: 0u;
}
}
}
void D3D11DeviceContext::GetShaderResources(
const D3D11ShaderResourceBindings& Bindings,
UINT StartSlot,
UINT NumViews,
ID3D11ShaderResourceView** ppShaderResourceViews) {
for (uint32_t i = 0; i < NumViews; i++) {
ppShaderResourceViews[i] = StartSlot + i < Bindings.views.size()
? Bindings.views[StartSlot + i].ref()
: nullptr;
}
}
void D3D11DeviceContext::GetSamplers(
const D3D11SamplerBindings& Bindings,
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState** ppSamplers) {
for (uint32_t i = 0; i < NumSamplers; i++) {
ppSamplers[i] = StartSlot + i < Bindings.size()
? ref(Bindings[StartSlot + i])
: nullptr;
}
}
void D3D11DeviceContext::ResetState() {
EmitCs([] (DxvkContext* ctx) {
// Reset render targets
ctx->bindRenderTargets(DxvkRenderTargets());
// Reset vertex input state
ctx->setInputLayout(0, nullptr, 0, nullptr);
// Reset render states
DxvkInputAssemblyState iaState;
InitDefaultPrimitiveTopology(&iaState);
DxvkDepthStencilState dsState;
InitDefaultDepthStencilState(&dsState);
DxvkRasterizerState rsState;
InitDefaultRasterizerState(&rsState);
DxvkBlendMode cbState;
DxvkLogicOpState loState;
DxvkMultisampleState msState;
InitDefaultBlendState(&cbState, &loState, &msState, D3D11_DEFAULT_SAMPLE_MASK);
ctx->setInputAssemblyState(iaState);
ctx->setDepthStencilState(dsState);
ctx->setRasterizerState(rsState);
ctx->setLogicOpState(loState);
ctx->setMultisampleState(msState);
for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
ctx->setBlendMode(i, cbState);
// Reset dynamic states
ctx->setBlendConstants(DxvkBlendConstants { 1.0f, 1.0f, 1.0f, 1.0f });
ctx->setStencilReference(D3D11_DEFAULT_STENCIL_REFERENCE);
// Reset viewports
auto viewport = VkViewport();
auto scissor = VkRect2D();
ctx->setViewports(1, &viewport, &scissor);
// Unbind indirect draw buffer
ctx->bindDrawBuffers(DxvkBufferSlice(), DxvkBufferSlice());
// Unbind index and vertex buffers
ctx->bindIndexBuffer(DxvkBufferSlice(), VK_INDEX_TYPE_UINT32);
for (uint32_t i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++)
ctx->bindVertexBuffer(i, DxvkBufferSlice(), 0);
// Unbind transform feedback buffers
for (uint32_t i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++)
ctx->bindXfbBuffer(i, DxvkBufferSlice(), DxvkBufferSlice());
// Unbind per-shader stage resources
for (uint32_t i = 0; i < 6; i++) {
auto programType = DxbcProgramType(i);
ctx->bindShader(GetShaderStage(programType), nullptr);
// Unbind constant buffers, including the shader's ICB
auto cbSlotId = computeConstantBufferBinding(programType, 0);
for (uint32_t j = 0; j <= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; j++)
ctx->bindResourceBuffer(cbSlotId + j, DxvkBufferSlice());
// Unbind shader resource views
auto srvSlotId = computeSrvBinding(programType, 0);
for (uint32_t j = 0; j < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; j++)
ctx->bindResourceView(srvSlotId + j, nullptr, nullptr);
// Unbind texture samplers
auto samplerSlotId = computeSamplerBinding(programType, 0);
for (uint32_t j = 0; j < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; j++)
ctx->bindResourceSampler(samplerSlotId + j, nullptr);
// Unbind UAVs for supported stages
if (programType == DxbcProgramType::PixelShader
|| programType == DxbcProgramType::ComputeShader) {
auto uavSlotId = computeUavBinding(programType, 0);
auto ctrSlotId = computeUavCounterBinding(programType, 0);
for (uint32_t j = 0; j < D3D11_1_UAV_SLOT_COUNT; j++) {
ctx->bindResourceView (uavSlotId, nullptr, nullptr);
ctx->bindResourceBuffer (ctrSlotId, DxvkBufferSlice());
}
}
}
});
}
void D3D11DeviceContext::RestoreState() {
BindFramebuffer();
BindShader<DxbcProgramType::VertexShader> (GetCommonShader(m_state.vs.shader.ptr()));
BindShader<DxbcProgramType::HullShader> (GetCommonShader(m_state.hs.shader.ptr()));
BindShader<DxbcProgramType::DomainShader> (GetCommonShader(m_state.ds.shader.ptr()));
BindShader<DxbcProgramType::GeometryShader> (GetCommonShader(m_state.gs.shader.ptr()));
BindShader<DxbcProgramType::PixelShader> (GetCommonShader(m_state.ps.shader.ptr()));
BindShader<DxbcProgramType::ComputeShader> (GetCommonShader(m_state.cs.shader.ptr()));
2018-03-10 11:44:27 +01:00
ApplyInputLayout();
ApplyPrimitiveTopology();
ApplyBlendState();
ApplyBlendFactor();
ApplyDepthStencilState();
ApplyStencilRef();
ApplyRasterizerState();
2018-03-10 11:44:27 +01:00
ApplyViewportState();
BindDrawBuffers(
m_state.id.argBuffer.ptr(),
m_state.id.cntBuffer.ptr());
2018-03-10 11:44:27 +01:00
BindIndexBuffer(
m_state.ia.indexBuffer.buffer.ptr(),
m_state.ia.indexBuffer.offset,
m_state.ia.indexBuffer.format);
for (uint32_t i = 0; i < m_state.ia.vertexBuffers.size(); i++) {
BindVertexBuffer(i,
m_state.ia.vertexBuffers[i].buffer.ptr(),
m_state.ia.vertexBuffers[i].offset,
m_state.ia.vertexBuffers[i].stride);
}
for (uint32_t i = 0; i < m_state.so.targets.size(); i++)
BindXfbBuffer(i, m_state.so.targets[i].buffer.ptr(), ~0u);
RestoreConstantBuffers<DxbcProgramType::VertexShader> (m_state.vs.constantBuffers);
RestoreConstantBuffers<DxbcProgramType::HullShader> (m_state.hs.constantBuffers);
RestoreConstantBuffers<DxbcProgramType::DomainShader> (m_state.ds.constantBuffers);
RestoreConstantBuffers<DxbcProgramType::GeometryShader> (m_state.gs.constantBuffers);
RestoreConstantBuffers<DxbcProgramType::PixelShader> (m_state.ps.constantBuffers);
RestoreConstantBuffers<DxbcProgramType::ComputeShader> (m_state.cs.constantBuffers);
RestoreSamplers<DxbcProgramType::VertexShader> (m_state.vs.samplers);
RestoreSamplers<DxbcProgramType::HullShader> (m_state.hs.samplers);
RestoreSamplers<DxbcProgramType::DomainShader> (m_state.ds.samplers);
RestoreSamplers<DxbcProgramType::GeometryShader>(m_state.gs.samplers);
RestoreSamplers<DxbcProgramType::PixelShader> (m_state.ps.samplers);
RestoreSamplers<DxbcProgramType::ComputeShader> (m_state.cs.samplers);
RestoreShaderResources<DxbcProgramType::VertexShader> (m_state.vs.shaderResources);
RestoreShaderResources<DxbcProgramType::HullShader> (m_state.hs.shaderResources);
RestoreShaderResources<DxbcProgramType::DomainShader> (m_state.ds.shaderResources);
RestoreShaderResources<DxbcProgramType::GeometryShader> (m_state.gs.shaderResources);
RestoreShaderResources<DxbcProgramType::PixelShader> (m_state.ps.shaderResources);
RestoreShaderResources<DxbcProgramType::ComputeShader> (m_state.cs.shaderResources);
RestoreUnorderedAccessViews<DxbcProgramType::PixelShader> (m_state.ps.unorderedAccessViews);
RestoreUnorderedAccessViews<DxbcProgramType::ComputeShader> (m_state.cs.unorderedAccessViews);
}
template<DxbcProgramType Stage>
void D3D11DeviceContext::RestoreConstantBuffers(
D3D11ConstantBufferBindings& Bindings) {
uint32_t slotId = computeConstantBufferBinding(Stage, 0);
for (uint32_t i = 0; i < Bindings.size(); i++) {
BindConstantBuffer(slotId + i, Bindings[i].buffer.ptr(),
Bindings[i].constantOffset, Bindings[i].constantBound);
}
}
template<DxbcProgramType Stage>
void D3D11DeviceContext::RestoreSamplers(
D3D11SamplerBindings& Bindings) {
uint32_t slotId = computeSamplerBinding(Stage, 0);
for (uint32_t i = 0; i < Bindings.size(); i++)
BindSampler(slotId + i, Bindings[i]);
}
template<DxbcProgramType Stage>
void D3D11DeviceContext::RestoreShaderResources(
D3D11ShaderResourceBindings& Bindings) {
uint32_t slotId = computeSrvBinding(Stage, 0);
for (uint32_t i = 0; i < Bindings.views.size(); i++)
BindShaderResource(slotId + i, Bindings.views[i].ptr());
}
template<DxbcProgramType Stage>
void D3D11DeviceContext::RestoreUnorderedAccessViews(
D3D11UnorderedAccessBindings& Bindings) {
uint32_t uavSlotId = computeUavBinding (Stage, 0);
uint32_t ctrSlotId = computeUavCounterBinding(Stage, 0);
for (uint32_t i = 0; i < Bindings.size(); i++) {
BindUnorderedAccessView(
uavSlotId + i,
Bindings[i].ptr(),
ctrSlotId + i, ~0u);
}
}
bool D3D11DeviceContext::TestRtvUavHazards(
UINT NumRTVs,
ID3D11RenderTargetView* const* ppRTVs,
UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUAVs) {
if (NumRTVs == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) NumRTVs = 0;
if (NumUAVs == D3D11_KEEP_UNORDERED_ACCESS_VIEWS) NumUAVs = 0;
for (uint32_t i = 0; i < NumRTVs; i++) {
auto rtv = static_cast<D3D11RenderTargetView*>(ppRTVs[i]);
if (!rtv)
continue;
for (uint32_t j = 0; j < i; j++) {
if (CheckViewOverlap(rtv, static_cast<D3D11RenderTargetView*>(ppRTVs[j])))
return true;
}
if (rtv->HasBindFlag(D3D11_BIND_UNORDERED_ACCESS)) {
for (uint32_t j = 0; j < NumUAVs; j++) {
if (CheckViewOverlap(rtv, static_cast<D3D11UnorderedAccessView*>(ppUAVs[j])))
return true;
}
}
}
for (uint32_t i = 0; i < NumUAVs; i++) {
auto uav = static_cast<D3D11UnorderedAccessView*>(ppUAVs[i]);
if (!uav)
continue;
for (uint32_t j = 0; j < i; j++) {
if (CheckViewOverlap(uav, static_cast<D3D11UnorderedAccessView*>(ppUAVs[j])))
return true;
}
}
return false;
}
template<DxbcProgramType ShaderStage>
bool D3D11DeviceContext::TestSrvHazards(
D3D11ShaderResourceView* pView) {
bool hazard = false;
if (ShaderStage == DxbcProgramType::ComputeShader) {
int32_t uav = m_state.cs.uavMask.findNext(0);
while (uav >= 0 && !hazard) {
hazard = CheckViewOverlap(pView, m_state.cs.unorderedAccessViews[uav].ptr());
uav = m_state.cs.uavMask.findNext(uav + 1);
}
} else {
hazard = CheckViewOverlap(pView, m_state.om.depthStencilView.ptr());
for (uint32_t i = 0; !hazard && i < m_state.om.maxRtv; i++)
hazard = CheckViewOverlap(pView, m_state.om.renderTargetViews[i].ptr());
for (uint32_t i = 0; !hazard && i < m_state.om.maxUav; i++)
hazard = CheckViewOverlap(pView, m_state.ps.unorderedAccessViews[i].ptr());
}
return hazard;
}
template<DxbcProgramType ShaderStage, typename T>
void D3D11DeviceContext::ResolveSrvHazards(
T* pView,
D3D11ShaderResourceBindings& Bindings) {
uint32_t slotId = computeSrvBinding(ShaderStage, 0);
int32_t srvId = Bindings.hazardous.findNext(0);
while (srvId >= 0) {
auto srv = Bindings.views[srvId].ptr();
if (likely(srv && srv->TestHazards())) {
bool hazard = CheckViewOverlap(pView, srv);
if (unlikely(hazard)) {
Bindings.views[srvId] = nullptr;
Bindings.hazardous.clr(srvId);
BindShaderResource(slotId + srvId, nullptr);
}
} else {
// Avoid further redundant iterations
Bindings.hazardous.clr(srvId);
}
srvId = Bindings.hazardous.findNext(srvId + 1);
}
}
template<typename T>
void D3D11DeviceContext::ResolveCsSrvHazards(
T* pView) {
if (!pView) return;
ResolveSrvHazards<DxbcProgramType::ComputeShader> (pView, m_state.cs.shaderResources);
}
template<typename T>
void D3D11DeviceContext::ResolveOmSrvHazards(
T* pView) {
if (!pView) return;
ResolveSrvHazards<DxbcProgramType::VertexShader> (pView, m_state.vs.shaderResources);
ResolveSrvHazards<DxbcProgramType::HullShader> (pView, m_state.hs.shaderResources);
ResolveSrvHazards<DxbcProgramType::DomainShader> (pView, m_state.ds.shaderResources);
ResolveSrvHazards<DxbcProgramType::GeometryShader> (pView, m_state.gs.shaderResources);
ResolveSrvHazards<DxbcProgramType::PixelShader> (pView, m_state.ps.shaderResources);
}
bool D3D11DeviceContext::ResolveOmRtvHazards(
D3D11UnorderedAccessView* pView) {
if (!pView || !pView->HasBindFlag(D3D11_BIND_RENDER_TARGET))
return false;
bool hazard = false;
if (CheckViewOverlap(pView, m_state.om.depthStencilView.ptr())) {
m_state.om.depthStencilView = nullptr;
hazard = true;
}
for (uint32_t i = 0; i < m_state.om.maxRtv; i++) {
if (CheckViewOverlap(pView, m_state.om.renderTargetViews[i].ptr())) {
m_state.om.renderTargetViews[i] = nullptr;
hazard = true;
}
}
return hazard;
}
void D3D11DeviceContext::ResolveOmUavHazards(
D3D11RenderTargetView* pView) {
if (!pView || !pView->HasBindFlag(D3D11_BIND_UNORDERED_ACCESS))
return;
uint32_t uavSlotId = computeUavBinding (DxbcProgramType::PixelShader, 0);
uint32_t ctrSlotId = computeUavCounterBinding(DxbcProgramType::PixelShader, 0);
for (uint32_t i = 0; i < m_state.om.maxUav; i++) {
if (CheckViewOverlap(pView, m_state.ps.unorderedAccessViews[i].ptr())) {
m_state.ps.unorderedAccessViews[i] = nullptr;
BindUnorderedAccessView(
uavSlotId + i, nullptr,
ctrSlotId + i, ~0u);
}
}
}
bool D3D11DeviceContext::ValidateRenderTargets(
UINT NumViews,
ID3D11RenderTargetView* const* ppRenderTargetViews,
ID3D11DepthStencilView* pDepthStencilView) {
Rc<DxvkImageView> refView;
if (pDepthStencilView != nullptr) {
refView = static_cast<D3D11DepthStencilView*>(
pDepthStencilView)->GetImageView();
}
for (uint32_t i = 0; i < NumViews; i++) {
if (ppRenderTargetViews[i] != nullptr) {
auto curView = static_cast<D3D11RenderTargetView*>(
ppRenderTargetViews[i])->GetImageView();
if (refView != nullptr) {
// Render target views must all have the same
// size, sample count, layer count, and type
if (curView->info().type != refView->info().type
|| curView->info().numLayers != refView->info().numLayers)
return false;
if (curView->imageInfo().sampleCount
!= refView->imageInfo().sampleCount)
return false;
} else {
// Set reference view. All remaining views
// must be compatible to the reference view.
refView = curView;
}
}
}
return true;
}
VkClearValue D3D11DeviceContext::ConvertColorValue(
const FLOAT Color[4],
const DxvkFormatInfo* pFormatInfo) {
VkClearValue result;
if (pFormatInfo->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
for (uint32_t i = 0; i < 4; i++) {
if (pFormatInfo->flags.test(DxvkFormatFlag::SampledUInt))
result.color.uint32[i] = uint32_t(std::max(0.0f, Color[i]));
else if (pFormatInfo->flags.test(DxvkFormatFlag::SampledSInt))
result.color.int32[i] = int32_t(Color[i]);
else
result.color.float32[i] = Color[i];
}
} else {
result.depthStencil.depth = Color[0];
result.depthStencil.stencil = 0;
}
return result;
}
DxvkDataSlice D3D11DeviceContext::AllocUpdateBufferSlice(size_t Size) {
constexpr size_t UpdateBufferSize = 16 * 1024 * 1024;
if (Size >= UpdateBufferSize) {
Rc<DxvkDataBuffer> buffer = new DxvkDataBuffer(Size);
return buffer->alloc(Size);
} else {
if (m_updateBuffer == nullptr)
m_updateBuffer = new DxvkDataBuffer(UpdateBufferSize);
DxvkDataSlice slice = m_updateBuffer->alloc(Size);
if (slice.ptr() == nullptr) {
m_updateBuffer = new DxvkDataBuffer(UpdateBufferSize);
slice = m_updateBuffer->alloc(Size);
}
return slice;
}
}
DxvkBufferSlice D3D11DeviceContext::AllocStagingBuffer(
VkDeviceSize Size) {
DxvkBufferCreateInfo info;
info.size = Size;
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
info.access = VK_ACCESS_TRANSFER_READ_BIT
| VK_ACCESS_SHADER_READ_BIT;
return DxvkBufferSlice(m_device->createBuffer(info,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
}
DxvkCsChunkRef D3D11DeviceContext::AllocCsChunk() {
return m_parent->AllocCsChunk(m_csFlags);
}
void D3D11DeviceContext::InitDefaultPrimitiveTopology(
DxvkInputAssemblyState* pIaState) {
pIaState->primitiveTopology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
pIaState->primitiveRestart = VK_FALSE;
pIaState->patchVertexCount = 0;
}
void D3D11DeviceContext::InitDefaultRasterizerState(
DxvkRasterizerState* pRsState) {
pRsState->polygonMode = VK_POLYGON_MODE_FILL;
pRsState->cullMode = VK_CULL_MODE_BACK_BIT;
pRsState->frontFace = VK_FRONT_FACE_CLOCKWISE;
pRsState->depthClipEnable = VK_TRUE;
pRsState->depthBiasEnable = VK_FALSE;
pRsState->conservativeMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
pRsState->sampleCount = 0;
}
void D3D11DeviceContext::InitDefaultDepthStencilState(
DxvkDepthStencilState* pDsState) {
VkStencilOpState stencilOp;
stencilOp.failOp = VK_STENCIL_OP_KEEP;
stencilOp.passOp = VK_STENCIL_OP_KEEP;
stencilOp.depthFailOp = VK_STENCIL_OP_KEEP;
stencilOp.compareOp = VK_COMPARE_OP_ALWAYS;
stencilOp.compareMask = D3D11_DEFAULT_STENCIL_READ_MASK;
stencilOp.writeMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
stencilOp.reference = 0;
pDsState->enableDepthTest = VK_TRUE;
pDsState->enableDepthWrite = VK_TRUE;
pDsState->enableStencilTest = VK_FALSE;
pDsState->depthCompareOp = VK_COMPARE_OP_LESS;
pDsState->stencilOpFront = stencilOp;
pDsState->stencilOpBack = stencilOp;
}
void D3D11DeviceContext::InitDefaultBlendState(
DxvkBlendMode* pCbState,
DxvkLogicOpState* pLoState,
DxvkMultisampleState* pMsState,
UINT SampleMask) {
pCbState->enableBlending = VK_FALSE;
pCbState->colorSrcFactor = VK_BLEND_FACTOR_ONE;
pCbState->colorDstFactor = VK_BLEND_FACTOR_ZERO;
pCbState->colorBlendOp = VK_BLEND_OP_ADD;
pCbState->alphaSrcFactor = VK_BLEND_FACTOR_ONE;
pCbState->alphaDstFactor = VK_BLEND_FACTOR_ZERO;
pCbState->alphaBlendOp = VK_BLEND_OP_ADD;
pCbState->writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
pLoState->enableLogicOp = VK_FALSE;
pLoState->logicOp = VK_LOGIC_OP_NO_OP;
pMsState->sampleMask = SampleMask;
pMsState->enableAlphaToCoverage = VK_FALSE;
}
2017-10-11 09:51:48 +02:00
}