1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-14 18:23:52 +01:00
dxvk/src/d3d11/d3d11_context.cpp

2105 lines
76 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"
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* parent,
Rc<DxvkDevice> device)
: m_parent(parent),
m_device(device) {
m_context = m_device->createContext();
m_context->beginRecording(
m_device->createCommandList());
// Create default state objects. We won't ever return them
// to the application, but we'll use them to apply state.
Com<ID3D11BlendState> defaultBlendState;
Com<ID3D11DepthStencilState> defaultDepthStencilState;
Com<ID3D11RasterizerState> defaultRasterizerState;
if (FAILED(m_parent->CreateBlendState (nullptr, &defaultBlendState))
|| FAILED(m_parent->CreateDepthStencilState(nullptr, &defaultDepthStencilState))
|| FAILED(m_parent->CreateRasterizerState (nullptr, &defaultRasterizerState)))
throw DxvkError("D3D11DeviceContext: Failed to create default state objects");
// Apply default state to the context. This is required
// in order to initialize the DXVK contex properly.
m_defaultBlendState = static_cast<D3D11BlendState*>(defaultBlendState.ptr());
m_defaultBlendState->BindToContext(m_context, 0xFFFFFFFF);
m_defaultDepthStencilState = static_cast<D3D11DepthStencilState*>(defaultDepthStencilState.ptr());
m_defaultDepthStencilState->BindToContext(m_context);
m_defaultRasterizerState = static_cast<D3D11RasterizerState*>(defaultRasterizerState.ptr());
m_defaultRasterizerState->BindToContext(m_context);
m_context->setBlendConstants(m_state.om.blendFactor);
m_context->setStencilReference(m_state.om.stencilRef);
2018-01-10 19:07:55 +01:00
// Create a default sampler that we're going to bind
// when the application binds null to a sampler slot.
m_defaultSampler = CreateDefaultSampler();
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
}
2017-12-12 12:50:52 +01:00
ULONG STDMETHODCALLTYPE D3D11DeviceContext::AddRef() {
return m_parent->AddRef();
}
2017-12-12 12:50:52 +01:00
ULONG STDMETHODCALLTYPE D3D11DeviceContext::Release() {
return m_parent->Release();
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11DeviceContext::QueryInterface(
2017-10-11 09:51:48 +02:00
REFIID riid,
void** ppvObject) {
2017-10-15 21:50:34 +02:00
COM_QUERY_IFACE(riid, ppvObject, IUnknown);
COM_QUERY_IFACE(riid, ppvObject, ID3D11DeviceChild);
2017-10-11 09:51:48 +02:00
COM_QUERY_IFACE(riid, ppvObject, ID3D11DeviceContext);
Logger::warn("D3D11DeviceContext::QueryInterface: Unknown interface query");
return E_NOINTERFACE;
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GetDevice(ID3D11Device **ppDevice) {
*ppDevice = ref(m_parent);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE D3D11DeviceContext::GetType() {
return m_type;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
UINT STDMETHODCALLTYPE D3D11DeviceContext::GetContextFlags() {
return m_flags;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::ClearState() {
this->IASetInputLayout(nullptr);
this->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED);
this->IASetIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
for (uint32_t i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) {
ID3D11Buffer* buffer = nullptr;
const UINT offset = 0;
const UINT stride = 0;
this->IASetVertexBuffers(i, 1, &buffer, &offset, &stride);
}
this->VSSetShader(nullptr, nullptr, 0);
this->HSSetShader(nullptr, nullptr, 0);
this->DSSetShader(nullptr, nullptr, 0);
2017-12-18 12:53:53 +01:00
this->GSSetShader(nullptr, nullptr, 0);
2017-12-07 10:12:48 +01:00
this->PSSetShader(nullptr, nullptr, 0);
this->CSSetShader(nullptr, nullptr, 0);
for (uint32_t i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) {
ID3D11Buffer* buffer = nullptr;
this->VSSetConstantBuffers(i, 1, &buffer);
this->HSSetConstantBuffers(i, 1, &buffer);
this->DSSetConstantBuffers(i, 1, &buffer);
this->GSSetConstantBuffers(i, 1, &buffer);
this->PSSetConstantBuffers(i, 1, &buffer);
this->CSSetConstantBuffers(i, 1, &buffer);
}
for (uint32_t i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++) {
ID3D11ShaderResourceView* view = nullptr;
this->VSSetShaderResources(i, 1, &view);
this->HSSetShaderResources(i, 1, &view);
this->DSSetShaderResources(i, 1, &view);
this->GSSetShaderResources(i, 1, &view);
this->PSSetShaderResources(i, 1, &view);
this->CSSetShaderResources(i, 1, &view);
}
for (uint32_t i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; i++) {
ID3D11SamplerState* sampler = nullptr;
this->VSSetSamplers(i, 1, &sampler);
this->HSSetSamplers(i, 1, &sampler);
this->DSSetSamplers(i, 1, &sampler);
this->GSSetSamplers(i, 1, &sampler);
this->PSSetSamplers(i, 1, &sampler);
this->CSSetSamplers(i, 1, &sampler);
}
for (uint32_t i = 0; i < D3D11_1_UAV_SLOT_COUNT; i++) {
ID3D11UnorderedAccessView* uav = nullptr;
this->CSSetUnorderedAccessViews(i, 1, &uav, nullptr);
}
this->OMSetRenderTargets(0, nullptr, nullptr);
this->OMSetBlendState(nullptr, nullptr, D3D11_DEFAULT_SAMPLE_MASK);
this->OMSetDepthStencilState(nullptr, 0);
this->RSSetState(nullptr);
this->RSSetViewports(0, nullptr);
this->RSSetScissorRects(0, nullptr);
// this->SOSetTargets(0, nullptr, nullptr);
// this->SetPredication(nullptr, FALSE);
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::Flush() {
if (m_type == D3D11_DEVICE_CONTEXT_IMMEDIATE) {
2018-01-13 05:00:27 +01:00
m_parent->FlushInitContext();
m_drawCount = 0;
m_device->submitCommandList(
m_context->endRecording(),
nullptr, nullptr);
m_context->beginRecording(
m_device->createCommandList());
} else {
Logger::err("D3D11DeviceContext::Flush: Not supported on deferred context");
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::ExecuteCommandList(
2017-10-11 09:51:48 +02:00
ID3D11CommandList* pCommandList,
WINBOOL RestoreContextState) {
Logger::err("D3D11DeviceContext::ExecuteCommandList: Not implemented");
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11DeviceContext::FinishCommandList(
2017-10-11 09:51:48 +02:00
WINBOOL RestoreDeferredContextState,
ID3D11CommandList **ppCommandList) {
if (m_type == D3D11_DEVICE_CONTEXT_DEFERRED) {
Logger::err("D3D11DeviceContext::FinishCommandList: Not implemented");
return E_NOTIMPL;
} else {
Logger::err("D3D11DeviceContext::FinishCommandList: Not supported on immediate context");
return DXGI_ERROR_INVALID_CALL;
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11DeviceContext::Map(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pResource,
UINT Subresource,
D3D11_MAP MapType,
UINT MapFlags,
D3D11_MAPPED_SUBRESOURCE* pMappedResource) {
2017-12-10 17:36:32 +01:00
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
if (resourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
const D3D11Buffer* resource = static_cast<D3D11Buffer*>(pResource);
const Rc<DxvkBuffer> buffer = resource->GetBufferSlice().buffer();
if (buffer->mapPtr(0) == nullptr) {
Logger::err("D3D11: Cannot map a device-local buffer");
return E_INVALIDARG;
}
if (pMappedResource == nullptr)
return S_OK;
if (buffer->isInUse()) {
// Don't wait if the application tells us not to
if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT)
return DXGI_ERROR_WAS_STILL_DRAWING;
// Invalidate the buffer in order to avoid synchronization
// if the application does not need the buffer contents to
// be preserved. The No Overwrite mode does not require any
// sort of synchronization, but should be used with care.
if (MapType == D3D11_MAP_WRITE_DISCARD) {
m_context->invalidateBuffer(buffer);
} else if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) {
this->Flush();
this->Synchronize();
}
}
pMappedResource->pData = buffer->mapPtr(0);
pMappedResource->RowPitch = buffer->info().size;
pMappedResource->DepthPitch = buffer->info().size;
return S_OK;
2017-12-10 17:36:32 +01:00
} else {
// Mapping an image is sadly not as simple as mapping a buffer
// because applications tend to ignore row and layer strides.
// We use a buffer instead and then perform a copy.
D3D11TextureInfo* textureInfo
= GetCommonTextureInfo(pResource);
if (textureInfo->imageBuffer == nullptr) {
Logger::err("D3D11DeviceContext: Cannot map a device-local image");
return E_INVALIDARG;
}
// FIXME copy current image contents into the
// buffer unless D3D11_MAP_DISCARD is used.
if (MapType == D3D11_MAP_READ || MapType == D3D11_MAP_READ_WRITE) {
Logger::err("D3D11DeviceContext: Read-only and Read-Write mapping of images currently not supported");
return E_INVALIDARG;
}
if (pMappedResource == nullptr)
return S_FALSE;
if (textureInfo->imageBuffer->isInUse()) {
// Don't wait if the application tells us not to
if (MapFlags & D3D11_MAP_FLAG_DO_NOT_WAIT)
return DXGI_ERROR_WAS_STILL_DRAWING;
if (MapType == D3D11_MAP_WRITE_DISCARD) {
m_context->invalidateBuffer(textureInfo->imageBuffer);
} else if (MapType != D3D11_MAP_WRITE_NO_OVERWRITE) {
this->Flush();
this->Synchronize();
}
}
// Query format and subresource in order to compute
// the row pitch and layer pitch properly.
const DxvkImageCreateInfo& imageInfo = textureInfo->image->info();
const DxvkFormatInfo* formatInfo = imageFormatInfo(imageInfo.format);
textureInfo->mappedSubresource =
GetSubresourceFromIndex(VK_IMAGE_ASPECT_COLOR_BIT,
imageInfo.mipLevels, Subresource);
const VkExtent3D levelExtent = textureInfo->image
->mipLevelExtent(textureInfo->mappedSubresource.mipLevel);
const VkExtent3D blockCount = {
levelExtent.width / formatInfo->blockSize.width,
levelExtent.height / formatInfo->blockSize.height,
levelExtent.depth / formatInfo->blockSize.depth };
// Set up map pointer. Data is tightly packed within the mapped buffer.
pMappedResource->pData = textureInfo->imageBuffer->mapPtr(0);
pMappedResource->RowPitch = formatInfo->elementSize * blockCount.width;
pMappedResource->DepthPitch = formatInfo->elementSize * blockCount.width * blockCount.height;
return S_OK;
2017-12-10 17:36:32 +01:00
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::Unmap(
2017-10-11 09:51:48 +02:00
ID3D11Resource* pResource,
UINT Subresource) {
D3D11_RESOURCE_DIMENSION resourceDim = D3D11_RESOURCE_DIMENSION_UNKNOWN;
pResource->GetType(&resourceDim);
if (resourceDim != D3D11_RESOURCE_DIMENSION_BUFFER) {
// Now that data has been written into the buffer,
// we need to copy its contents into the image
const D3D11TextureInfo* textureInfo
= GetCommonTextureInfo(pResource);
const VkExtent3D levelExtent = textureInfo->image
->mipLevelExtent(textureInfo->mappedSubresource.mipLevel);
const VkImageSubresourceLayers subresourceLayers = {
textureInfo->mappedSubresource.aspectMask,
textureInfo->mappedSubresource.mipLevel,
textureInfo->mappedSubresource.arrayLayer, 1 };
m_context->copyBufferToImage(
textureInfo->image, subresourceLayers,
VkOffset3D { 0, 0, 0 }, levelExtent,
textureInfo->imageBuffer, 0, { 0u, 0u });
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::Begin(ID3D11Asynchronous *pAsync) {
2018-01-02 12:07:30 +01:00
// Logger::err("D3D11DeviceContext::Begin: Not implemented");
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::End(ID3D11Asynchronous *pAsync) {
2018-01-02 12:07:30 +01:00
// Logger::err("D3D11DeviceContext::End: Not implemented");
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
HRESULT STDMETHODCALLTYPE D3D11DeviceContext::GetData(
2017-10-11 09:51:48 +02:00
ID3D11Asynchronous* pAsync,
void* pData,
UINT DataSize,
UINT GetDataFlags) {
if (pAsync->GetDataSize() != DataSize) {
Logger::err("D3D11DeviceContext: GetData: Data size mismatch");
return E_INVALIDARG;
}
// This method handles various different but incompatible interfaces,
// so we have to find out what we are actually dealing with
Com<ID3D11Query> query;
if (SUCCEEDED(pAsync->QueryInterface(__uuidof(ID3D11Query), reinterpret_cast<void**>(&query))))
return static_cast<D3D11Query*>(query.ptr())->GetData(pData, GetDataFlags);
// The interface is not supported
Logger::err("D3D11DeviceContext: GetData: Unsupported Async type");
return E_INVALIDARG;
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,
WINBOOL PredicateValue) {
Logger::err("D3D11DeviceContext::SetPredication: Not implemented");
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GetPredication(
2017-10-11 09:51:48 +02:00
ID3D11Predicate** ppPredicate,
WINBOOL* pPredicateValue) {
Logger::err("D3D11DeviceContext::GetPredication: Not implemented");
}
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) {
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("D3D11DeviceContext: CopySubresourceRegion: Mismatched resource types");
return;
}
if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
Logger::err("D3D11DeviceContext::CopySubresourceRegion: Buffers not supported");
} else {
const D3D11TextureInfo* dstTextureInfo = GetCommonTextureInfo(pDstResource);
const D3D11TextureInfo* srcTextureInfo = GetCommonTextureInfo(pSrcResource);
const DxvkFormatInfo* dstFormatInfo = imageFormatInfo(dstTextureInfo->image->info().format);
const DxvkFormatInfo* srcFormatInfo = imageFormatInfo(srcTextureInfo->image->info().format);
const VkImageSubresource dstSubresource =
GetSubresourceFromIndex(
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
dstTextureInfo->image->info().mipLevels, DstSubresource);
const VkImageSubresource srcSubresource =
GetSubresourceFromIndex(
dstFormatInfo->aspectMask & srcFormatInfo->aspectMask,
srcTextureInfo->image->info().mipLevels, SrcSubresource);
VkOffset3D srcOffset = { 0, 0, 0 };
VkOffset3D dstOffset = {
static_cast<int32_t>(DstX),
static_cast<int32_t>(DstY),
static_cast<int32_t>(DstZ) };
VkExtent3D extent = srcTextureInfo->image->mipLevelExtent(srcSubresource.mipLevel);
if (pSrcBox != nullptr) {
if (pSrcBox->left >= pSrcBox->right
|| pSrcBox->top >= pSrcBox->bottom
|| pSrcBox->front >= pSrcBox->back)
return; // no-op, but legal
srcOffset.x = pSrcBox->left;
srcOffset.y = pSrcBox->top;
srcOffset.z = pSrcBox->front;
extent.width = pSrcBox->right - pSrcBox->left;
extent.height = pSrcBox->bottom - pSrcBox->top;
extent.depth = pSrcBox->back - pSrcBox->front;
}
const VkImageSubresourceLayers dstLayers = {
dstSubresource.aspectMask,
dstSubresource.mipLevel,
dstSubresource.arrayLayer, 1 };
const VkImageSubresourceLayers srcLayers = {
srcSubresource.aspectMask,
srcSubresource.mipLevel,
srcSubresource.arrayLayer, 1 };
m_context->copyImage(
dstTextureInfo->image, dstLayers, dstOffset,
srcTextureInfo->image, srcLayers, srcOffset,
extent);
}
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) {
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("D3D11DeviceContext: CopyResource: Mismatched resource types");
return;
}
if (dstResourceDim == D3D11_RESOURCE_DIMENSION_BUFFER) {
auto dstBuffer = static_cast<D3D11Buffer*>(pDstResource)->GetBufferSlice();
auto srcBuffer = static_cast<D3D11Buffer*>(pSrcResource)->GetBufferSlice();
if (dstBuffer.length() != srcBuffer.length()) {
Logger::err("D3D11DeviceContext: CopyResource: Mismatched buffer size");
return;
}
m_context->copyBuffer(
dstBuffer.buffer(),
dstBuffer.offset(),
srcBuffer.buffer(),
srcBuffer.offset(),
srcBuffer.length());
} else {
const D3D11TextureInfo* dstTextureInfo = GetCommonTextureInfo(pDstResource);
const D3D11TextureInfo* srcTextureInfo = GetCommonTextureInfo(pSrcResource);
VkExtent3D extent = srcTextureInfo->image->mipLevelExtent(
dstTextureInfo->mappedSubresource.mipLevel);
const VkImageSubresourceLayers dstLayers = {
dstTextureInfo->mappedSubresource.aspectMask,
dstTextureInfo->mappedSubresource.mipLevel,
dstTextureInfo->mappedSubresource.arrayLayer, 1 };
const VkImageSubresourceLayers srcLayers = {
srcTextureInfo->mappedSubresource.aspectMask,
srcTextureInfo->mappedSubresource.mipLevel,
srcTextureInfo->mappedSubresource.arrayLayer, 1 };
m_context->copyImage(
dstTextureInfo->image, dstLayers, VkOffset3D { 0, 0, 0 },
srcTextureInfo->image, srcLayers, VkOffset3D { 0, 0, 0 },
extent);
}
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) {
auto buf = static_cast<D3D11Buffer*>(pDstBuffer);
auto uav = static_cast<D3D11UnorderedAccessView*>(pSrcView);
const DxvkBufferSlice dstSlice = buf->GetBufferSlice(DstAlignedByteOffset);
const DxvkBufferSlice srcSlice = uav->GetCounterSlice();
m_context->copyBuffer(
dstSlice.buffer(),
dstSlice.offset(),
srcSlice.buffer(),
srcSlice.offset(),
sizeof(uint32_t));
2017-10-11 09:51:48 +02:00
}
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]) {
2017-12-04 13:39:37 +01:00
auto rtv = static_cast<D3D11RenderTargetView*>(pRenderTargetView);
const Rc<DxvkImageView> dxvkView = rtv->GetImageView();
// Find out whether the given attachment is currently bound
// or not, and if it is, which attachment index it has.
int32_t attachmentIndex = -1;
for (uint32_t i = 0; i < m_state.om.renderTargetViews.size(); i++) {
if (m_state.om.renderTargetViews.at(i) == rtv)
attachmentIndex = i;
}
// Copy the clear color into a clear value structure.
// This should also work for images that don nott have
// a floating point format.
VkClearColorValue clearValue;
std::memcpy(clearValue.float32, ColorRGBA,
sizeof(clearValue.float32));
if (attachmentIndex >= 0) {
// Image is bound to the pipeline for rendering. We can
// use the clear function that operates on attachments.
VkClearAttachment clearInfo;
clearInfo.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
clearInfo.colorAttachment = static_cast<uint32_t>(attachmentIndex);
clearInfo.clearValue.color = clearValue;
// Clear the full area. On FL 9.x, only the first array
// layer will be cleared, rather than all array layers.
VkClearRect clearRect;
clearRect.rect.offset.x = 0;
clearRect.rect.offset.y = 0;
clearRect.rect.extent.width = dxvkView->mipLevelExtent(0).width;
clearRect.rect.extent.height = dxvkView->mipLevelExtent(0).height;
clearRect.baseArrayLayer = 0;
clearRect.layerCount = dxvkView->imageInfo().numLayers;
if (m_parent->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0)
clearRect.layerCount = 1;
m_context->clearRenderTarget(clearInfo, clearRect);
} else {
// Image is not bound to the pipeline. We can still clear
// it, but we'll have to use a generic clear function.
m_context->clearColorImage(dxvkView->image(),
clearValue, dxvkView->subresources());
}
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]) {
Logger::err("D3D11DeviceContext::ClearUnorderedAccessViewUint: Not implemented");
}
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]) {
Logger::err("D3D11DeviceContext::ClearUnorderedAccessViewFloat: Not implemented");
}
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) {
auto dsv = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
const Rc<DxvkImageView> dxvkView = dsv->GetImageView();
VkClearDepthStencilValue clearValue;
clearValue.depth = Depth;
clearValue.stencil = Stencil;
if (m_state.om.depthStencilView == dsv) {
// Image is bound to the pipeline for rendering. We can
// use the clear function that operates on attachments.
VkClearAttachment clearInfo;
clearInfo.aspectMask = 0;
clearInfo.colorAttachment = 0;
clearInfo.clearValue.depthStencil = clearValue;
if (ClearFlags & D3D11_CLEAR_DEPTH)
clearInfo.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (ClearFlags & D3D11_CLEAR_STENCIL)
clearInfo.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
// Clear the full area
VkClearRect clearRect;
clearRect.rect.offset.x = 0;
clearRect.rect.offset.y = 0;
clearRect.rect.extent.width = dxvkView->mipLevelExtent(0).width;
clearRect.rect.extent.height = dxvkView->mipLevelExtent(0).height;
clearRect.baseArrayLayer = 0;
clearRect.layerCount = dxvkView->imageInfo().numLayers;
// FIXME Is this correct? Docs don't say anything
if (m_parent->GetFeatureLevel() < D3D_FEATURE_LEVEL_10_0)
clearRect.layerCount = 1;
m_context->clearRenderTarget(clearInfo, clearRect);
} else {
m_context->clearDepthStencilImage(dxvkView->image(),
clearValue, dxvkView->subresources());
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::GenerateMips(ID3D11ShaderResourceView* pShaderResourceView) {
2017-10-11 09:51:48 +02:00
Logger::err("D3D11DeviceContext::GenerateMips: Not implemented");
}
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) {
// 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 = 0;
VkDeviceSize size = bufferSlice.length();
if (pDstBox != nullptr) {
offset = pDstBox->left;
size = pDstBox->right - pDstBox->left;
}
if (offset + size > bufferSlice.length()) {
Logger::err("D3D11DeviceContext: Buffer update range out of bounds");
return;
}
if (size != 0) {
m_context->updateBuffer(
bufferSlice.buffer(),
bufferSlice.offset() + offset,
size, pSrcData);
}
} else {
const D3D11TextureInfo* textureInfo
= GetCommonTextureInfo(pDstResource);
const VkImageSubresource subresource =
GetSubresourceFromIndex(VK_IMAGE_ASPECT_COLOR_BIT,
textureInfo->image->info().mipLevels, DstSubresource);
VkOffset3D offset = { 0, 0, 0 };
VkExtent3D extent = textureInfo->image->mipLevelExtent(subresource.mipLevel);
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;
}
const VkImageSubresourceLayers layers = {
subresource.aspectMask,
subresource.mipLevel,
subresource.arrayLayer, 1 };
m_context->updateImage(
textureInfo->image, layers,
offset, extent, pSrcData,
SrcRowPitch, SrcDepthPitch);
}
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) {
Logger::err("D3D11DeviceContext::SetResourceMinLOD: Not implemented");
}
2017-12-12 12:50:52 +01:00
FLOAT STDMETHODCALLTYPE D3D11DeviceContext::GetResourceMinLOD(ID3D11Resource* pResource) {
2017-10-11 09:51:48 +02:00
Logger::err("D3D11DeviceContext::GetResourceMinLOD: Not implemented");
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) {
Logger::err("D3D11DeviceContext::ResolveSubresource: Not implemented");
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::DrawAuto() {
2017-10-11 09:51:48 +02:00
Logger::err("D3D11DeviceContext::DrawAuto: Not implemented");
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::Draw(
2017-10-11 09:51:48 +02:00
UINT VertexCount,
UINT StartVertexLocation) {
m_context->draw(
VertexCount, 1,
StartVertexLocation, 0);
m_drawCount += 1;
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) {
m_context->drawIndexed(
IndexCount, 1,
StartIndexLocation,
BaseVertexLocation, 0);
m_drawCount += 1;
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) {
m_context->draw(
VertexCountPerInstance,
InstanceCount,
StartVertexLocation,
StartInstanceLocation);
m_drawCount += 1;
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) {
m_context->drawIndexed(
IndexCountPerInstance,
InstanceCount,
StartIndexLocation,
BaseVertexLocation,
StartInstanceLocation);
m_drawCount += 1;
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) {
D3D11Buffer* buffer = static_cast<D3D11Buffer*>(pBufferForArgs);
DxvkBufferSlice bufferSlice = buffer->GetBufferSlice(AlignedByteOffsetForArgs);
m_context->drawIndexedIndirect(bufferSlice, 1, 0);
m_drawCount += 1;
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) {
D3D11Buffer* buffer = static_cast<D3D11Buffer*>(pBufferForArgs);
DxvkBufferSlice bufferSlice = buffer->GetBufferSlice(AlignedByteOffsetForArgs);
m_context->drawIndirect(bufferSlice, 1, 0);
m_drawCount += 1;
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) {
m_context->dispatch(
ThreadGroupCountX,
ThreadGroupCountY,
ThreadGroupCountZ);
m_drawCount += 1;
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) {
D3D11Buffer* buffer = static_cast<D3D11Buffer*>(pBufferForArgs);
DxvkBufferSlice bufferSlice = buffer->GetBufferSlice(AlignedByteOffsetForArgs);
m_context->dispatchIndirect(bufferSlice);
m_drawCount += 1;
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IASetInputLayout(ID3D11InputLayout* pInputLayout) {
auto inputLayout = static_cast<D3D11InputLayout*>(pInputLayout);
if (m_state.ia.inputLayout != inputLayout) {
m_state.ia.inputLayout = inputLayout;
2017-12-08 00:44:58 +01:00
if (inputLayout != nullptr)
inputLayout->BindToContext(m_context);
else
m_context->setInputLayout(0, nullptr, 0, nullptr);
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY Topology) {
if (m_state.ia.primitiveTopology != Topology) {
m_state.ia.primitiveTopology = Topology;
if (Topology == D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED)
return;
const DxvkInputAssemblyState iaState = [&] () -> DxvkInputAssemblyState {
switch (Topology) {
case D3D11_PRIMITIVE_TOPOLOGY_POINTLIST:
return { VK_PRIMITIVE_TOPOLOGY_POINT_LIST, VK_FALSE };
case D3D11_PRIMITIVE_TOPOLOGY_LINELIST:
return { VK_PRIMITIVE_TOPOLOGY_LINE_LIST, VK_FALSE };
case D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP:
return { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, VK_TRUE };
case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST:
return { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_FALSE };
case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP:
return { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, VK_TRUE };
case D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ:
return { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, VK_FALSE };
case D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ:
return { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, VK_TRUE };
case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ:
return { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, VK_FALSE };
case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ:
return { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, VK_TRUE };
default:
Logger::err(str::format("D3D11DeviceContext::IASetPrimitiveTopology: Unknown primitive topology: ", Topology));
return { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_FALSE };
}
}();
m_context->setInputAssemblyState(iaState);
}
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) {
// TODO check if any of these buffers
// are bound as UAVs or stream outputs
for (uint32_t i = 0; i < NumBuffers; i++) {
auto newBuffer = static_cast<D3D11Buffer*>(ppVertexBuffers[i]);
2017-12-15 19:11:10 +01:00
m_state.ia.vertexBuffers[i].buffer = newBuffer;
m_state.ia.vertexBuffers[i].offset = pOffsets[i];
m_state.ia.vertexBuffers[i].stride = pStrides[i];
if (newBuffer != nullptr) {
m_context->bindVertexBuffer(StartSlot + i,
newBuffer->GetBufferSlice(pOffsets[i]),
pStrides[i]);
} else {
m_context->bindVertexBuffer(StartSlot + i,
DxvkBufferSlice(), 0);
}
}
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) {
auto newBuffer = static_cast<D3D11Buffer*>(pIndexBuffer);
m_state.ia.indexBuffer.buffer = newBuffer;
m_state.ia.indexBuffer.offset = Offset;
m_state.ia.indexBuffer.format = Format;
// As in Vulkan, the index format can be either a 32-bit
// unsigned integer or a 16-bit unsigned integer, no other
// formats are allowed.
if (newBuffer != nullptr) {
VkIndexType indexType = VK_INDEX_TYPE_UINT32;
switch (Format) {
case DXGI_FORMAT_R16_UINT: indexType = VK_INDEX_TYPE_UINT16; break;
case DXGI_FORMAT_R32_UINT: indexType = VK_INDEX_TYPE_UINT32; break;
default: Logger::err(str::format("D3D11: Invalid index format: ", Format));
}
m_context->bindIndexBuffer(
newBuffer->GetBufferSlice(Offset),
indexType);
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IAGetInputLayout(ID3D11InputLayout** ppInputLayout) {
*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) {
*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) {
Logger::err("D3D11DeviceContext::IAGetVertexBuffers: Not implemented");
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::IAGetIndexBuffer(
2017-10-11 09:51:48 +02:00
ID3D11Buffer** pIndexBuffer,
DXGI_FORMAT* Format,
UINT* Offset) {
Logger::err("D3D11DeviceContext::IAGetIndexBuffer: Not implemented");
}
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) {
2017-12-07 10:12:48 +01:00
auto shader = static_cast<D3D11VertexShader*>(pVertexShader);
if (NumClassInstances != 0)
Logger::err("D3D11DeviceContext::VSSetShader: Class instances not supported");
if (m_state.vs.shader != shader) {
m_state.vs.shader = shader;
m_context->bindShader(VK_SHADER_STAGE_VERTEX_BIT,
shader != nullptr ? shader->GetShader() : nullptr);
}
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) {
this->BindConstantBuffers(
DxbcProgramType::VertexShader,
m_state.vs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
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) {
this->BindShaderResources(
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) {
2017-12-09 21:17:26 +01:00
this->BindSamplers(
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) {
2017-12-11 14:21:24 +01:00
if (ppVertexShader != nullptr)
*ppVertexShader = m_state.vs.shader.ref();
if (pNumClassInstances != nullptr) {
Logger::err("D3D11: VSGetShader: Class instances not implemented");
*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) {
for (uint32_t i = 0; i < NumBuffers; i++)
ppConstantBuffers[i] = m_state.vs.constantBuffers.at(StartSlot + i).ref();
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) {
for (uint32_t i = 0; i < NumViews; i++)
ppShaderResourceViews[i] = m_state.vs.shaderResources.at(StartSlot + i).ref();
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) {
for (uint32_t i = 0; i < NumSamplers; i++)
ppSamplers[i] = m_state.vs.samplers.at(StartSlot + i).ref();
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) {
if (m_state.hs.shader.ptr() != pHullShader)
Logger::err("D3D11DeviceContext::HSSetShader: Not implemented");
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) {
this->BindShaderResources(
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) {
this->BindConstantBuffers(
DxbcProgramType::HullShader,
m_state.hs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
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) {
this->BindSamplers(
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) {
if (ppHullShader != nullptr)
*ppHullShader = m_state.hs.shader.ref();
if (pNumClassInstances != nullptr) {
Logger::err("D3D11: HSGetShader: Class instances not implemented");
*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) {
for (uint32_t i = 0; i < NumBuffers; i++)
ppConstantBuffers[i] = m_state.hs.constantBuffers.at(StartSlot + i).ref();
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) {
for (uint32_t i = 0; i < NumViews; i++)
ppShaderResourceViews[i] = m_state.hs.shaderResources.at(StartSlot + i).ref();
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) {
for (uint32_t i = 0; i < NumSamplers; i++)
ppSamplers[i] = m_state.hs.samplers.at(StartSlot + i).ref();
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) {
if (m_state.ds.shader.ptr() != pDomainShader)
Logger::err("D3D11DeviceContext::DSSetShader: Not implemented");
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) {
this->BindShaderResources(
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) {
this->BindConstantBuffers(
DxbcProgramType::DomainShader,
m_state.ds.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
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) {
this->BindSamplers(
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) {
if (ppDomainShader != nullptr)
*ppDomainShader = m_state.ds.shader.ref();
if (pNumClassInstances != nullptr) {
Logger::err("D3D11: DSGetShader: Class instances not implemented");
*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) {
for (uint32_t i = 0; i < NumBuffers; i++)
ppConstantBuffers[i] = m_state.ds.constantBuffers.at(StartSlot + i).ref();
2017-10-11 09:51:48 +02:00
}
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) {
for (uint32_t i = 0; i < NumViews; i++)
ppShaderResourceViews[i] = m_state.ds.shaderResources.at(StartSlot + i).ref();
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) {
for (uint32_t i = 0; i < NumSamplers; i++)
ppSamplers[i] = m_state.ds.samplers.at(StartSlot + i).ref();
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) {
2017-12-18 12:53:53 +01:00
auto shader = static_cast<D3D11GeometryShader*>(pShader);
if (NumClassInstances != 0)
Logger::err("D3D11DeviceContext::GSSetShader: Class instances not supported");
if (m_state.gs.shader != shader) {
m_state.gs.shader = shader;
m_context->bindShader(VK_SHADER_STAGE_GEOMETRY_BIT,
shader != nullptr ? shader->GetShader() : nullptr);
}
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) {
2017-12-18 12:53:53 +01:00
this->BindConstantBuffers(
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
}
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) {
2017-12-18 12:53:53 +01:00
this->BindShaderResources(
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) {
2017-12-18 12:53:53 +01:00
this->BindSamplers(
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) {
2017-12-18 12:53:53 +01:00
if (ppGeometryShader != nullptr)
*ppGeometryShader = m_state.gs.shader.ref();
if (pNumClassInstances != nullptr) {
Logger::err("D3D11: GSGetShader: Class instances not implemented");
*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) {
2017-12-18 12:53:53 +01:00
for (uint32_t i = 0; i < NumBuffers; i++)
ppConstantBuffers[i] = m_state.gs.constantBuffers.at(StartSlot + i).ref();
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) {
2017-12-18 12:53:53 +01:00
for (uint32_t i = 0; i < NumViews; i++)
ppShaderResourceViews[i] = m_state.gs.shaderResources.at(StartSlot + i).ref();
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) {
2017-12-18 12:53:53 +01:00
for (uint32_t i = 0; i < NumSamplers; i++)
ppSamplers[i] = m_state.gs.samplers.at(StartSlot + i).ref();
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) {
2017-12-07 10:12:48 +01:00
auto shader = static_cast<D3D11PixelShader*>(pPixelShader);
if (NumClassInstances != 0)
Logger::err("D3D11DeviceContext::PSSetShader: Class instances not supported");
2017-12-07 10:12:48 +01:00
if (m_state.ps.shader != shader) {
m_state.ps.shader = shader;
m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT,
shader != nullptr ? shader->GetShader() : nullptr);
}
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) {
this->BindConstantBuffers(
DxbcProgramType::PixelShader,
m_state.ps.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
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) {
this->BindShaderResources(
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) {
2017-12-09 21:17:26 +01:00
this->BindSamplers(
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) {
2017-12-11 14:21:24 +01:00
if (ppPixelShader != nullptr)
*ppPixelShader = m_state.ps.shader.ref();
if (pNumClassInstances != nullptr) {
Logger::err("D3D11: PSGetShader: Class instances not implemented");
*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) {
2017-12-11 14:21:24 +01:00
for (uint32_t i = 0; i < NumBuffers; i++)
ppConstantBuffers[i] = m_state.ps.constantBuffers.at(StartSlot + i).ref();
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) {
2017-12-11 14:21:24 +01:00
for (uint32_t i = 0; i < NumViews; i++)
ppShaderResourceViews[i] = m_state.ps.shaderResources.at(StartSlot + i).ref();
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) {
2017-12-11 14:21:24 +01:00
for (uint32_t i = 0; i < NumSamplers; i++)
ppSamplers[i] = m_state.ps.samplers.at(StartSlot + i).ref();
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) {
2017-12-21 17:27:40 +01:00
auto shader = static_cast<D3D11ComputeShader*>(pComputeShader);
if (NumClassInstances != 0)
Logger::err("D3D11DeviceContext::CSSetShader: Class instances not supported");
if (m_state.cs.shader != shader) {
m_state.cs.shader = shader;
m_context->bindShader(VK_SHADER_STAGE_COMPUTE_BIT,
shader != nullptr ? shader->GetShader() : nullptr);
}
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) {
this->BindConstantBuffers(
DxbcProgramType::ComputeShader,
m_state.cs.constantBuffers,
StartSlot, NumBuffers,
ppConstantBuffers);
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) {
this->BindShaderResources(
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) {
this->BindSamplers(
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) {
this->BindUnorderedAccessViews(
DxbcProgramType::ComputeShader,
m_state.cs.unorderedAccessViews,
StartSlot, NumUAVs,
ppUnorderedAccessViews);
if (pUAVInitialCounts != nullptr) {
this->InitUnorderedAccessViewCounters(
NumUAVs, ppUnorderedAccessViews,
pUAVInitialCounts);
}
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) {
if (ppComputeShader != nullptr)
*ppComputeShader = m_state.cs.shader.ref();
if (pNumClassInstances != nullptr) {
Logger::err("D3D11: CSGetShader: Class instances not implemented");
*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) {
for (uint32_t i = 0; i < NumBuffers; i++)
ppConstantBuffers[i] = m_state.cs.constantBuffers.at(StartSlot + i).ref();
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) {
for (uint32_t i = 0; i < NumViews; i++)
ppShaderResourceViews[i] = m_state.cs.shaderResources.at(StartSlot + i).ref();
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) {
for (uint32_t i = 0; i < NumSamplers; i++)
ppSamplers[i] = m_state.cs.samplers.at(StartSlot + i).ref();
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) {
Logger::err("D3D11DeviceContext::CSGetUnorderedAccessViews: Not implemented");
}
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) {
// Optimization: If the number of draw and dispatch calls issued
// prior to the previous context flush is above a certain threshold,
// submit the current command buffer in order to keep the GPU busy.
// This also helps keep the command buffers at a reasonable size.
if (m_drawCount >= 500)
this->Flush();
for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) {
2017-12-04 13:39:37 +01:00
D3D11RenderTargetView* view = nullptr;
2017-12-04 13:39:37 +01:00
if ((i < NumViews) && (ppRenderTargetViews[i] != nullptr))
view = static_cast<D3D11RenderTargetView*>(ppRenderTargetViews[i]);
m_state.om.renderTargetViews.at(i) = view;
}
m_state.om.depthStencilView = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
// NOTE According to the Microsoft docs, we are supposed to
// unbind overlapping shader resource views. Since this comes
// with a large performance penalty we'll ignore this until an
// application actually relies on this behaviour.
Rc<DxvkFramebuffer> framebuffer = nullptr;
if (ppRenderTargetViews != nullptr || pDepthStencilView != nullptr) {
// 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.
DxvkRenderTargets attachments;
for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) {
if (m_state.om.renderTargetViews.at(i) != nullptr)
attachments.setColorTarget(i, m_state.om.renderTargetViews.at(i)->GetImageView());
}
if (m_state.om.depthStencilView != nullptr)
attachments.setDepthTarget(m_state.om.depthStencilView->GetImageView());
if (attachments.hasAttachments())
framebuffer = m_device->createFramebuffer(attachments);
}
// Bind the framebuffer object to the context
m_context->bindFramebuffer(framebuffer);
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) {
if (NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)
OMSetRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView);
if (NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) {
// UAVs are made available to all shader stages in
// the graphics pipeline even though this code may
// suggest that they are limited to the pixel shader.
// This behaviour is only required for FL_11_1.
BindUnorderedAccessViews(
DxbcProgramType::PixelShader,
m_state.ps.unorderedAccessViews,
UAVStartSlot, NumUAVs,
ppUnorderedAccessViews);
if (pUAVInitialCounts != nullptr) {
InitUnorderedAccessViewCounters(NumUAVs,
ppUnorderedAccessViews, pUAVInitialCounts);
}
}
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) {
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;
if (blendState == nullptr)
blendState = m_defaultBlendState.ptr();
blendState->BindToContext(m_context, SampleMask);
}
if ((BlendFactor != nullptr) && (!std::memcmp(m_state.om.blendFactor, BlendFactor, 4 * sizeof(FLOAT)))) {
std::memcpy(m_state.om.blendFactor, BlendFactor, 4 * sizeof(FLOAT));
m_context->setBlendConstants(BlendFactor);
}
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) {
auto depthStencilState = static_cast<D3D11DepthStencilState*>(pDepthStencilState);
if (m_state.om.dsState != depthStencilState) {
m_state.om.dsState = depthStencilState;
if (depthStencilState == nullptr)
depthStencilState = m_defaultDepthStencilState.ptr();
depthStencilState->BindToContext(m_context);
}
if (m_state.om.stencilRef != StencilRef) {
m_state.om.stencilRef = StencilRef;
m_context->setStencilReference(StencilRef);
}
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) {
if (ppRenderTargetViews != nullptr) {
for (UINT i = 0; i < NumViews; i++)
ppRenderTargetViews[i] = i < m_state.om.renderTargetViews.size()
? m_state.om.renderTargetViews.at(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) {
Logger::err("D3D11DeviceContext::OMGetRenderTargetsAndUnorderedAccessViews: Not implemented");
}
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) {
2017-12-11 14:21:24 +01:00
if (ppBlendState != nullptr)
*ppBlendState = m_state.om.cbState.ref();
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) {
2017-12-11 14:21:24 +01:00
if (ppDepthStencilState != nullptr)
*ppDepthStencilState = m_state.om.dsState.ref();
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) {
auto rasterizerState = static_cast<D3D11RasterizerState*>(pRasterizerState);
if (m_state.rs.state != rasterizerState) {
m_state.rs.state = rasterizerState;
if (rasterizerState == nullptr)
rasterizerState = m_defaultRasterizerState.ptr();
rasterizerState->BindToContext(m_context);
// In D3D11, the rasterizer state defines
// whether the scissor test is enabled, so
// we have to update the scissor rectangles.
this->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) {
m_state.rs.numViewports = NumViewports;
for (uint32_t i = 0; i < NumViewports; i++)
m_state.rs.viewports.at(i) = pViewports[i];
this->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) {
m_state.rs.numScissors = NumRects;
for (uint32_t i = 0; i < NumRects; i++)
m_state.rs.scissors.at(i) = pRects[i];
if (m_state.rs.state != nullptr) {
D3D11_RASTERIZER_DESC rsDesc;
m_state.rs.state->GetDesc(&rsDesc);
if (rsDesc.ScissorEnable)
this->ApplyViewportState();
}
2017-10-11 09:51:48 +02:00
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::RSGetState(ID3D11RasterizerState** ppRasterizerState) {
2017-12-11 14:21:24 +01:00
if (ppRasterizerState != nullptr)
*ppRasterizerState = m_state.rs.state.ref();
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) {
if (pViewports != nullptr) {
for (uint32_t i = 0; i < *pNumViewports; i++) {
if (i < m_state.rs.numViewports) {
pViewports[i] = m_state.rs.viewports.at(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 = m_state.rs.numViewports;
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) {
if (pRects != nullptr) {
for (uint32_t i = 0; i < *pNumRects; i++) {
if (i < m_state.rs.numScissors) {
pRects[i] = m_state.rs.scissors.at(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) {
Logger::err("D3D11DeviceContext::SOSetTargets: Not implemented");
}
2017-12-12 12:50:52 +01:00
void STDMETHODCALLTYPE D3D11DeviceContext::SOGetTargets(
2017-10-11 09:51:48 +02:00
UINT NumBuffers,
ID3D11Buffer** ppSOTargets) {
Logger::err("D3D11DeviceContext::SOGetTargets: Not implemented");
}
void D3D11DeviceContext::Synchronize() {
m_device->waitForIdle();
}
void D3D11DeviceContext::BindConstantBuffers(
DxbcProgramType ShaderStage,
D3D11ConstantBufferBindings& Bindings,
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer* const* ppConstantBuffers) {
const uint32_t slotId = computeResourceSlotId(
ShaderStage, DxbcBindingType::ConstantBuffer,
StartSlot);
for (uint32_t i = 0; i < NumBuffers; i++) {
auto newBuffer = static_cast<D3D11Buffer*>(ppConstantBuffers[i]);
if (Bindings[StartSlot + i] != newBuffer) {
Bindings[StartSlot + i] = newBuffer;
if (newBuffer != nullptr) {
m_context->bindResourceBuffer(
slotId + i, newBuffer->GetBufferSlice(0));
} else {
m_context->bindResourceBuffer(
slotId + i, DxvkBufferSlice());
}
}
}
}
2017-12-09 21:17:26 +01:00
void D3D11DeviceContext::BindSamplers(
DxbcProgramType ShaderStage,
D3D11SamplerBindings& Bindings,
2017-12-09 21:17:26 +01:00
UINT StartSlot,
UINT NumSamplers,
ID3D11SamplerState* const* ppSamplers) {
const uint32_t slotId = computeResourceSlotId(
ShaderStage, DxbcBindingType::ImageSampler,
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;
2017-12-09 21:17:26 +01:00
if (sampler != nullptr) {
m_context->bindResourceSampler(
slotId + i, sampler->GetDXVKSampler());
} else {
m_context->bindResourceSampler(
2018-01-10 19:07:55 +01:00
slotId + i, m_defaultSampler);
}
2017-12-09 21:17:26 +01:00
}
}
}
void D3D11DeviceContext::BindShaderResources(
DxbcProgramType ShaderStage,
D3D11ShaderResourceBindings& Bindings,
UINT StartSlot,
UINT NumResources,
ID3D11ShaderResourceView* const* ppResources) {
const uint32_t slotId = computeResourceSlotId(
ShaderStage, DxbcBindingType::ShaderResource,
StartSlot);
for (uint32_t i = 0; i < NumResources; i++) {
auto resView = static_cast<D3D11ShaderResourceView*>(ppResources[i]);
if (Bindings[StartSlot + i] != resView) {
Bindings[StartSlot + i] = resView;
if (resView != nullptr) {
// Figure out what we have to bind based on the resource type
if (resView->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
m_context->bindResourceTexelBuffer(
slotId + i, resView->GetBufferView());
} else {
m_context->bindResourceImage(
slotId + i, resView->GetImageView());
}
} else {
// When unbinding a resource, it doesn't really matter if
// the resource type is correct, so we'll just bind a null
// image to the given resource slot
m_context->bindResourceImage(slotId + i, nullptr);
}
}
}
}
void D3D11DeviceContext::BindUnorderedAccessViews(
DxbcProgramType ShaderStage,
D3D11UnorderedAccessBindings& Bindings,
UINT StartSlot,
UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews) {
const uint32_t uavSlotId = computeResourceSlotId(
ShaderStage, DxbcBindingType::UnorderedAccessView,
StartSlot);
const uint32_t ctrSlotId = computeResourceSlotId(
ShaderStage, DxbcBindingType::UavCounter,
StartSlot);
for (uint32_t i = 0; i < NumUAVs; i++) {
auto uav = static_cast<D3D11UnorderedAccessView*>(ppUnorderedAccessViews[i]);
if (Bindings[StartSlot + i] != uav) {
Bindings[StartSlot + i] = uav;
if (uav != nullptr) {
// Figure out what we have to bind based on the resource type
if (uav->GetResourceType() == D3D11_RESOURCE_DIMENSION_BUFFER) {
m_context->bindResourceTexelBuffer(
uavSlotId + i, uav->GetBufferView());
m_context->bindResourceBuffer(
ctrSlotId + i, uav->GetCounterSlice());
} else {
m_context->bindResourceImage(
uavSlotId + i, uav->GetImageView());
}
} else {
// When unbinding a resource, it doesn't really matter if
// the resource type is correct, so we'll just bind a null
// image to the given resource slot
m_context->bindResourceTexelBuffer(uavSlotId + i, nullptr);
m_context->bindResourceBuffer (ctrSlotId + i, DxvkBufferSlice());
}
}
}
}
void D3D11DeviceContext::InitUnorderedAccessViewCounters(
UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
const UINT* pUAVInitialCounts) {
for (uint32_t i = 0; i < NumUAVs; i++) {
auto uav = static_cast<D3D11UnorderedAccessView*>(ppUnorderedAccessViews[i]);
if (uav != nullptr) {
const DxvkBufferSlice counterSlice = uav->GetCounterSlice();
const D3D11UavCounter counterValue = { pUAVInitialCounts[i] };
if (counterSlice.handle() != VK_NULL_HANDLE
&& counterValue.atomicCtr != 0xFFFFFFFFu) {
m_context->updateBuffer(
counterSlice.buffer(),
counterSlice.offset(),
counterSlice.length(),
&counterValue);
}
}
}
}
void D3D11DeviceContext::ApplyViewportState() {
// We cannot set less than one viewport in Vulkan, and
// rendering with no active viewport is illegal anyway.
if (m_state.rs.numViewports == 0)
return;
std::array<VkViewport, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> viewports;
std::array<VkRect2D, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE> scissors;
// 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++) {
const D3D11_VIEWPORT& vp = m_state.rs.viewports.at(i);
viewports.at(i) = VkViewport {
2018-01-05 16:53:12 +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++) {
// TODO D3D11 docs aren't clear about what should happen
// when there are undefined scissor rects for a viewport.
// Figure out what it does on Windows.
if (enableScissorTest && (i < m_state.rs.numScissors)) {
const D3D11_RECT& sr = m_state.rs.scissors.at(i);
scissors.at(i) = VkRect2D {
VkOffset2D { sr.left, sr.top },
VkExtent2D {
static_cast<uint32_t>(sr.right - sr.left),
static_cast<uint32_t>(sr.bottom - sr.top) } };
} else {
scissors.at(i) = VkRect2D {
VkOffset2D { 0, 0 },
VkExtent2D {
D3D11_VIEWPORT_BOUNDS_MAX,
D3D11_VIEWPORT_BOUNDS_MAX } };
}
}
m_context->setViewports(
m_state.rs.numViewports,
viewports.data(),
scissors.data());
}
2018-01-10 19:07:55 +01:00
Rc<DxvkSampler> D3D11DeviceContext::CreateDefaultSampler() {
DxvkSamplerCreateInfo info;
info.minFilter = VK_FILTER_LINEAR;
info.magFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
info.mipmapLodBias = 0.0f;
info.mipmapLodMin = -256.0f;
info.mipmapLodMax = 256.0f;
info.useAnisotropy = VK_FALSE;
info.maxAnisotropy = 1.0f;
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.compareToDepth = VK_FALSE;
info.compareOp = VK_COMPARE_OP_NEVER;
info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
info.usePixelCoord = VK_FALSE;
return m_device->createSampler(info);
}
2017-10-11 09:51:48 +02:00
}