Skip to content

Commit

Permalink
Remove XRWebGLLayer.requestViewportScaling()
Browse files Browse the repository at this point in the history
This method has been identified as a target for deferring until a future
version of the API, due to it's difficulty to use effectively and
overlap with framebuffer scaling for quality control.
  • Loading branch information
toji committed May 9, 2019
1 parent 8c7a85c commit 6dfeb6b
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 40 deletions.
23 changes: 3 additions & 20 deletions explainer.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,9 @@ Beyond the core APIs described above, the WebXR Device API also exposes several

### Controlling rendering quality

While in immersive sessions, the UA is responsible for providing a framebuffer that is correctly optimized for presentation to the `XRSession` in each `XRFrame`. Developers can optionally request either the buffer size or viewport size be scaled, though the UA may not respect the request. Even when the UA honors the scaling requests, the result is not guaranteed to be the exact percentage requested.
While in immersive sessions, the UA is responsible for providing a framebuffer that is correctly optimized for presentation to the `XRSession` in each `XRFrame`. Developers can optionally request the framebuffer size be scaled, though the UA may not respect the request. Even when the UA honors the scaling requests, the result is not guaranteed to be the exact percentage requested.

The first scaling mechanism is done by specifying a `framebufferScaleFactor` at `XRWebGLLayer` creation time. Each XR device has a default framebuffer size, which corresponds to a `framebufferScaleFactor` of `1.0`. This default size is determined by the UA and should represent a reasonable balance between rendering quality and performance. It may not be the 'native' size for the device (that is, a buffer which would match the native screen resolution 1:1 at point of highest magnification). For example, mobile platforms such as GearVR or Daydream frequently suggest using lower resolutions than their screens are capable of to ensure consistent performance.
Framebuffer scaling is done by specifying a `framebufferScaleFactor` at `XRWebGLLayer` creation time. Each XR device has a default framebuffer size, which corresponds to a `framebufferScaleFactor` of `1.0`. This default size is determined by the UA and should represent a reasonable balance between rendering quality and performance. It may not be the 'native' size for the device (that is, a buffer which would match the native screen resolution 1:1 at point of highest magnification). For example, mobile platforms such as GearVR or Daydream frequently suggest using lower resolutions than their screens are capable of to ensure consistent performance.

If the `framebufferScaleFactor` is set to a number higher or lower than `1.0` the UA should create a framebuffer that is the default resolution multiplied by the given scale factor. So a `framebufferScaleFactor` of `0.5` would specify a framebuffer with 50% the default height and width, and so on. The UA may clamp the scale factor however it sees fit, or may round it to a desired increment if needed (for example, fitting the buffer dimensions to powers of two if that is known to increase performance.)

Expand All @@ -485,23 +485,7 @@ function setupNativeScaleWebGLLayer() {
});
```
This technique should be used carefully, since the native resolution on some headsets may be higher than the system is capable of rendering at a stable framerate without use of additional techniques such as foveated rendering. Also note that the UA's scale clamping is allowed to prevent the allocation of native resoltion framebuffers if it deems it necessary to maintain acceptable performance.
The second scaling mechanism is to request a scaled viewport into the `XRWebGLLayer`'s `framebuffer`. For example, under times of heavy load the developer may choose to temporarily render fewer pixels. To do so, developers should call `XRWebGLLayer.requestViewportScaling()` and supply a value between 0.0 and 1.0. The UA may then respond by changing the `XRWebGLLayer`'s `framebuffer` and/or the `XRViewport` values in future XR frames. It is worth noting that the UA may change the viewports for reasons other than developer request, and that not all UAs will respect requested viewport changes; as such, developers must always query the viewport values on each XR frame.
```js
function onDrawFrame() {
// Draw the current frame

// In response to a performance dip, request the viewport be restricted
// to a percentage (ex: 50%) of the layer's actual buffer. This change
// will apply to subsequent rendering frames
layer.requestViewportScaling(0.5);

// Register for next frame callback
xrSession.requestAnimationFrame(onDrawFrame);
}
```
This technique should be used carefully, since the native resolution on some headsets may be higher than the system is capable of rendering at a stable framerate without use of additional techniques such as foveated rendering. Also note that the UA's scale clamping is allowed to prevent the allocation of native resolution framebuffers if it deems it necessary to maintain acceptable performance.
### Controlling depth precision
Expand Down Expand Up @@ -738,7 +722,6 @@ interface XRWebGLLayer : XRLayer {
readonly attribute WebGLFramebuffer framebuffer;

XRViewport? getViewport(XRView view);
Promise<void> requestViewportScaling(double viewportScaleFactor);

static double getNativeFramebufferScaleFactor(XRSession session);
};
Expand Down
24 changes: 4 additions & 20 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,6 @@ interface XRWebGLLayer : XRLayer {

// Methods
XRViewport? getViewport(XRView view);
void requestViewportScaling(double viewportScaleFactor);

// Static Methods
static double getNativeFramebufferScaleFactor(XRSession session);
Expand Down Expand Up @@ -1358,7 +1357,7 @@ The <dfn attribute for="XRWebGLLayer">framebuffer</dfn> attribute of an {{XRWebG
- An [=opaque framebuffer=]'s attachments cannot be inspected or changed. Calling {{framebufferTexture2D}}, {{framebufferRenderbuffer}}, {{getFramebufferAttachmentParameter}}, or {{getRenderbufferParameter}} with an [=opaque framebuffer=] MUST generate an {{INVALID_OPERATION}} error.
- An [=opaque framebuffer=] is considered incomplete outside of an {{XRSession/requestAnimationFrame()}} callback. When not in a {{XRSession/requestAnimationFrame()}} callback calls to {{checkFramebufferStatus}} outside of an {{XRSession/requestAnimationFrame()}} callback MUST generate a {{FRAMEBUFFER_UNSUPPORTED}} error and attempts to clear, draw to, or read from the [=opaque framebuffer=] MUST generate an {{INVALID_FRAMEBUFFER_OPERATION}} error.

The <dfn attribute for="XRWebGLLayer">framebufferWidth</dfn> and <dfn attribute for="XRWebGLLayer">framebufferHeight</dfn> attributes return the width and height of the {{framebuffer}}'s attachments, respectively.
The <dfn attribute for="XRWebGLLayer">framebufferWidth</dfn> and <dfn attribute for="XRWebGLLayer">framebufferHeight</dfn> attributes return the width and height of the {{framebuffer}}'s attachments, respectively. The {{framebuffer}} size cannot be adjusted by the developer after the {{XRWebGLLayer}} has been created.

The <dfn attribute for="XRWebGLLayer">antialias</dfn> attribute is <code>true</code> if the {{framebuffer}} supports antialiasing using a technique of the UAs choosing, and <code>false</code> if no antialiasing will be performed.

Expand All @@ -1368,7 +1367,7 @@ Depth values stored in the buffer are expected to be between <code>0.0</code> an

NOTE: Making the scene's depth buffer available to the compositor allows some platforms to provide quality and comfort improvements such as improved reprojection.

Each {{XRWebGLLayer}} MUST have a <dfn>list of viewports</dfn> which contains one [=WebGL viewport=] for each {{XRView}} the {{XRSession}} currently exposes. The viewports MUST NOT be overlapping. The {{XRWebGLLayer}} MUST also have a <dfn>viewport scale factor</dfn>, initially set to 1.0, and a <dfn>minimum viewport scale factor</dfn> set to a UA-determined value between 0 and 1.
Each {{XRWebGLLayer}} MUST have a <dfn>list of viewports</dfn> which contains one [=WebGL viewport=] for each {{XRView}} the {{XRSession}} currently exposes. The viewports MUST NOT be overlapping.

{{getViewport()}} queries the {{XRViewport}} the given {{XRView}} should use when rendering to the layer.

Expand All @@ -1381,27 +1380,12 @@ The <dfn method for="XRWebGLLayer">getViewport(|view|)</dfn> method, when invoke
1. Let |viewport| be a new {{XRViewport}} instance.
1. Initialize |viewport|'s {{XRViewport/x}} to |glViewport|'s <code>x</code> component.
1. Initialize |viewport|'s {{XRViewport/y}} to |glViewport|'s <code>y</code> component.
1. Initialize |viewport|'s {{XRViewport/width}} to |glViewport|'s <code>width</code> component multiplied by the [=viewport scale factor=].
1. Initialize |viewport|'s {{XRViewport/height}} to |glViewport|'s <code>height</code> component multiplied by the [=viewport scale factor=].
1. Initialize |viewport|'s {{XRViewport/width}} to |glViewport|'s <code>width</code>.
1. Initialize |viewport|'s {{XRViewport/height}} to |glViewport|'s <code>height</code>.
1. Return |viewport|.

</div>

<section class="unstable">
The {{framebuffer}} size cannot be adjusted by the developer after the {{XRWebGLLayer}} has been created, but it can be useful to adjust the resolution content is rendered at at runtime to aid application performance. To do so, developers can request that the size of the viewports in the [=list of viewports=] be changed using the {{requestViewportScaling()}} method.

<div class="algorithm" data-algorithm="request-viewport-scaling">

The <dfn method for="XRWebGLLayer">requestViewportScaling(|scaleFactor|)</dfn> method, when invoked, MUST run the following steps:

1. If |scaleFactor| is greater than 1.0 set |scaleFactor| to 1.0.
1. If |scaleFactor| is less than the [=minimum viewport scale factor=] set |scaleFactor| to the [=minimum viewport scale factor=].
1. If the [=XR/XR device=] places additional device-specific restrictions on viewport size, adjust |scaleFactor| accordingly.
1. Set the [=viewport scale factor=] to |scaleFactor|.

</div>
</section>

Each {{XRSession}} MUST identify a <dfn>native WebGL framebuffer resolution</dfn>, which is the pixel resolution of a WebGL framebuffer required to match the physical pixel resolution of the [=/XR device=].

<div class="algorithm" data-algorithm="native-webgl-framebuffer-resolution">
Expand Down

0 comments on commit 6dfeb6b

Please sign in to comment.