1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-05 01:24:14 +01:00

[d3d11,dxbc] Use push constant instead of spec constant for rasterizer sample count

This commit is contained in:
Philip Rebohle 2022-06-30 19:26:26 +02:00
parent 87e2d70448
commit a637134c56
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
8 changed files with 105 additions and 27 deletions

View File

@ -9,7 +9,7 @@
#include "../dxbc/dxbc_util.h"
namespace dxvk {
D3D11DeviceContext::D3D11DeviceContext(
D3D11Device* pParent,
const Rc<DxvkDevice>& Device,
@ -230,6 +230,7 @@ namespace dxvk {
for (uint32_t i = 0; i < 4; i++)
m_state.om.blendFactor[i] = 1.0f;
m_state.om.sampleCount = 0;
m_state.om.sampleMask = D3D11_DEFAULT_SAMPLE_MASK;
m_state.om.stencilRef = D3D11_DEFAULT_STENCIL_REFERENCE;
@ -2606,24 +2607,25 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11DeviceContext::RSSetState(ID3D11RasterizerState* pRasterizerState) {
D3D10DeviceLock lock = LockContext();
auto rasterizerState = static_cast<D3D11RasterizerState*>(pRasterizerState);
auto currRasterizerState = m_state.rs.state;
auto nextRasterizerState = static_cast<D3D11RasterizerState*>(pRasterizerState);
bool currScissorEnable = m_state.rs.state != nullptr
? m_state.rs.state->Desc()->ScissorEnable
: false;
bool nextScissorEnable = rasterizerState != nullptr
? rasterizerState->Desc()->ScissorEnable
: false;
if (m_state.rs.state != rasterizerState) {
m_state.rs.state = rasterizerState;
// In D3D11, the rasterizer state defines whether the
// scissor test is enabled, so we have to update the
// scissor rectangles as well.
if (m_state.rs.state != nextRasterizerState) {
m_state.rs.state = nextRasterizerState;
ApplyRasterizerState();
// If necessary, update the rasterizer sample count push constant
uint32_t currSampleCount = currRasterizerState != nullptr ? currRasterizerState->Desc()->ForcedSampleCount : 0;
uint32_t nextSampleCount = nextRasterizerState != nullptr ? nextRasterizerState->Desc()->ForcedSampleCount : 0;
if (currSampleCount != nextSampleCount)
ApplyRasterizerSampleCount();
// In D3D11, the rasterizer state defines whether the scissor test is
// enabled, so if that changes, we need to update scissor rects as well.
bool currScissorEnable = currRasterizerState != nullptr ? currRasterizerState->Desc()->ScissorEnable : false;
bool nextScissorEnable = nextRasterizerState != nullptr ? nextRasterizerState->Desc()->ScissorEnable : false;
if (currScissorEnable != nextScissorEnable)
ApplyViewportState();
}
@ -3025,6 +3027,25 @@ namespace dxvk {
}
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;
@ -3143,7 +3164,8 @@ namespace dxvk {
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.
@ -3152,6 +3174,7 @@ namespace dxvk {
attachments.color[i] = {
m_state.om.renderTargetViews[i]->GetImageView(),
m_state.om.renderTargetViews[i]->GetRenderLayout() };
sampleCount = m_state.om.renderTargetViews[i]->GetSampleCount();
}
}
@ -3159,6 +3182,7 @@ namespace dxvk {
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
@ -3167,6 +3191,12 @@ namespace dxvk {
] (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();
}
}
@ -4149,6 +4179,11 @@ namespace dxvk {
}
}
}
// Initialize push constants
DxbcPushConstants pc;
pc.rasterizerSampleCount = 1;
ctx->pushConstants(0, sizeof(pc), &pc);
});
}
@ -4170,6 +4205,7 @@ namespace dxvk {
ApplyDepthStencilState();
ApplyStencilRef();
ApplyRasterizerState();
ApplyRasterizerSampleCount();
ApplyViewportState();
BindDrawBuffers(

View File

@ -723,6 +723,8 @@ namespace dxvk {
void ApplyRasterizerState();
void ApplyRasterizerSampleCount();
void ApplyViewportState();
template<DxbcProgramType ShaderStage>

View File

@ -129,6 +129,8 @@ namespace dxvk {
D3D11DepthStencilState* dsState = nullptr;
FLOAT blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
UINT sampleCount = 0u;
UINT sampleMask = 0xFFFFFFFFu;
UINT stencilRef = 0u;

View File

@ -66,6 +66,10 @@ namespace dxvk {
}
}
UINT GetSampleCount() const {
return UINT(m_view->imageInfo().sampleCount);
}
VkImageAspectFlags GetWritableAspectMask() const {
VkImageAspectFlags mask = m_view->formatInfo()->aspectMask;
if (m_desc.Flags & D3D11_DSV_READ_ONLY_DEPTH) mask &= ~VK_IMAGE_ASPECT_DEPTH_BIT;

View File

@ -57,6 +57,10 @@ namespace dxvk {
: VK_IMAGE_LAYOUT_GENERAL;
}
UINT GetSampleCount() const {
return UINT(m_view->imageInfo().sampleCount);
}
D3D10RenderTargetView* GetD3D10Iface() {
return &m_d3d10;
}

View File

@ -258,6 +258,9 @@ namespace dxvk {
info.uniformSize = m_immConstData.size();
info.uniformData = m_immConstData.data();
if (m_programInfo.type() == DxbcProgramType::PixelShader && m_ps.pushConstantId)
info.pushConstSize = sizeof(DxbcPushConstants);
if (m_moduleInfo.xfb) {
info.xfbRasterizedStream = m_moduleInfo.xfb->rasterizedStream;
@ -5309,19 +5312,20 @@ namespace dxvk {
DxbcRegisterValue DxbcCompiler::emitQueryTextureSamples(
const DxbcRegister& resource) {
if (resource.type == DxbcOperandType::Rasterizer) {
// SPIR-V has no gl_NumSamples equivalent, so we have
// to work around it using a specialization constant
if (!m_ps.specRsSampleCount) {
m_ps.specRsSampleCount = emitNewSpecConstant(
DxvkSpecConstantId::RasterizerSampleCount,
DxbcScalarType::Uint32, 1,
"RasterizerSampleCount");
}
// SPIR-V has no gl_NumSamples equivalent, so we
// have to work around it using a push constant
if (!m_ps.pushConstantId)
m_ps.pushConstantId = emitPushConstants();
uint32_t uintTypeId = m_module.defIntType(32, 0);
uint32_t ptrTypeId = m_module.defPointerType(uintTypeId, spv::StorageClassPushConstant);
uint32_t index = m_module.constu32(0);
DxbcRegisterValue result;
result.type.ctype = DxbcScalarType::Uint32;
result.type.ccount = 1;
result.id = m_ps.specRsSampleCount;
result.id = m_module.opLoad(uintTypeId,
m_module.opAccessChain(ptrTypeId, m_ps.pushConstantId, 1, &index));
return result;
} else {
DxbcBufferInfo info = getBufferInfo(resource);
@ -7532,6 +7536,22 @@ namespace dxvk {
}
uint32_t DxbcCompiler::emitPushConstants() {
uint32_t uintTypeId = m_module.defIntType(32, 0);
uint32_t structTypeId = m_module.defStructTypeUnique(1, &uintTypeId);
m_module.setDebugName(structTypeId, "pc_t");
m_module.setDebugMemberName(structTypeId, 0, "RasterizerSampleCount");
m_module.memberDecorateOffset(structTypeId, 0, 0);
uint32_t ptrTypeId = m_module.defPointerType(structTypeId, spv::StorageClassPushConstant);
uint32_t varId = m_module.newVar(ptrTypeId, spv::StorageClassPushConstant);
m_module.setDebugName(varId, "pc");
return varId;
}
void DxbcCompiler::enableShaderViewportIndexLayer() {
if (!m_extensions.shaderViewportIndexLayer) {
m_extensions.shaderViewportIndexLayer = true;

View File

@ -184,7 +184,7 @@ namespace dxvk {
uint32_t builtinLaneId = 0;
uint32_t killState = 0;
uint32_t specRsSampleCount = 0;
uint32_t pushConstantId = 0;
};
@ -1198,6 +1198,8 @@ namespace dxvk {
uint32_t emitBuiltinTessLevelInner(
spv::StorageClass storageClass);
uint32_t emitPushConstants();
////////////////////////////////
// Extension enablement methods
void enableShaderViewportIndexLayer();

View File

@ -5,6 +5,14 @@
namespace dxvk {
/**
* \brief Push constant struct
*/
struct DxbcPushConstants {
uint32_t rasterizerSampleCount;
};
/**
* \brief Binding numbers and properties
*/