[WIP] D3D11 gpu accel

This commit is contained in:
wuggy 2026-09-12 08:57:32 -07:00
commit 25c4eb5efb
9 changed files with 339 additions and 0 deletions

View file

@ -7,6 +7,7 @@
#include "TextureD3D11.h"
#include "CompositorD3D11Shaders.h"
#include "GpuRasterD3D11.h"
#include "gfxWindowsPlatform.h"
#include "nsIWidget.h"
@ -143,6 +144,7 @@ private:
CompositorD3D11::CompositorD3D11(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget)
: Compositor(aWidget, aParent)
, mGpuRasterViewport(false)
, mAttachments(nullptr)
, mHwnd(nullptr)
, mDisableSequenceForNextFrame(false)
@ -199,6 +201,16 @@ CompositorD3D11::Initialize(nsCString* const out_failureReason)
mFeatureLevel = mDevice->GetFeatureLevel();
D3D11_FEATURE_DATA_D3D11_OPTIONS options = {};
if (gfxPrefs::D3D11GpuRectangleFills() &&
mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 &&
SUCCEEDED(mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS,
&options, sizeof(options))) &&
options.ClearView) {
mContext->QueryInterface(__uuidof(ID3D11DeviceContext1),
getter_AddRefs(mGpuRasterContext));
}
mHwnd = mWidget->AsWindows()->GetHwnd();
memset(&mVSConstants, 0, sizeof(VertexShaderConstants));
@ -656,6 +668,20 @@ CompositorD3D11::GetPSForEffect(Effect* aEffect, MaskType aMaskType)
void
CompositorD3D11::ClearRect(const gfx::Rect& aRect)
{
if (mGpuRasterContext && mGpuRasterViewport && mCurrentRT &&
!mCurrentRT->HasComplexProjection()) {
GpuRasterRect rect = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() };
IntSize size = mCurrentRT->GetSize();
D3D11_RECT clip = { 0, 0, size.width, size.height };
const float clear[4] = { 0, 0, 0, 0 };
if (GpuRasterD3D11FillRect(mGpuRasterContext, mCurrentRT->mRTView,
size.width, size.height, &rect, &clip, clear)) {
// BeginFrame relies on ClearRect to establish premultiplied blending.
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
return;
}
}
mContext->OMSetBlendState(mAttachments->mDisabledBlendState, sBlendFactor, 0xFFFFFFFF);
Matrix4x4 identity;
@ -736,6 +762,39 @@ CompositorD3D11::DrawQuad(const gfx::Rect& aRect,
MOZ_ASSERT(mCurrentRT, "No render target");
// Opaque, integer-aligned translated rectangles can be filled directly by
// the GPU without shader binding or per-quad constant-buffer uploads.
if (mGpuRasterContext && mGpuRasterViewport && !mCurrentRT->HasComplexProjection() &&
aEffectChain.mPrimaryEffect->mType == EffectTypes::SOLID_COLOR &&
!aEffectChain.mSecondaryEffects[EffectTypes::MASK] &&
!aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE] &&
aOpacity == 1.0f && aTransform.Is2D() && aTransform.As2D().IsTranslation()) {
const Color& color = static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
if (color.a == 1.0f) {
IntPoint origin = mCurrentRT->GetOrigin();
// Transform both edges in the shader's order before subtracting the
// target origin; moving x/y and then adding width/height can round
// differently for large coordinates.
float left = aRect.x + aTransform._41;
float right = aRect.XMost() + aTransform._41;
float top = aRect.y + aTransform._42;
float bottom = aRect.YMost() + aTransform._42;
GpuRasterRect rect = { left - origin.x, top - origin.y,
right - origin.x, bottom - origin.y };
IntRect clipRect = aClipRect;
if (mCurrentRT == mDefaultRT) {
clipRect = clipRect.Intersect(mCurrentClip);
}
D3D11_RECT clip = { clipRect.x, clipRect.y, clipRect.XMost(), clipRect.YMost() };
IntSize size = mCurrentRT->GetSize();
const float fill[4] = { color.r, color.g, color.b, color.a };
if (GpuRasterD3D11FillRect(mGpuRasterContext, mCurrentRT->mRTView,
size.width, size.height, &rect, &clip, fill)) {
return;
}
}
}
memcpy(&mVSConstants.layerTransform, &aTransform._11, 64);
IntPoint origin = mCurrentRT->GetOrigin();
mVSConstants.renderTargetOffset[0] = origin.x;
@ -1193,6 +1252,7 @@ CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize)
projection._33 = 0.0f;
PrepareViewport(aSize, projection, 0.0f, 1.0f);
mGpuRasterViewport = true;
}
void
@ -1213,6 +1273,7 @@ CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize,
const gfx::Matrix4x4& aProjection,
float aZNear, float aZFar)
{
mGpuRasterViewport = false;
D3D11_VIEWPORT viewport;
viewport.MaxDepth = aZFar;
viewport.MinDepth = aZNear;

View file

@ -11,6 +11,7 @@
#include "mozilla/layers/Compositor.h"
#include "TextureD3D11.h"
#include <d3d11.h>
#include <d3d11_1.h>
class nsWidget;
@ -174,6 +175,8 @@ private:
RefPtr<ID3D11ShaderResourceView>* aOutView);
RefPtr<ID3D11DeviceContext> mContext;
RefPtr<ID3D11DeviceContext1> mGpuRasterContext;
bool mGpuRasterViewport;
RefPtr<ID3D11Device> mDevice;
RefPtr<IDXGISwapChain> mSwapChain;
RefPtr<CompositingRenderTargetD3D11> mDefaultRT;

View file

@ -0,0 +1,84 @@
/* 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/. */
#define COBJMACROS
#include "GpuRasterD3D11.h"
#include <limits.h>
static BOOL
IntegerEdge(double value)
{
/* Ordered comparisons reject NaNs and infinities before integer conversion. */
return value >= LONG_MIN && value <= LONG_MAX && value == (LONG)value;
}
BOOL
GpuRasterD3D11ClipRect(const GpuRasterRect* rect, const D3D11_RECT* clip,
LONG width, LONG height, D3D11_RECT* result)
{
LONG left, top, right, bottom;
if (!rect || !clip || !result || width <= 0 || height <= 0 ||
!IntegerEdge(rect->left) || !IntegerEdge(rect->top) ||
!IntegerEdge(rect->right) || !IntegerEdge(rect->bottom) ||
rect->right < rect->left || rect->bottom < rect->top) {
return FALSE;
}
left = (LONG)rect->left;
top = (LONG)rect->top;
right = (LONG)rect->right;
bottom = (LONG)rect->bottom;
if (left < clip->left) left = clip->left;
if (top < clip->top) top = clip->top;
if (right > clip->right) right = clip->right;
if (bottom > clip->bottom) bottom = clip->bottom;
if (left < 0) left = 0;
if (top < 0) top = 0;
if (right > width) right = width;
if (bottom > height) bottom = height;
if (right <= left || bottom <= top) {
result->left = result->top = result->right = result->bottom = 0;
} else {
result->left = left;
result->top = top;
result->right = right;
result->bottom = bottom;
}
return TRUE;
}
BOOL
GpuRasterD3D11FillRect(ID3D11DeviceContext1* context,
ID3D11RenderTargetView* target,
LONG width, LONG height,
const GpuRasterRect* rect, const D3D11_RECT* clip,
const float color[4])
{
D3D11_RECT clipped;
D3D11_RENDER_TARGET_VIEW_DESC desc;
unsigned i;
if (!context || !target || !color ||
!GpuRasterD3D11ClipRect(rect, clip, width, height, &clipped)) {
return FALSE;
}
for (i = 0; i < 4; ++i) {
if (!(color[i] >= 0.0f && color[i] <= 1.0f)) {
return FALSE;
}
}
ID3D11RenderTargetView_GetDesc(target, &desc);
if ((desc.Format != DXGI_FORMAT_B8G8R8A8_UNORM &&
desc.Format != DXGI_FORMAT_R8G8B8A8_UNORM) ||
desc.ViewDimension != D3D11_RTV_DIMENSION_TEXTURE2D ||
desc.Texture2D.MipSlice != 0) {
return FALSE;
}
if (clipped.right != clipped.left && clipped.bottom != clipped.top) {
ID3D11DeviceContext1_ClearView(context, (ID3D11View*)target, color, &clipped, 1);
}
return TRUE;
}

View file

@ -0,0 +1,36 @@
/* 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 GFX_GPU_RASTER_D3D11_H
#define GFX_GPU_RASTER_D3D11_H
#include <d3d11_1.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Device-space edges. Fractional or non-finite edges require normal drawing. */
typedef struct GpuRasterRect {
double left, top, right, bottom;
} GpuRasterRect;
/* FALSE means unsupported input; TRUE may produce an empty clipped rectangle. */
BOOL GpuRasterD3D11ClipRect(const GpuRasterRect* rect, const D3D11_RECT* clip,
LONG width, LONG height, D3D11_RECT* result);
/* Source replacement, not alpha blending. The caller must check ClearView
* device support and supply the dimensions of the render target. No pipeline
* bindings are changed. FALSE leaves the target untouched for shader fallback. */
BOOL GpuRasterD3D11FillRect(ID3D11DeviceContext1* context,
ID3D11RenderTargetView* target,
LONG width, LONG height,
const GpuRasterRect* rect, const D3D11_RECT* clip,
const float color[4]);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -80,6 +80,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
]
SOURCES += [
'd3d11/CompositorD3D11.cpp',
'd3d11/GpuRasterD3D11.c',
'd3d11/ReadbackManagerD3D11.cpp',
]
UNIFIED_SOURCES += [