Implement depthBoundsTest

The depthBoundsTest checks if the depth is withing a certain range, and if not, sets coverage to 0 for the particular fragment. Tests: dEQP-VK.pipeline.depth.nocolor.format.d16_unorm.compare_ops.* Tests: dEQP-VK.pipeline.depth.nocolor.format.d32_sfloat.compare_ops.* Tests: dEQP-VK.pipeline.depth.nocolor.format.d32_sfloat_s8_uint.compare_ops.* Tests: dEQP-VK.pipeline.depth.nocolor.format.d32_sfloat_s8_uint_separate_layouts.compare_ops.* Tests: dEQP-VK.dynamic_state.ds_state.depth_bounds_1 Tests: dEQP-VK.dynamic_state.ds_state.depth_bounds_2 Tests: dEQP-VK.rasterization.frag_side_effects.color_at_end.depth_bounds Tests: dEQP-VK.rasterization.frag_side_effects.color_at_beginning.depth_bounds Bug: b/181656417 Change-Id: I50076834afa21f5b93e59b27a5438ba26f8008c8 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/53888 Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarSean Risser <srisser@google.com> Commit-Queue: Sean Risser <srisser@google.com>
parent 45be1bc3
......@@ -457,12 +457,10 @@ GraphicsState::GraphicsState(const Device *device, const VkGraphicsPipelineCreat
UNSUPPORTED("pCreateInfo->pDepthStencilState->flags %d", int(pCreateInfo->pDepthStencilState->flags));
}
if(depthStencilState->depthBoundsTestEnable != VK_FALSE)
{
UNSUPPORTED("VkPhysicalDeviceFeatures::depthBounds");
}
depthBoundsTestEnable = (depthStencilState->depthBoundsTestEnable != VK_FALSE);
minDepthBounds = depthStencilState->minDepthBounds;
maxDepthBounds = depthStencilState->maxDepthBounds;
depthBufferEnable = (depthStencilState->depthTestEnable != VK_FALSE);
depthWriteEnable = (depthStencilState->depthWriteEnable != VK_FALSE);
depthCompareMode = depthStencilState->depthCompareOp;
......@@ -593,6 +591,11 @@ bool GraphicsState::stencilActive(const Attachments &attachments) const
return attachments.stencilBuffer && stencilEnable;
}
bool GraphicsState::depthBoundsTestActive() const
{
return depthBoundsTestEnable;
}
const GraphicsState GraphicsState::combineStates(const DynamicState &dynamicState) const
{
GraphicsState combinedState = *this;
......@@ -627,7 +630,8 @@ const GraphicsState GraphicsState::combineStates(const DynamicState &dynamicStat
ASSERT(dynamicState.minDepthBounds >= 0.0f && dynamicState.minDepthBounds <= 1.0f);
ASSERT(dynamicState.maxDepthBounds >= 0.0f && dynamicState.maxDepthBounds <= 1.0f);
UNSUPPORTED("VkPhysicalDeviceFeatures::depthBounds");
combinedState.minDepthBounds = dynamicState.minDepthBounds;
combinedState.maxDepthBounds = dynamicState.maxDepthBounds;
}
if(hasDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK) && stencilEnable)
......
......@@ -155,6 +155,8 @@ struct GraphicsState
inline float getConstantDepthBias() const { return constantDepthBias; }
inline float getSlopeDepthBias() const { return slopeDepthBias; }
inline float getDepthBiasClamp() const { return depthBiasClamp; }
inline float getMinDepthBounds() const { return minDepthBounds; }
inline float getMaxDepthBounds() const { return maxDepthBounds; }
inline bool hasDepthRangeUnrestricted() const { return depthRangeUnrestricted; }
// Pixel processor states
......@@ -184,6 +186,7 @@ struct GraphicsState
bool depthWriteActive(const Attachments &attachments) const;
bool depthBufferActive(const Attachments &attachments) const;
bool stencilActive(const Attachments &attachments) const;
bool depthBoundsTestActive() const;
private:
inline bool hasDynamicState(VkDynamicState dynamicState) const { return (dynamicStateFlags & (1 << dynamicState)) != 0; }
......@@ -219,6 +222,8 @@ private:
float constantDepthBias;
float slopeDepthBias;
float depthBiasClamp;
float minDepthBounds;
float maxDepthBounds;
bool depthRangeUnrestricted;
// Pixel processor states
......
......@@ -123,6 +123,10 @@ const PixelProcessor::State PixelProcessor::update(const vk::GraphicsState &pipe
state.depthClamp = !state.depthFormat.isFloatFormat() || !pipelineState.hasDepthRangeUnrestricted();
}
state.depthBoundsTestActive = pipelineState.depthBoundsTestActive();
state.minDepthBounds = pipelineState.getMinDepthBounds();
state.maxDepthBounds = pipelineState.getMaxDepthBounds();
state.occlusionEnabled = occlusionEnabled;
bool fragmentContainsKill = (fragmentShader && fragmentShader->getModes().ContainsKill);
......
......@@ -77,6 +77,7 @@ public:
StencilOpState backStencil;
bool depthTestActive;
bool depthBoundsTestActive;
bool occlusionEnabled;
bool perspective;
......@@ -91,6 +92,8 @@ public:
bool centroid;
bool sampleShadingEnabled;
float minSampleShading;
float minDepthBounds;
float maxDepthBounds;
VkFrontFace frontFace;
vk::Format depthFormat;
bool depthBias;
......
......@@ -83,7 +83,7 @@ void QuadRasterizer::rasterize(Int &yMin, Int &yMax)
}
}
if(state.depthTestActive)
if(state.depthTestActive || state.depthBoundsTestActive)
{
zBuffer = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, depthBuffer)) + yMin * *Pointer<Int>(data + OFFSET(DrawData, depthPitchB));
}
......@@ -216,7 +216,7 @@ void QuadRasterizer::rasterize(Int &yMin, Int &yMax)
}
}
if(state.depthTestActive)
if(state.depthTestActive || state.depthBoundsTestActive)
{
zBuffer += *Pointer<Int>(data + OFFSET(DrawData, depthPitchB)) << (1 + clusterCountLog2); // FIXME: Precompute
}
......
......@@ -141,6 +141,7 @@ void PixelRoutine::quad(Pointer<Byte> cBuffer[RENDERTARGETS], Pointer<Byte> &zBu
for(unsigned int q = sampleLoopInit; q < sampleLoopEnd; q++)
{
depthPass = depthPass || depthTest(zBuffer, q, x, z[q], sMask[q], zMask[q], cMask[q]);
depthBoundsTest(zBuffer, q, x, zMask[q], cMask[q]);
}
}
......@@ -307,6 +308,7 @@ void PixelRoutine::quad(Pointer<Byte> cBuffer[RENDERTARGETS], Pointer<Byte> &zBu
for(unsigned int q = sampleLoopInit; q < sampleLoopEnd; q++)
{
depthPass = depthPass || depthTest(zBuffer, q, x, z[q], sMask[q], zMask[q], cMask[q]);
depthBoundsTest(zBuffer, q, x, zMask[q], cMask[q]);
}
}
......@@ -604,6 +606,58 @@ Bool PixelRoutine::depthTest(const Pointer<Byte> &zBuffer, int q, const Int &x,
}
}
Int4 PixelRoutine::depthBoundsTest16(const Pointer<Byte> &zBuffer, int q, const Int &x)
{
Pointer<Byte> buffer = zBuffer + 2 * x;
Int pitch = *Pointer<Int>(data + OFFSET(DrawData, depthPitchB));
if(q > 0)
{
buffer += q * *Pointer<Int>(data + OFFSET(DrawData, depthSliceB));
}
Float4 minDepthBound(state.minDepthBounds);
Float4 maxDepthBound(state.maxDepthBounds);
Int2 z;
z = Insert(z, *Pointer<Int>(buffer), 0);
z = Insert(z, *Pointer<Int>(buffer + pitch), 1);
Float4 zValue = convertFloat32(As<UShort4>(z));
return Int4(CmpLE(minDepthBound, zValue) & CmpLE(zValue, maxDepthBound));
}
Int4 PixelRoutine::depthBoundsTest32F(const Pointer<Byte> &zBuffer, int q, const Int &x)
{
Pointer<Byte> buffer = zBuffer + 4 * x;
Int pitch = *Pointer<Int>(data + OFFSET(DrawData, depthPitchB));
if(q > 0)
{
buffer += q * *Pointer<Int>(data + OFFSET(DrawData, depthSliceB));
}
Float4 zValue = Float4(*Pointer<Float2>(buffer), *Pointer<Float2>(buffer + pitch));
return Int4(CmpLE(Float4(state.minDepthBounds), zValue) & CmpLE(zValue, Float4(state.maxDepthBounds)));
}
void PixelRoutine::depthBoundsTest(const Pointer<Byte> &zBuffer, int q, const Int &x, Int &zMask, Int &cMask)
{
if(state.depthBoundsTestActive)
{
Int4 zTest = (state.depthFormat == VK_FORMAT_D16_UNORM) ? depthBoundsTest16(zBuffer, q, x) : depthBoundsTest32F(zBuffer, q, x);
if(!state.depthTestActive)
{
cMask &= zMask & SignMask(zTest);
}
else
{
zMask &= cMask & SignMask(zTest);
}
}
}
void PixelRoutine::alphaToCoverage(Int cMask[4], const Float4 &alpha, int sampleId)
{
static const int a2c[4] = {
......@@ -2788,6 +2842,11 @@ UShort4 PixelRoutine::convertFixed16(const Float4 &cf, bool saturate)
return UShort4(cf * Float4(0xFFFF), saturate);
}
Float4 PixelRoutine::convertFloat32(const UShort4 &cf)
{
return Float4(cf) * Float4(1.0f / 65535.0f);
}
void PixelRoutine::sRGBtoLinear16_12_16(Vector4s &c)
{
Pointer<Byte> LUT = constants + OFFSET(Constants, sRGBtoLinear12_16);
......
......@@ -63,6 +63,7 @@ protected:
bool isSRGB(int index) const;
UShort4 convertFixed16(const Float4 &cf, bool saturate = true);
Float4 convertFloat32(const UShort4 &cf);
void linearToSRGB12_16(Vector4s &c);
private:
......@@ -72,6 +73,7 @@ private:
void stencilOperation(Byte8 &newValue, const Byte8 &bufferValue, const PixelProcessor::States::StencilOpState &ops, bool isBack, const Int &zMask, const Int &sMask);
void stencilOperation(Byte8 &output, const Byte8 &bufferValue, VkStencilOp operation, bool isBack);
Bool depthTest(const Pointer<Byte> &zBuffer, int q, const Int &x, const Float4 &z, const Int &sMask, Int &zMask, const Int &cMask);
void depthBoundsTest(const Pointer<Byte> &zBuffer, int q, const Int &x, Int &zMask, Int &cMask);
// Raster operations
void blendFactor(Vector4s &blendFactor, const Vector4s &current, const Vector4s &pixel, VkBlendFactor blendFactorActive);
......@@ -91,6 +93,9 @@ private:
void writeDepth32F(Pointer<Byte> &zBuffer, int q, const Int &x, const Float4 &z, const Int &zMask);
void writeDepth16(Pointer<Byte> &zBuffer, int q, const Int &x, const Float4 &z, const Int &zMask);
Int4 depthBoundsTest32F(const Pointer<Byte> &zBuffer, int q, const Int &x);
Int4 depthBoundsTest16(const Pointer<Byte> &zBuffer, int q, const Int &x);
};
} // namespace sw
......
......@@ -62,6 +62,7 @@ namespace sw
bool stencilWriteMaskedCCW : 1;
bool depthTestActive : 1;
bool depthBoundsTestActive : 1;
bool fogActive : 1;
FogMode pixelFogMode : BITS(FOG_LAST);
bool specularAdd : 1;
......
......@@ -49,7 +49,7 @@ const VkPhysicalDeviceFeatures &PhysicalDevice::getFeatures() const
VK_FALSE, // depthClamp
VK_TRUE, // depthBiasClamp
VK_TRUE, // fillModeNonSolid
VK_FALSE, // depthBounds
VK_TRUE, // depthBounds
VK_FALSE, // wideLines
VK_TRUE, // largePoints
VK_FALSE, // alphaToOne
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment