fix(agc): support unrestricted vulkan depth range
This commit is contained in:
parent
f0b13b6652
commit
9c78d10044
|
|
@ -57,6 +57,7 @@ struct VulkanDevice::State {
|
|||
bool tessellationShader = false;
|
||||
bool meshShader = false;
|
||||
bool depthClipControl = false;
|
||||
bool depthRangeUnrestricted = false;
|
||||
VkPhysicalDeviceMeshShaderPropertiesEXT meshLimits{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT};
|
||||
|
||||
template<typename TFunction>
|
||||
|
|
@ -277,6 +278,8 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window) : state(std::make_u
|
|||
meshFeatures.meshShader = state->meshShader;
|
||||
std::vector<const char*> deviceExtensions;
|
||||
if (window != nullptr) deviceExtensions.assign(presentationExtensions.begin(), presentationExtensions.end());
|
||||
state->depthRangeUnrestricted = hasExtension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
|
||||
if (state->depthRangeUnrestricted) deviceExtensions.push_back(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
|
||||
VkPhysicalDeviceDepthClipControlFeaturesEXT depthClipFeatures{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT};
|
||||
if (hasExtension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME)) {
|
||||
VkPhysicalDeviceFeatures2 features{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &depthClipFeatures};
|
||||
|
|
@ -538,7 +541,8 @@ void VulkanDevice::DrawIndexed(const Graphics::State& graphics, const Pm4::Index
|
|||
state->tessellationShader,
|
||||
state->meshShader,
|
||||
state->meshLimits,
|
||||
state->depthClipControl
|
||||
state->depthClipControl,
|
||||
state->depthRangeUnrestricted
|
||||
};
|
||||
Graphics::DrawIndexed(context, graphics, draw, shaders);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ struct Context {
|
|||
bool meshShader = false;
|
||||
VkPhysicalDeviceMeshShaderPropertiesEXT meshLimits{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT};
|
||||
bool depthClipControl = false;
|
||||
bool depthRangeUnrestricted = false;
|
||||
|
||||
template<typename TFunction>
|
||||
TFunction Function(const char* name) const {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ Pipeline::Pipeline(const Context& context, const State& state, const RenderTarge
|
|||
Require(mesh.maxVertices <= context.meshLimits.maxMeshOutputVertices && mesh.maxPrimitives <= context.meshLimits.maxMeshOutputPrimitives && static_cast<std::uint64_t>(mesh.ldsSizeDwords) * 4 <= context.meshLimits.maxMeshSharedMemorySize, "mesh output or LDS exceeds device limits");
|
||||
}
|
||||
const auto& viewport = state.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");
|
||||
Require(std::isfinite(viewport.x) && std::isfinite(viewport.y) && std::isfinite(viewport.width) && std::isfinite(viewport.height), "viewport arithmetic overflow");
|
||||
Require(viewport.width <= context.limits.maxViewportDimensions[0] && std::abs(viewport.height) <= context.limits.maxViewportDimensions[1], "viewport dimensions exceed device limits");
|
||||
Require(viewport.x >= context.limits.viewportBoundsRange[0] && viewport.x + viewport.width <= context.limits.viewportBoundsRange[1], "viewport X exceeds device bounds");
|
||||
|
|
|
|||
|
|
@ -218,12 +218,12 @@ State DecodeState(const QueueState& queue) {
|
|||
const auto zo = readFloat(cx, 0x114);
|
||||
const auto minDepth = result.negativeOneToOne ? zo - zs : zo;
|
||||
const auto maxDepth = zo + zs;
|
||||
if (!(xs > 0 && ys != 0 && minDepth >= 0 && minDepth <= 1 && maxDepth >= 0 && maxDepth <= 1)) {
|
||||
if (!(xs > 0 && ys != 0 && std::isfinite(minDepth) && std::isfinite(maxDepth))) {
|
||||
std::ostringstream message;
|
||||
message << "AGC graphics: unsupported viewport transform: scale=(" << xs << ", " << ys << ", " << zs << "), offset=(" << xo << ", " << yo << ", " << zo << "), depth=(" << minDepth << ", " << maxDepth << "), negativeOneToOne=" << result.negativeOneToOne;
|
||||
throw std::runtime_error(message.str());
|
||||
}
|
||||
Require(readFloat(cx, 0xb4) == std::min(minDepth, maxDepth) && readFloat(cx, 0xb5) == std::max(minDepth, maxDepth), "viewport depth clamp differs from transform");
|
||||
Require(readFloat(cx, 0xb4) <= readFloat(cx, 0xb5), "inverted viewport depth clamp bounds");
|
||||
result.viewport = {xo - xs, yo - ys, 2 * xs, 2 * ys, minDepth, maxDepth};
|
||||
result.scissor = {{0, 0}, result.renderExtent};
|
||||
intersect(result.scissor, cx, 0xc, true);
|
||||
|
|
|
|||
|
|
@ -192,10 +192,19 @@ void DepthClipTests() {
|
|||
const auto reversed = AgcDriver::Graphics::DecodeState(queue);
|
||||
Require(reversed.viewport.minDepth == 1 && reversed.viewport.maxDepth == 0, "reversed depth transform is incorrect");
|
||||
queue.context[0x113] = std::bit_cast<std::uint32_t>(1.0f);
|
||||
queue.context[0x114] = 0;
|
||||
const auto unrestricted = AgcDriver::Graphics::DecodeState(queue);
|
||||
Require(unrestricted.viewport.minDepth == -1 && unrestricted.viewport.maxDepth == 1, "unrestricted viewport depth was normalized");
|
||||
queue.context[0x113] = std::bit_cast<std::uint32_t>(-1.0f);
|
||||
const auto unrestrictedReversed = AgcDriver::Graphics::DecodeState(queue);
|
||||
Require(unrestrictedReversed.viewport.minDepth == 1 && unrestrictedReversed.viewport.maxDepth == -1, "reversed unrestricted viewport depth changed");
|
||||
queue.context[0x113] = 0x7f7fffff;
|
||||
queue.context[0x114] = 0x7f7fffff;
|
||||
expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "unsupported viewport transform");
|
||||
queue.context[0x114] = std::bit_cast<std::uint32_t>(0.5f);
|
||||
queue.context[0x113] = std::bit_cast<std::uint32_t>(0.5f);
|
||||
queue.context[0xb4] = std::bit_cast<std::uint32_t>(0.25f);
|
||||
expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "viewport depth clamp differs");
|
||||
queue.context[0xb4] = std::bit_cast<std::uint32_t>(2.0f);
|
||||
expectFailure([&] { AgcDriver::Graphics::DecodeState(queue); }, "inverted viewport depth clamp");
|
||||
queue.context[0xb4] = 0;
|
||||
for (std::uint32_t bit = 0; bit < 32; ++bit) {
|
||||
if (bit == 19) continue;
|
||||
|
|
|
|||
Loading…
Reference in New Issue