gecko-dev/gfx/layers/d3d11/mlgshaders/common-vs.hlsl

168 lines
5.4 KiB
HLSL

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_gfx_layers_d3d11_mlgshaders_common_vs_hlsl
#define mozilla_gfx_layers_d3d11_mlgshaders_common_vs_hlsl
#include "common.hlsl"
cbuffer VSBufSimple : register(b0)
{
float4x4 WorldTransform;
float2 RenderTargetOffset;
int SortIndexOffset;
uint DebugFrameNumber;
};
struct Layer {
float4x4 transform;
float4 clipRect;
uint4 info;
};
cbuffer Layers : register(b1)
{
Layer sLayers[682];
};
cbuffer MaskRects : register(b3)
{
float4 sMaskRects[4096];
};
struct VertexInfo {
float4 worldPos;
float2 screenPos;
float3 maskCoords;
float4 clipRect;
};
float3 ComputeMaskCoords(float4 aPosition, Layer aLayer)
{
if (aLayer.info.x == 0) {
return float3(0.0, 0.0, 0.0);
}
float4 maskRect = sMaskRects[aLayer.info.x - 1];
// See the perspective comment in CompositorD3D11.hlsl.
float4x4 transform = float4x4(
1.0/maskRect.z, 0.0, 0.0, -maskRect.x/maskRect.z,
0.0, 1.0/maskRect.w, 0.0, -maskRect.y/maskRect.w,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
return float3(mul(transform, aPosition / aPosition.w).xy, 1.0) * aPosition.w;
}
float2 UnitTriangleToPos(const float3 aVertex,
const float2 aPos1,
const float2 aPos2,
const float2 aPos3)
{
return aVertex.x * aPos1 +
aVertex.y * aPos2 +
aVertex.z * aPos3;
}
float2 UnitQuadToRect(const float2 aVertex, const float4 aRect)
{
return float2(aRect.x + aVertex.x * aRect.z, aRect.y + aVertex.y * aRect.w);
}
float ComputeDepth(float4 aPosition, float aSortIndex)
{
// Note: this value should match ShaderDefinitionsMLGPU.h.
return ((aSortIndex + SortIndexOffset) / 1000000.0f) * aPosition.w;
}
// Compute the world-space, screen-space, layer-space clip, and mask
// uv-coordinates given a layer-space vertex, id, and z-index.
VertexInfo ComputePosition(float2 aVertex, uint aLayerId, float aSortIndex)
{
Layer layer = sLayers[aLayerId];
// Translate from unit vertex to layer quad vertex.
float4 clipRect = layer.clipRect;
// Transform to screen coordinates.
float4x4 transform = layer.transform;
float4 layerPos = mul(transform, float4(aVertex, 0, 1));
float4 position = layerPos;
position.xyz /= position.w;
position.xy -= RenderTargetOffset.xy;
position.xyz *= position.w;
float4 worldPos = mul(WorldTransform, position);
// Depth must be computed after the world transform, since we don't want
// 3d transforms clobbering the z-value. We assume a viewport culling
// everything outside of [0, 1). Note that when depth-testing, we do not
// use sorting indices < 1.
//
// Note that we have to normalize this value to w=1, since the GPU will
// divide all values by w internally.
worldPos.z = ComputeDepth(worldPos, aSortIndex);
VertexInfo info;
info.screenPos = position.xy;
info.worldPos = worldPos;
info.maskCoords = ComputeMaskCoords(layerPos, layer);
info.clipRect = clipRect;
return info;
}
// This function takes a unit quad position and a layer rectangle, and computes
// a clipped draw rect. It is only valid to use this function for layers with
// rectilinear transforms that do not have masks.
float4 ComputeClippedPosition(const float2 aVertex,
const float4 aRect,
uint aLayerId,
float aDepth)
{
Layer layer = sLayers[aLayerId];
float4 position = float4(UnitQuadToRect(aVertex, aRect), 0, 1);
float4x4 transform = layer.transform;
float4 clipRect = layer.clipRect;
// Transform to screen coordinates.
//
// We clamp the draw rect to the clip. This lets us use faster shaders.
// For opaque shapes, it is necessary to do this anyway since we might
// otherwrite write transparent pixels in the pixel which would also be
// written to the depth buffer. We cannot use discard in the pixel shader
// as this would break early-z tests.
//
// Note that for some shaders, like textured shaders, it is not valid to
// change the draw rect like this without also clamping the texture
// coordinates. We take care to adjust for this in our batching code.
//
// We do not need to do this for 3D transforms since we always treat those
// as transparent (they are not written to the depth buffer). 3D items
// will always use the full clip+masking shader.
position = mul(transform, position);
position.xyz /= position.w;
position.xy -= RenderTargetOffset.xy;
position.xy = clamp(position.xy, clipRect.xy, clipRect.xy + clipRect.zw);
position.xyz *= position.w;
float4 worldPos = mul(WorldTransform, position);
// Depth must be computed after the world transform, since we don't want
// 3d transforms clobbering the z-value. We assume a viewport culling
// everything outside of [0, 1). Note that when depth-testing, we do not
// use sorting indices < 1.
//
// Note that we have to normalize this value to w=1, since the GPU will
// divide all values by w internally.
worldPos.z = ComputeDepth(worldPos, aDepth);
return worldPos;
}
#endif // mozilla_gfx_layers_d3d11_mlgshaders_common_vs_hlsl