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:
parent
87e2d70448
commit
a637134c56
@ -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(
|
||||
|
@ -723,6 +723,8 @@ namespace dxvk {
|
||||
|
||||
void ApplyRasterizerState();
|
||||
|
||||
void ApplyRasterizerSampleCount();
|
||||
|
||||
void ApplyViewportState();
|
||||
|
||||
template<DxbcProgramType ShaderStage>
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -57,6 +57,10 @@ namespace dxvk {
|
||||
: VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
|
||||
UINT GetSampleCount() const {
|
||||
return UINT(m_view->imageInfo().sampleCount);
|
||||
}
|
||||
|
||||
D3D10RenderTargetView* GetD3D10Iface() {
|
||||
return &m_d3d10;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -5,6 +5,14 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Push constant struct
|
||||
*/
|
||||
struct DxbcPushConstants {
|
||||
uint32_t rasterizerSampleCount;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Binding numbers and properties
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user