← 输入框|github.com|刷新
Skip to content

Viewport rect must lie entirely within the current attachment size? #373

Closed

Description

@Richard-Yunchao

Metal documentation says that "The x/y rectangle of the viewport must lie entirely within the current attachment size". See https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515527-setviewport?language=objc.

The current setViewport API in WebGPU doesn't require this. The viewport rect can be bigger than the current attachment size, or it can be set to somewhere outside of the attachment size.

When I implement this API in Dawn project, I obey the WebGPU's rule and break Metal's requirement, the tests (outside of current attachment size) can pass on Metal backend even the Metal validation layer is on. Looks like Metal's implementation doesn't follow its documentation on this.

Say the attachment's (x, y, w, h) = {0, 0, 4, 4}. The viewport rect is {0, 0, 8, 8}, or {-2, -2, 4, 4} or something like this.

What do you think, @litherum , @grorg , @JusSn ? Can you verify this with Metal team? BTW, I can find similar statement in Metal documentation for SetScissorRect that the scissor rect must lie entirely inside the attachment. And we do need to obey this rule.

FYI. @Kangz , @kainino0x , @austinEng . We simply discussed this in Dawn patch.

Activity

  1. kvark commented on Jul 22, 2019

    @kvark
    Contributor

    I don't think there is a downside for us to require both viewport and scissor rects to be limited to the render pass attachments size.

  2. Richard-Yunchao commented on Jul 22, 2019

    @Richard-Yunchao
    Author

    @kvark , that's an obvious choice. But I am not sure about it.

    I am not an app developer. But when I play with a canvas/image/video or something like that and I resize the window, I can see that two different designs are quite common: 1) the rendering result in canvas/image/video will shrink or enlarge as the window changes its size, and every object in the scene changes its size in pixel. As a result, you can always see the entire rendering result, 2) the rendering result keep the same size, every object in the scene never change its size in pixel. As a result, parts of its area are obscured when the window resizes to a smaller one, or the background color (like black) in extra area is showed when the window resizes to a larger one.

    For the 2) situation, I think it might be implemented via changing the back buffer size while keeping the viewport rect when you resize the window. If so, the viewport rect might be outside of the current attachment (or back buffer). Well, if we say viewport rect must lie within the attachment, I guess we can still implement the 2) design (but more difficult?) for webgpu-based canvas if some developers want that design for their apps.

  3. kvark commented on Jul 23, 2019

    @kvark
    Contributor

    @Richard-Yunchao good point!
    @jdashg what does WebGL do today to handle resize? Does it care about portable behavior during resize?

  4. kdashg commented on Jul 23, 2019

    @kdashg
    Contributor

    WebGL allows oversized viewports, though Firefox does issue a console warning in this case.
    Viewport and scissor are not changed automatically on resize.

  5. krogovin commented on Aug 8, 2019

    @krogovin

    There are cases where an application may want to use an oversized viewport (I have had one to be honest), but if one the underlying API's says it can't (even it can now), it is likely asking for trouble allowing for it.

  6. kainino0x commented on Aug 25, 2020

    @kainino0x
    Contributor

    This came up again in gpuweb/cts#276 and #850 (comment).

    We need to figure out what the rules are for both viewports and scissor rectangles.
    For viewports I think the two options are:

    • Disallow viewports outside the attachment, inconvenient if the attachment changes size.
    • Allow, but we can probably only do this if the underlying APIs support it. (IIRC clamping is not semantic-preserving.)

    For scissor:

    • Disallow scissor outside the attachment; same problem as above?
    • Clamp the scissor rectangle to the attachment in the implementation. I believe this is semantic-preserving.
  7. Kangz commented on Aug 31, 2020

    @Kangz
    Contributor

    There's quite some restrictions around setViewport in Vulkan. Maybe we could restrict it to be inside the attachment.

    Disallow viewports outside the attachment, inconvenient if the attachment changes size.

    I'm not sure why this matters because the viewport is set locally to a render pass, and the attachment size is constant during a render pass.

  8. kainino0x commented on Aug 31, 2020

    @kainino0x
    Contributor

    I think it would only come up if you're trying to set a fixed-size viewport and you don't handle the case where the window gets resized to smaller than that.

    The Vulkan restrictions seem to all be device limits, independent of the attachment size.

  9. kainino0x commented on Sep 14, 2020

    @kainino0x
    Contributor

    Resolution: Validate setViewport is within the attachment. Continue to investigate the following:

    • Flipped viewports (I think we already have an investigation and possibly a decision on this, just need to find it. Maybe Investigation: Viewport and Scissor Test #120, in which it's mentioned that this requires VK_KHR_maintenance1.)
    • Scissor restrictions (Metal doesn't allow zero-sized scissor rectangle. So if the scissor rect is entirely outside the attachment, we can't just clamp it, because it will end up being zero-sized. We can't no-op draw calls because of vertex shader storage writes.)
  10. kvark commented on Sep 15, 2020

    @kvark
    Contributor

    This might be a little bit silly, but there is an idea to mess with Metal viewport in order to make sure the draw calls are not rasterized. I.e. if the render area has at least 2 pixels, we can make the viewport such that it is fully within one pixel (or no pixels at all?), and the scissor in the another pixel. This doesn't answer the question of what to do if there is only 1x1 rendering :)

  11. kainino0x commented on Sep 15, 2020

    @kainino0x
    Contributor

    I'm confused now about Metal's setViewport (linked in OP). It appears that Metal has removed the sentence that Yunchao quoted, and it no longer says the viewport has to be within the attachment. I'm assuming this was lifted in a later revision of Metal, but which one?? and is it retroactive?

  12. kainino0x commented on Sep 15, 2020

    @kainino0x
    Contributor

    It was removed somewhere between 2019-06-18 and now. The documentation page still says "iOS 8.0+, macOS 10.11+" which technically implies it's retroactive, but would need confirmation from @litherum @grorg.

  13. Richard-Yunchao commented on Sep 15, 2020

    @Richard-Yunchao
    Author

    IIRC, when I raised that issue, Metal could actually allow that behavior (viewport size can be larger than attachment size), which means that the behavior on Metal conflicts with its documentation at that time. I wrote end2end tests, they can pass on Metal. Well, it is understandable because document may be outdated at that time. And the document was updated at some time.

  14. 36 remaining items

  15. magcius commented on Oct 11, 2023

    @magcius

    The 2x limit is not for 2x the current viewport size, but for 2x the maximum texture size, which WebGPU mandates is at least 8192, much larger than I would expect most web page sizes to be. I don't think it's likely you'll have viewport sizes below -16384 or above 16384.

  16. floooh commented on Oct 11, 2023

    @floooh

    To quote the relevant parts from the Vulkan documentation (https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceLimits.html)

    • viewportBoundsRange[2] is the [minimum, maximum] range that the corners of a viewport must be contained in. This range must be at least [-2 × size, 2 × size - 1], where size = max(maxViewportDimensions[0], maxViewportDimensions[1]). See Controlling the Viewport.

    ...and maxViewportDimensions is defined as:

    • maxViewportDimensions[2] are the maximum viewport dimensions in the X (width) and Y (height) dimensions, respectively. The maximum viewport dimensions must be greater than or equal to the largest image which can be created and used as a framebuffer attachment. See Controlling the Viewport.

    ...and the following note regarding viewportsBoundsRange:

    The intent of the viewportBoundsRange limit is to allow a maximum sized viewport to be arbitrarily shifted relative to the output target as long as at least some portion intersects. This would give a bounds limit of [-size + 1, 2 × size - 1] which would allow all possible non-empty-set intersections of the output target and the viewport. Since these numbers are typically powers of two, picking the signed number range using the smallest possible number of bits ends up with the specified range.

    We should probably check if this definition is the same all the way back to Vulkan 1.0.

  17. kainino0x commented on Oct 11, 2023

    @kainino0x
    Contributor

    Ah, sorry, I misremembered or never correctly understood what the -2x..2x meant. Thanks for the clarification.

  18. kainino0x commented on Nov 25, 2024

    @kainino0x
    Contributor

    Another request for this feature in #4335

  19. kdashg commented on Dec 4, 2024

    @kdashg
    Contributor

    Can we just polyfill this?

  20. floooh commented on Dec 4, 2024

    @floooh

    @kdashg assuming I understand 'polyfill' right: you can't simply clip an out-of-bounds viewport rectangle before it enters WebGPU, because that would distort the clipspace-to-screenspace(?) transform (that's also the reason why this can't be trivially handled in an engine layer, you would need to undo the distorted transform in the vertex shader).

  21. Kangz commented on Jan 27, 2025

    @Kangz
    Contributor
    GPU Web WG 2024-12-04 Atlantic-time
    • KG: Polyfill?
    • KN: Shouldn't even need polyfilling, all backends support it
    • BJ: Except Vulkan has detailed limits for this.
    • KN: IIUC Vulkan requires those limits to be at least 2*max texture size, and that would work on other backends, so can just make that the hard limit. (not introduce a new limit).
    • KG: Ok! I think we’re just waiting on a PR to relax this [somewhat].
    • BJ: Will likely pick it up
    • AB: What about zero-area viewport? Requires Vulkan 1.1 or maintenance1.
    • KN: We already require 1.1/maintenance1.
    • BJ: Use case?
    • AB: Unreal Engine uses it in multiview stuff for turning off a view, or something.
  22. floooh commented on Jan 31, 2025

    @floooh

    I'm very happy that this got resolved :)

  23. added
    api-milestone-2-202502api issues that were in milestone 2 before we triaged milestone 1 on 2025-02-19
    on Feb 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiWebGPU APIapi-milestone-2-202502api issues that were in milestone 2 before we triaged milestone 1 on 2025-02-19

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions