fix(agc): refuse depth bounds outside [0, 1] without VK_EXT_depth_range_unrestricted
Clamping them changed the result where the stored depth is exactly 0 or 1. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c15238ddc0
commit
057bcb1b42
|
|
@ -83,6 +83,7 @@ std::shared_ptr<Pipeline> CachedPipeline(const Context& context, const State& st
|
|||
void ClearCachedPipelines(VkDevice device);
|
||||
// Device limit checks of the viewport, which is dynamic state and so no longer checked by Pipeline.
|
||||
void ValidateViewport(const Context& context, const VkViewport& viewport);
|
||||
void ValidateDepthBounds(const Context& context, const State& state);
|
||||
|
||||
void ValidateShaderPair(const ShaderRecompiler::RecompileResult& vertex, const ShaderRecompiler::RecompileResult& fragment);
|
||||
// Returns the color attachment locations the pixel shader writes.
|
||||
|
|
|
|||
|
|
@ -778,6 +778,7 @@ DrawInputs prepareDrawInputs(const Context& context, const State& state, const P
|
|||
if (state.stages.tessellation) Require(draw.indexCount % state.stages.tessellation->inputControlPoints == 0, "incomplete tessellation patch");
|
||||
// Viewport and scissor are dynamic pipeline state, so their limits are checked here per draw.
|
||||
ValidateViewport(context, state.viewport);
|
||||
ValidateDepthBounds(context, state);
|
||||
timer.phase(PhaseValidate);
|
||||
inputs.maxIndex = draw.indexed ? 0u : draw.firstVertex + draw.indexCount - 1u;
|
||||
if (draw.indexed) {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ Framebuffer::~Framebuffer() {
|
|||
if (framebuffer) context.Function<PFN_vkDestroyFramebuffer>("vkDestroyFramebuffer")(context.device, framebuffer, nullptr);
|
||||
}
|
||||
|
||||
void ValidateDepthBounds(const Context& context, const State& state) {
|
||||
Require(!state.depthBoundsTest || context.depthRangeUnrestricted || (state.minDepthBounds >= 0.0f && state.minDepthBounds <= 1.0f && state.maxDepthBounds >= 0.0f && state.maxDepthBounds <= 1.0f), "depth bounds outside [0, 1] require VK_EXT_depth_range_unrestricted");
|
||||
}
|
||||
|
||||
void ValidateViewport(const Context& context, const VkViewport& viewport) {
|
||||
Require(std::isfinite(viewport.minDepth) && std::isfinite(viewport.maxDepth), "non-finite viewport depth range");
|
||||
Require(context.depthRangeUnrestricted || (viewport.minDepth >= 0 && viewport.minDepth <= 1 && viewport.maxDepth >= 0 && viewport.maxDepth <= 1), "viewport depth outside [0, 1] requires VK_EXT_depth_range_unrestricted");
|
||||
|
|
@ -285,8 +289,7 @@ void Pipeline::Continue(VkCommandBuffer commands, const State& state) const {
|
|||
context.Resolved(&DeviceFunctions::cmdSetScissor, "vkCmdSetScissor")(commands, 0, 1, &state.scissor);
|
||||
if (depthBias) context.Resolved(&DeviceFunctions::cmdSetDepthBias, "vkCmdSetDepthBias")(commands, state.depthBiasConstant, state.depthBiasClamp, state.depthBiasSlope);
|
||||
if (!depthBounds) return;
|
||||
const auto bound = [&](float value) { return context.depthRangeUnrestricted ? value : std::clamp(value, 0.0f, 1.0f); };
|
||||
context.Resolved(&DeviceFunctions::cmdSetDepthBounds, "vkCmdSetDepthBounds")(commands, bound(state.minDepthBounds), bound(state.maxDepthBounds));
|
||||
context.Resolved(&DeviceFunctions::cmdSetDepthBounds, "vkCmdSetDepthBounds")(commands, state.minDepthBounds, state.maxDepthBounds);
|
||||
}
|
||||
|
||||
void Pipeline::PushConstants(VkCommandBuffer commands, VkShaderStageFlags stages, std::span<const std::byte, PipelinePushConstantBytes> bytes) const {
|
||||
|
|
|
|||
|
|
@ -1702,6 +1702,15 @@ int main() {
|
|||
draw.indexAddress = 0;
|
||||
draw.flags = 1;
|
||||
expectFailure([&] { AgcDriver::Graphics::Draw(context, state, draw, {}); }, "draw modifiers");
|
||||
auto bounded = state;
|
||||
bounded.depthBoundsTest = true;
|
||||
bounded.minDepthBounds = 0.25f;
|
||||
AgcDriver::Graphics::ValidateDepthBounds(context, bounded);
|
||||
bounded.minDepthBounds = 1.5f;
|
||||
expectFailure([&] { AgcDriver::Graphics::ValidateDepthBounds(context, bounded); }, "depth bounds outside [0, 1]");
|
||||
auto unrestricted = context;
|
||||
unrestricted.depthRangeUnrestricted = true;
|
||||
AgcDriver::Graphics::ValidateDepthBounds(unrestricted, bounded);
|
||||
}
|
||||
stateTests();
|
||||
hardwareScreenOffsetTests();
|
||||
|
|
|
|||
Loading…
Reference in New Issue