mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 22:08:59 +01:00
[d3d11] Move Apply* methods to D3D11CommonContext
This commit is contained in:
parent
7c82ed35b2
commit
17c318864e
@ -502,312 +502,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::ApplyInputLayout() {
|
||||
auto inputLayout = m_state.ia.inputLayout.prvRef();
|
||||
|
||||
if (likely(inputLayout != nullptr)) {
|
||||
EmitCs([
|
||||
cInputLayout = std::move(inputLayout)
|
||||
] (DxvkContext* ctx) {
|
||||
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 };
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::ApplyRasterizerSampleCount() {
|
||||
DxbcPushConstants pc;
|
||||
pc.rasterizerSampleCount = m_state.om.sampleCount;
|
||||
|
||||
if (unlikely(!m_state.om.sampleCount)) {
|
||||
pc.rasterizerSampleCount = m_state.rs.state->Desc()->ForcedSampleCount;
|
||||
|
||||
if (!m_state.om.sampleCount)
|
||||
pc.rasterizerSampleCount = 1;
|
||||
}
|
||||
|
||||
EmitCs([
|
||||
cPushConstants = pc
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->pushConstants(0, sizeof(cPushConstants), &cPushConstants);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// 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[i];
|
||||
|
||||
viewports[i] = VkViewport {
|
||||
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 {
|
||||
D3D11_RECT sr = m_state.rs.scissors[i];
|
||||
|
||||
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);
|
||||
|
||||
scissors[i] = VkRect2D { srPosA, srSize };
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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(stage, slotId, cSlice);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::BindFramebuffer() {
|
||||
DxvkRenderTargets attachments;
|
||||
uint32_t sampleCount = 0;
|
||||
|
||||
// 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++) {
|
||||
if (m_state.om.renderTargetViews[i] != nullptr) {
|
||||
attachments.color[i] = {
|
||||
m_state.om.renderTargetViews[i]->GetImageView(),
|
||||
m_state.om.renderTargetViews[i]->GetRenderLayout() };
|
||||
sampleCount = m_state.om.renderTargetViews[i]->GetSampleCount();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_state.om.depthStencilView != nullptr) {
|
||||
attachments.depth = {
|
||||
m_state.om.depthStencilView->GetImageView(),
|
||||
m_state.om.depthStencilView->GetRenderLayout() };
|
||||
sampleCount = m_state.om.depthStencilView->GetSampleCount();
|
||||
}
|
||||
|
||||
// Create and bind the framebuffer object to the context
|
||||
EmitCs([
|
||||
cAttachments = std::move(attachments)
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->bindRenderTargets(cAttachments);
|
||||
});
|
||||
|
||||
// If necessary, update push constant for the sample count
|
||||
if (m_state.om.sampleCount != sampleCount) {
|
||||
m_state.om.sampleCount = sampleCount;
|
||||
ApplyRasterizerSampleCount();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::BindDrawBuffers(
|
||||
D3D11Buffer* pBufferForArgs,
|
||||
D3D11Buffer* pBufferForCount) {
|
||||
@ -820,170 +514,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::BindVertexBuffer(
|
||||
UINT Slot,
|
||||
D3D11Buffer* pBuffer,
|
||||
UINT Offset,
|
||||
UINT Stride) {
|
||||
if (likely(pBuffer != nullptr)) {
|
||||
EmitCs([
|
||||
cSlotId = Slot,
|
||||
cBufferSlice = pBuffer->GetBufferSlice(Offset),
|
||||
cStride = Stride
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->bindVertexBuffer(cSlotId, cBufferSlice, cStride);
|
||||
});
|
||||
} else {
|
||||
EmitCs([
|
||||
cSlotId = Slot
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->bindVertexBuffer(cSlotId, DxvkBufferSlice(), 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::BindIndexBuffer(
|
||||
D3D11Buffer* pBuffer,
|
||||
UINT Offset,
|
||||
DXGI_FORMAT Format) {
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void D3D11DeviceContext::BindConstantBuffer(
|
||||
UINT Slot,
|
||||
D3D11Buffer* pBuffer,
|
||||
UINT Offset,
|
||||
UINT Length) {
|
||||
EmitCs([
|
||||
cSlotId = Slot,
|
||||
cBufferSlice = pBuffer ? pBuffer->GetBufferSlice(16 * Offset, 16 * Length) : DxvkBufferSlice()
|
||||
] (DxvkContext* ctx) {
|
||||
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
|
||||
ctx->bindResourceBuffer(stage, cSlotId, cBufferSlice);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void D3D11DeviceContext::BindConstantBufferRange(
|
||||
UINT Slot,
|
||||
UINT Offset,
|
||||
UINT Length) {
|
||||
EmitCs([
|
||||
cSlotId = Slot,
|
||||
cOffset = 16 * Offset,
|
||||
cLength = 16 * Length
|
||||
] (DxvkContext* ctx) {
|
||||
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
|
||||
ctx->bindResourceBufferRange(stage, cSlotId, cOffset, cLength);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void D3D11DeviceContext::BindSampler(
|
||||
UINT Slot,
|
||||
D3D11SamplerState* pSampler) {
|
||||
EmitCs([
|
||||
cSlotId = Slot,
|
||||
cSampler = pSampler != nullptr ? pSampler->GetDXVKSampler() : nullptr
|
||||
] (DxvkContext* ctx) {
|
||||
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
|
||||
ctx->bindResourceSampler(stage, cSlotId, cSampler);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void D3D11DeviceContext::BindShaderResource(
|
||||
UINT Slot,
|
||||
D3D11ShaderResourceView* pResource) {
|
||||
EmitCs([
|
||||
cSlotId = Slot,
|
||||
cImageView = pResource != nullptr ? pResource->GetImageView() : nullptr,
|
||||
cBufferView = pResource != nullptr ? pResource->GetBufferView() : nullptr
|
||||
] (DxvkContext* ctx) {
|
||||
VkShaderStageFlagBits stage = GetShaderStage(ShaderStage);
|
||||
ctx->bindResourceView(stage, cSlotId, cImageView, cBufferView);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
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) {
|
||||
VkShaderStageFlags stages = ShaderStage == DxbcProgramType::PixelShader
|
||||
? VK_SHADER_STAGE_ALL_GRAPHICS
|
||||
: VK_SHADER_STAGE_COMPUTE_BIT;
|
||||
|
||||
if (cCounterSlice.defined() && cCounterValue != ~0u) {
|
||||
ctx->updateBuffer(
|
||||
cCounterSlice.buffer(),
|
||||
cCounterSlice.offset(),
|
||||
sizeof(uint32_t),
|
||||
&cCounterValue);
|
||||
}
|
||||
|
||||
ctx->bindResourceView (stages, cUavSlotId, cImageView, cBufferView);
|
||||
ctx->bindResourceBuffer (stages, cCtrSlotId, cCounterSlice);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void D3D11DeviceContext::SetDrawBuffers(
|
||||
ID3D11Buffer* pBufferForArgs,
|
||||
ID3D11Buffer* pBufferForCount) {
|
||||
@ -1000,112 +530,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
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<ShaderStage>(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);
|
||||
}
|
||||
|
||||
|
||||
VkClearValue D3D11DeviceContext::ConvertColorValue(
|
||||
const FLOAT Color[4],
|
||||
const DxvkFormatInfo* pFormatInfo) {
|
||||
|
@ -173,102 +173,13 @@ namespace dxvk {
|
||||
D3D11ContextState m_state;
|
||||
D3D11CmdData* m_cmdData;
|
||||
|
||||
void ApplyInputLayout();
|
||||
|
||||
void ApplyPrimitiveTopology();
|
||||
|
||||
void ApplyBlendState();
|
||||
|
||||
void ApplyBlendFactor();
|
||||
|
||||
void ApplyDepthStencilState();
|
||||
|
||||
void ApplyStencilRef();
|
||||
|
||||
void ApplyRasterizerState();
|
||||
|
||||
void ApplyRasterizerSampleCount();
|
||||
|
||||
void ApplyViewportState();
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void BindShader(
|
||||
const D3D11CommonShader* pShaderModule);
|
||||
|
||||
void BindFramebuffer();
|
||||
|
||||
void BindDrawBuffers(
|
||||
D3D11Buffer* pBufferForArgs,
|
||||
D3D11Buffer* pBufferForCount);
|
||||
|
||||
void BindVertexBuffer(
|
||||
UINT Slot,
|
||||
D3D11Buffer* pBuffer,
|
||||
UINT Offset,
|
||||
UINT Stride);
|
||||
|
||||
void BindIndexBuffer(
|
||||
D3D11Buffer* pBuffer,
|
||||
UINT Offset,
|
||||
DXGI_FORMAT Format);
|
||||
|
||||
void BindXfbBuffer(
|
||||
UINT Slot,
|
||||
D3D11Buffer* pBuffer,
|
||||
UINT Offset);
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void BindConstantBuffer(
|
||||
UINT Slot,
|
||||
D3D11Buffer* pBuffer,
|
||||
UINT Offset,
|
||||
UINT Length);
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void BindConstantBufferRange(
|
||||
UINT Slot,
|
||||
UINT Offset,
|
||||
UINT Length);
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void BindSampler(
|
||||
UINT Slot,
|
||||
D3D11SamplerState* pSampler);
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void BindShaderResource(
|
||||
UINT Slot,
|
||||
D3D11ShaderResourceView* pResource);
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void BindUnorderedAccessView(
|
||||
UINT UavSlot,
|
||||
D3D11UnorderedAccessView* pUav,
|
||||
UINT CtrSlot,
|
||||
UINT Counter);
|
||||
D3D11Buffer* pBufferForArgs,
|
||||
D3D11Buffer* pBufferForCount);
|
||||
|
||||
void SetDrawBuffers(
|
||||
ID3D11Buffer* pBufferForArgs,
|
||||
ID3D11Buffer* pBufferForCount);
|
||||
|
||||
bool TestRtvUavHazards(
|
||||
UINT NumRTVs,
|
||||
ID3D11RenderTargetView* const* ppRTVs,
|
||||
UINT NumUAVs,
|
||||
ID3D11UnorderedAccessView* const* ppUAVs);
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
bool TestSrvHazards(
|
||||
D3D11ShaderResourceView* pView);
|
||||
|
||||
template<DxbcProgramType ShaderStage, typename T>
|
||||
void ResolveSrvHazards(
|
||||
T* pView,
|
||||
D3D11ShaderResourceBindings& Bindings);
|
||||
|
||||
template<typename T>
|
||||
void ResolveCsSrvHazards(
|
||||
T* pView);
|
||||
|
||||
VkClearValue ConvertColorValue(
|
||||
const FLOAT Color[4],
|
||||
|
@ -2483,6 +2483,259 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::ApplyInputLayout() {
|
||||
auto inputLayout = m_state.ia.inputLayout.prvRef();
|
||||
|
||||
if (likely(inputLayout != nullptr)) {
|
||||
EmitCs([
|
||||
cInputLayout = std::move(inputLayout)
|
||||
] (DxvkContext* ctx) {
|
||||
cInputLayout->BindToContext(ctx);
|
||||
});
|
||||
} else {
|
||||
EmitCs([] (DxvkContext* ctx) {
|
||||
ctx->setInputLayout(0, nullptr, 0, nullptr);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::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 };
|
||||
}
|
||||
|
||||
EmitCs([iaState] (DxvkContext* ctx) {
|
||||
ctx->setInputAssemblyState(iaState);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::ApplyStencilRef() {
|
||||
EmitCs([
|
||||
cStencilRef = m_state.om.stencilRef
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->setStencilReference(cStencilRef);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::ApplyRasterizerSampleCount() {
|
||||
DxbcPushConstants pc;
|
||||
pc.rasterizerSampleCount = m_state.om.sampleCount;
|
||||
|
||||
if (unlikely(!m_state.om.sampleCount)) {
|
||||
pc.rasterizerSampleCount = m_state.rs.state->Desc()->ForcedSampleCount;
|
||||
|
||||
if (!m_state.om.sampleCount)
|
||||
pc.rasterizerSampleCount = 1;
|
||||
}
|
||||
|
||||
EmitCs([
|
||||
cPushConstants = pc
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->pushConstants(0, sizeof(cPushConstants), &cPushConstants);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
void D3D11CommonContext<ContextType>::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();
|
||||
}
|
||||
|
||||
// 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[i];
|
||||
|
||||
viewports[i] = VkViewport {
|
||||
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 {
|
||||
D3D11_RECT sr = m_state.rs.scissors[i];
|
||||
|
||||
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);
|
||||
|
||||
scissors[i] = VkRect2D { srPosA, srSize };
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ContextType>
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void D3D11CommonContext<ContextType>::BindShader(
|
||||
|
@ -620,6 +620,24 @@ namespace dxvk {
|
||||
D3D11DeviceContextExt<ContextType> m_contextExt;
|
||||
D3D11UserDefinedAnnotation<ContextType> m_annotation;
|
||||
|
||||
void ApplyInputLayout();
|
||||
|
||||
void ApplyPrimitiveTopology();
|
||||
|
||||
void ApplyBlendState();
|
||||
|
||||
void ApplyBlendFactor();
|
||||
|
||||
void ApplyDepthStencilState();
|
||||
|
||||
void ApplyStencilRef();
|
||||
|
||||
void ApplyRasterizerState();
|
||||
|
||||
void ApplyRasterizerSampleCount();
|
||||
|
||||
void ApplyViewportState();
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
void BindShader(
|
||||
const D3D11CommonShader* pShaderModule);
|
||||
|
Loading…
Reference in New Issue
Block a user