Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to round depth values when using a depth format fallback #2679

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions dxvk.conf
Original file line number Diff line number Diff line change
Expand Up @@ -557,3 +557,10 @@
# - True/False

# dxvk.enableDebugUtils = False

# Depth rounding
#
# Enables rounding depth values when using a fallback depth format.
# (D24->D32 or D16->D24/D32)

# d3d9.roundDepth = False
8 changes: 8 additions & 0 deletions src/d3d9/d3d9_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ namespace dxvk {
return m_d3d9Formats.GetUnsupportedFormatInfo(Format);
}

bool SupportsD24S8() const {
return m_d3d9Formats.SupportsD24S8();
}

bool SupportsD16S8() const {
return m_d3d9Formats.SupportsD16S8();
}

private:

HRESULT CheckDeviceVkFormat(
Expand Down
16 changes: 16 additions & 0 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5593,6 +5593,22 @@ namespace dxvk {
}
}

if (unlikely(m_d3d9Options.roundDepth && m_state.depthStencil != nullptr)) {
D3D9Format format = m_state.depthStencil->GetCommonTexture()->Desc()->Format;
uint32_t depthRoundingValue = 0;
D3D9_VK_FORMAT_MAPPING fmtMapping = ConvertFormatUnfixed(format);
if (fmtMapping.FormatColor == VK_FORMAT_D24_UNORM_S8_UINT && !m_adapter->SupportsD24S8()) {
depthRoundingValue = 1;
}
if (fmtMapping.FormatColor == VK_FORMAT_D16_UNORM_S8_UINT && !m_adapter->SupportsD16S8()) {
depthRoundingValue = 2;
}

EmitCs([cDepthRoundingValue = depthRoundingValue] (DxvkContext* ctx) {
ctx->setSpecConstant(VK_PIPELINE_BIND_POINT_GRAPHICS, D3D9SpecConstantId::DepthFormatRounding, cDepthRoundingValue);
});
}

// Create and bind the framebuffer object to the context
EmitCs([
cAttachments = std::move(attachments)
Expand Down
8 changes: 8 additions & 0 deletions src/d3d9/d3d9_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ namespace dxvk {
const DxvkFormatInfo* GetUnsupportedFormatInfo(
D3D9Format Format) const;

bool SupportsD24S8() const {
return m_d24s8Support;
}

bool SupportsD16S8() const {
return m_d16s8Support;
}

private:

bool CheckImageFormatSupport(
Expand Down
1 change: 1 addition & 0 deletions src/d3d9/d3d9_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ namespace dxvk {
this->apitraceMode = config.getOption<bool> ("d3d9.apitraceMode", false);
this->deviceLocalConstantBuffers = config.getOption<bool> ("d3d9.deviceLocalConstantBuffers", false);
this->allowDirectBufferMapping = config.getOption<bool> ("d3d9.allowDirectBufferMapping", true);
this->roundDepth = config.getOption<bool> ("d3d9.roundDepth", false);

// If we are not Nvidia, enable general hazards.
this->generalHazards = adapter != nullptr
Expand Down
3 changes: 3 additions & 0 deletions src/d3d9/d3d9_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ namespace dxvk {

/// Disable direct buffer mapping
bool allowDirectBufferMapping;

/// Should we round depth when using the D24->D32 or D16->D24/D32 workaround
bool roundDepth;
};

}
2 changes: 2 additions & 0 deletions src/d3d9/d3d9_spec_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ namespace dxvk {
Fetch4 = 9,

SamplerDepthMode = 10,

DepthFormatRounding = 11,
};

}
52 changes: 52 additions & 0 deletions src/dxso/dxso_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3996,6 +3996,58 @@ void DxsoCompiler::emitControlFlowGenericLoop(

this->emitPsProcessing();
this->emitOutputDepthClamp();

if (m_moduleInfo.options.roundDepth) {
const uint32_t boolType = m_module.defBoolType();
const uint32_t floatType = m_module.defFloatType(32);
const uint32_t roundLabel = m_module.allocateId();
const uint32_t dontRoundLabel = m_module.allocateId();
const uint32_t endLabel = m_module.allocateId();

uint32_t depthRoundingSpecConst = m_module.specConst32(m_module.defIntType(32, 0), 0);
m_module.decorateSpecId(depthRoundingSpecConst, getSpecId(D3D9SpecConstantId::DepthFormatRounding));
m_module.setDebugName(depthRoundingSpecConst, "s_depth_rounding");

uint32_t originalDepthId;
if (m_ps.oDepth.id == 0) {
DxsoRegisterPointer fragCoordPtr = this->emitRegisterPtr(
"ps_depth_rounding_frag_coord", DxsoScalarType::Float32, 4, 0,
spv::StorageClassInput, spv::BuiltInFragCoord);
DxsoRegisterValue fragCoordId = this->emitValueLoad(fragCoordPtr);
uint32_t index = 2;
originalDepthId = m_module.opCompositeExtract(floatType, fragCoordId.id, 1, &index);
} else {
originalDepthId = emitValueLoad(m_ps.oDepth).id;
}

DxsoRegister fragDepthReg;
fragDepthReg.id.type = DxsoRegisterType::DepthOut;
DxsoRegisterPointer depthOutPtr = emitGetOperandPtr(fragDepthReg);

const uint32_t noRoundingConstValueId = m_module.constu32(0);
const uint32_t roundCondition = m_module.opINotEqual(boolType, depthRoundingSpecConst, noRoundingConstValueId);
m_module.opSelectionMerge(endLabel, spv::SelectionControlMaskNone);
m_module.opBranchConditional(roundCondition, roundLabel, dontRoundLabel);

m_module.opLabel(roundLabel);
const uint32_t depthBase24Id = m_module.constf32(16777216 - 1); // 2^24 - 1
const uint32_t depthBase16Id = m_module.constf32(65535 - 1); // 2^16 - 1
const uint32_t depth24SpecConstValueId = m_module.constu32(1);
uint32_t depthBaseCondition = m_module.opIEqual(boolType, depthRoundingSpecConst, depth24SpecConstValueId);
const uint32_t depthBaseId = m_module.opSelect(floatType, depthBaseCondition, depthBase24Id, depthBase16Id);
uint32_t depthId = m_module.opFMul(floatType, originalDepthId, depthBaseId);
depthId = m_module.opRound(floatType, depthId);
depthId = m_module.opFDiv(floatType, depthId, depthBaseId);
m_module.opStore(depthOutPtr.id, depthId);
m_module.opBranch(endLabel);

m_module.opLabel(dontRoundLabel);
m_module.opStore(depthOutPtr.id, originalDepthId);
m_module.opBranch(endLabel);

m_module.opLabel(endLabel);
}

this->emitFunctionEnd();
}

Expand Down
2 changes: 2 additions & 0 deletions src/dxso/dxso_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ namespace dxvk {
alphaTestWiggleRoom = options.alphaTestWiggleRoom;

robustness2Supported = devFeatures.extRobustness2.robustBufferAccess2;

roundDepth = options.roundDepth;
}

}
3 changes: 3 additions & 0 deletions src/dxso/dxso_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ namespace dxvk {

/// Whether or not we can rely on robustness2 to handle oob constant access
bool robustness2Supported;

/// Should we round depth when using the D24->D32 or D16->D24/D32 workaround
bool roundDepth;
};

}
13 changes: 13 additions & 0 deletions src/util/config/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,19 @@ namespace dxvk {
{ R"(\\eoa\.exe$)", {{
{ "d3d9.customVendorId", "10de" },
}} },
/* Assassin's Creed Brotherhood has shadow acne issues
with the D24->D32 workaround. */
{ R"(\\(ACBSP|ACBMP)\.exe$)", {{
{ "d3d9.roundDepth", "true" },
}} },
/* SimCity has shadow issues with the D24->D32 workaround. */
{ R"(\\SimCity\.exe$)", {{
{ "d3d9.roundDepth", "true" },
}} },
/* The Saboteur has shadow issues with the D24->D32 workaround. */
{ R"(\\Saboteur\.exe$)", {{
{ "d3d9.roundDepth", "true" },
}} },
}};


Expand Down