Add the webgpu.h swapchain creation path

This commit changes wgpu::Device::CreateSwapChain to take an additional
wgpu::Surface argument. Passing nullptr is enough to stay on the
previous swapchain implementation, until the new one is ready.

In order to support both the "old" implementation-based swapchains and
the "new" surface-based swapchains. SwapChainBase is now split into
three abstract classes:

 - SwapChainBase that has a virtual method for each of the
wgpu::SwapChain methods.
 - OldSwapChainBase that corresponds to the implementation-based
swapchains.
 - NewSwapChainBase that will contain the surface-based swapchain
implementation and will eventually just be renamed to SwapChainBase.

The interaction of the surface-based swapchains with the Surface objects
aren't implemented yet, neither are the swapchain methods. Only creation
works.

Validation tests for surface-based swapchain creation are added in the
end2end test target because they need to create OS windows.

Bug: dawn:269

Change-Id: I7e07d6c666479867b9a16d7b1b8c181d5dbd69a0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15281
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Corentin Wallez
2020-01-23 17:20:38 +00:00
committed by Commit Bot service account
parent a5a6e4f5bb
commit d87e676845
31 changed files with 460 additions and 73 deletions

View File

@@ -14,7 +14,9 @@
#include "dawn_native/SwapChain.h"
#include "common/Constants.h"
#include "dawn_native/Device.h"
#include "dawn_native/Surface.h"
#include "dawn_native/Texture.h"
#include "dawn_native/ValidationUtils_autogen.h"
@@ -28,40 +30,75 @@ namespace dawn_native {
}
private:
TextureBase* GetNextTextureImpl(const TextureDescriptor*) override {
UNREACHABLE();
void Configure(wgpu::TextureFormat format,
wgpu::TextureUsage allowedUsage,
uint32_t width,
uint32_t height) override {
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("error swapchain"));
}
MaybeError OnBeforePresent(TextureBase* texture) override {
UNREACHABLE();
TextureViewBase* GetCurrentTextureView() override {
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("error swapchain"));
return TextureViewBase::MakeError(GetDevice());
}
void Present() override {
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("error swapchain"));
}
};
} // anonymous namespace
MaybeError ValidateSwapChainDescriptor(const DeviceBase* device,
const Surface* surface,
const SwapChainDescriptor* descriptor) {
if (descriptor->implementation == 0) {
return DAWN_VALIDATION_ERROR("Null implementation for the swapchain");
}
if (descriptor->implementation != 0) {
if (surface != nullptr) {
return DAWN_VALIDATION_ERROR(
"Exactly one of surface or implementation must be set");
}
DawnSwapChainImplementation* impl =
reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation);
DawnSwapChainImplementation* impl =
reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation);
if (!impl->Init || !impl->Destroy || !impl->Configure || !impl->GetNextTexture ||
!impl->Present) {
return DAWN_VALIDATION_ERROR("Implementation is incomplete");
if (!impl->Init || !impl->Destroy || !impl->Configure || !impl->GetNextTexture ||
!impl->Present) {
return DAWN_VALIDATION_ERROR("Implementation is incomplete");
}
} else {
if (surface == nullptr) {
return DAWN_VALIDATION_ERROR(
"At least one of surface or implementation must be set");
}
DAWN_TRY(ValidatePresentMode(descriptor->presentMode));
// TODO(cwallez@chromium.org): Lift this restriction once
// wgpu::Instance::GetPreferredSurfaceFormat is implemented.
if (descriptor->format != wgpu::TextureFormat::BGRA8Unorm) {
return DAWN_VALIDATION_ERROR("Format must (currently) be BGRA8Unorm");
}
if (descriptor->usage != wgpu::TextureUsage::OutputAttachment) {
return DAWN_VALIDATION_ERROR("Usage must (currently) be OutputAttachment");
}
if (descriptor->width == 0 || descriptor->height == 0) {
return DAWN_VALIDATION_ERROR("Swapchain size can't be empty");
}
if (descriptor->width > kMaxTextureSize || descriptor->height > kMaxTextureSize) {
return DAWN_VALIDATION_ERROR("Swapchain size too big");
}
}
return {};
}
// SwapChain
// SwapChainBase
SwapChainBase::SwapChainBase(DeviceBase* device, const SwapChainDescriptor* descriptor)
: ObjectBase(device),
mImplementation(
*reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation)) {
SwapChainBase::SwapChainBase(DeviceBase* device) : ObjectBase(device) {
}
SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag)
@@ -69,10 +106,6 @@ namespace dawn_native {
}
SwapChainBase::~SwapChainBase() {
if (!IsError()) {
const auto& im = GetImplementation();
im.Destroy(im.userData);
}
}
// static
@@ -80,10 +113,25 @@ namespace dawn_native {
return new ErrorSwapChain(device);
}
void SwapChainBase::Configure(wgpu::TextureFormat format,
wgpu::TextureUsage allowedUsage,
uint32_t width,
uint32_t height) {
// OldSwapChainBase
OldSwapChainBase::OldSwapChainBase(DeviceBase* device, const SwapChainDescriptor* descriptor)
: SwapChainBase(device),
mImplementation(
*reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation)) {
}
OldSwapChainBase::~OldSwapChainBase() {
if (!IsError()) {
const auto& im = GetImplementation();
im.Destroy(im.userData);
}
}
void OldSwapChainBase::Configure(wgpu::TextureFormat format,
wgpu::TextureUsage allowedUsage,
uint32_t width,
uint32_t height) {
if (GetDevice()->ConsumedError(ValidateConfigure(format, allowedUsage, width, height))) {
return;
}
@@ -99,7 +147,7 @@ namespace dawn_native {
static_cast<WGPUTextureUsage>(allowedUsage), width, height);
}
TextureViewBase* SwapChainBase::GetCurrentTextureView() {
TextureViewBase* OldSwapChainBase::GetCurrentTextureView() {
if (GetDevice()->ConsumedError(ValidateGetCurrentTextureView())) {
return TextureViewBase::MakeError(GetDevice());
}
@@ -133,7 +181,7 @@ namespace dawn_native {
return mCurrentTextureView.Get();
}
void SwapChainBase::Present() {
void OldSwapChainBase::Present() {
if (GetDevice()->ConsumedError(ValidatePresent())) {
return;
}
@@ -149,15 +197,15 @@ namespace dawn_native {
mCurrentTextureView = nullptr;
}
const DawnSwapChainImplementation& SwapChainBase::GetImplementation() {
const DawnSwapChainImplementation& OldSwapChainBase::GetImplementation() {
ASSERT(!IsError());
return mImplementation;
}
MaybeError SwapChainBase::ValidateConfigure(wgpu::TextureFormat format,
wgpu::TextureUsage allowedUsage,
uint32_t width,
uint32_t height) const {
MaybeError OldSwapChainBase::ValidateConfigure(wgpu::TextureFormat format,
wgpu::TextureUsage allowedUsage,
uint32_t width,
uint32_t height) const {
DAWN_TRY(GetDevice()->ValidateObject(this));
DAWN_TRY(ValidateTextureUsage(allowedUsage));
@@ -170,7 +218,7 @@ namespace dawn_native {
return {};
}
MaybeError SwapChainBase::ValidateGetCurrentTextureView() const {
MaybeError OldSwapChainBase::ValidateGetCurrentTextureView() const {
DAWN_TRY(GetDevice()->ValidateObject(this));
if (mWidth == 0) {
@@ -181,7 +229,7 @@ namespace dawn_native {
return {};
}
MaybeError SwapChainBase::ValidatePresent() const {
MaybeError OldSwapChainBase::ValidatePresent() const {
DAWN_TRY(GetDevice()->ValidateObject(this));
if (mCurrentTextureView.Get() == nullptr) {
@@ -192,4 +240,56 @@ namespace dawn_native {
return {};
}
// Implementation of NewSwapChainBase
NewSwapChainBase::NewSwapChainBase(DeviceBase* device,
Surface* surface,
const SwapChainDescriptor* descriptor)
: SwapChainBase(device),
mWidth(descriptor->width),
mHeight(descriptor->height),
mFormat(descriptor->format),
mUsage(descriptor->usage),
mSurface(surface) {
}
void NewSwapChainBase::Configure(wgpu::TextureFormat format,
wgpu::TextureUsage allowedUsage,
uint32_t width,
uint32_t height) {
GetDevice()->ConsumedError(
DAWN_VALIDATION_ERROR("Configure is invalid for surface-based swapchains"));
}
TextureViewBase* NewSwapChainBase::GetCurrentTextureView() {
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR(
"GetCurrentTextureView not implemented yet for surface-based swapchains"));
return TextureViewBase::MakeError(GetDevice());
}
void NewSwapChainBase::Present() {
GetDevice()->ConsumedError(
DAWN_VALIDATION_ERROR("Present not implemented yet for surface-based swapchains"));
}
uint32_t NewSwapChainBase::GetWidth() const {
return mWidth;
}
uint32_t NewSwapChainBase::GetHeight() const {
return mHeight;
}
wgpu::TextureFormat NewSwapChainBase::GetFormat() const {
return mFormat;
}
wgpu::TextureUsage NewSwapChainBase::GetUsage() const {
return mUsage;
}
Surface* NewSwapChainBase::GetSurface() {
return mSurface.Get();
}
} // namespace dawn_native