wg_engine: cross-platform support

it provide changes public API for webgpu canvas interface to provide nessessary handles to native window for different platforms:

API Change:
- Result target(void *instance, void *surface, uint32_t w, uint32_t h) noexcept;
This commit is contained in:
Sergii Liebodkin 2024-06-12 06:39:37 +03:00 committed by GitHub
parent 50d1d2fd36
commit 7e493f91f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 131 additions and 91 deletions

View file

@ -1796,7 +1796,7 @@ public:
* @note Experimental API * @note Experimental API
* @see Canvas::viewport() * @see Canvas::viewport()
*/ */
Result target(void* window, uint32_t w, uint32_t h) noexcept; Result target(void* instance, void* surface, uint32_t w, uint32_t h) noexcept;
/** /**
* @brief Creates a new WgCanvas object. * @brief Creates a new WgCanvas object.

View file

@ -52,17 +52,18 @@ WgCanvas::~WgCanvas()
delete pImpl; delete pImpl;
} }
Result WgCanvas::target(void* window, uint32_t w, uint32_t h) noexcept Result WgCanvas::target(void* instance, void* surface, uint32_t w, uint32_t h) noexcept
{ {
#ifdef THORVG_WG_RASTER_SUPPORT #ifdef THORVG_WG_RASTER_SUPPORT
if (!window) return Result::InvalidArguments; if (!instance) return Result::InvalidArguments;
if (!surface) return Result::InvalidArguments;
if ((w == 0) || (h == 0)) return Result::InvalidArguments; if ((w == 0) || (h == 0)) return Result::InvalidArguments;
//We know renderer type, avoid dynamic_cast for performance. //We know renderer type, avoid dynamic_cast for performance.
auto renderer = static_cast<WgRenderer*>(Canvas::pImpl->renderer); auto renderer = static_cast<WgRenderer*>(Canvas::pImpl->renderer);
if (!renderer) return Result::MemoryCorruption; if (!renderer) return Result::MemoryCorruption;
if (!renderer->target(window, w, h)) return Result::Unknown; if (!renderer->target((WGPUInstance)instance, (WGPUSurface)surface, w, h)) return Result::Unknown;
Canvas::pImpl->vport = {0, 0, (int32_t)w, (int32_t)h}; Canvas::pImpl->vport = {0, 0, (int32_t)w, (int32_t)h};
renderer->viewport(Canvas::pImpl->vport); renderer->viewport(Canvas::pImpl->vport);

View file

@ -33,7 +33,8 @@ WGPUBindGroupLayout WgBindGroupRadialGradient::layout = nullptr;
WGPUBindGroupLayout WgBindGroupPicture::layout = nullptr; WGPUBindGroupLayout WgBindGroupPicture::layout = nullptr;
// composition and blending properties gropus // composition and blending properties gropus
WGPUBindGroupLayout WgBindGroupTexture::layout = nullptr; WGPUBindGroupLayout WgBindGroupTexture::layout = nullptr;
WGPUBindGroupLayout WgBindGroupTextureStorage::layout = nullptr; WGPUBindGroupLayout WgBindGroupTextureStorageRgba::layout = nullptr;
WGPUBindGroupLayout WgBindGroupTextureStorageBgra::layout = nullptr;
WGPUBindGroupLayout WgBindGroupTextureSampled::layout = nullptr; WGPUBindGroupLayout WgBindGroupTextureSampled::layout = nullptr;
WGPUBindGroupLayout WgBindGroupTexComposeBlend::layout = nullptr; WGPUBindGroupLayout WgBindGroupTexComposeBlend::layout = nullptr;
WGPUBindGroupLayout WgBindGroupOpacity::layout = nullptr; WGPUBindGroupLayout WgBindGroupOpacity::layout = nullptr;
@ -315,11 +316,11 @@ void WgBindGroupTexture::release()
} }
WGPUBindGroupLayout WgBindGroupTextureStorage::getLayout(WGPUDevice device) WGPUBindGroupLayout WgBindGroupTextureStorageRgba::getLayout(WGPUDevice device)
{ {
if (layout) return layout; if (layout) return layout;
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
makeBindGroupLayoutEntryStorageTexture(0, WGPUStorageTextureAccess_ReadWrite) makeBindGroupLayoutEntryStorage(0, WGPUStorageTextureAccess_ReadWrite, WGPUTextureFormat_RGBA8Unorm)
}; };
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1); layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1);
assert(layout); assert(layout);
@ -327,13 +328,13 @@ WGPUBindGroupLayout WgBindGroupTextureStorage::getLayout(WGPUDevice device)
} }
void WgBindGroupTextureStorage::releaseLayout() void WgBindGroupTextureStorageRgba::releaseLayout()
{ {
releaseBindGroupLayout(layout); releaseBindGroupLayout(layout);
} }
void WgBindGroupTextureStorage::initialize(WGPUDevice device, WGPUQueue queue, WGPUTextureView uTexture) void WgBindGroupTextureStorageRgba::initialize(WGPUDevice device, WGPUQueue queue, WGPUTextureView uTexture)
{ {
release(); release();
const WGPUBindGroupEntry bindGroupEntries[] { const WGPUBindGroupEntry bindGroupEntries[] {
@ -344,7 +345,42 @@ void WgBindGroupTextureStorage::initialize(WGPUDevice device, WGPUQueue queue, W
} }
void WgBindGroupTextureStorage::release() void WgBindGroupTextureStorageRgba::release()
{
releaseBindGroup(mBindGroup);
}
WGPUBindGroupLayout WgBindGroupTextureStorageBgra::getLayout(WGPUDevice device)
{
if (layout) return layout;
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
makeBindGroupLayoutEntryStorage(0, WGPUStorageTextureAccess_WriteOnly, WGPUTextureFormat_BGRA8Unorm)
};
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 1);
assert(layout);
return layout;
}
void WgBindGroupTextureStorageBgra::releaseLayout()
{
releaseBindGroupLayout(layout);
}
void WgBindGroupTextureStorageBgra::initialize(WGPUDevice device, WGPUQueue queue, WGPUTextureView uTexture)
{
release();
const WGPUBindGroupEntry bindGroupEntries[] {
makeBindGroupEntryTextureView(0, uTexture)
};
mBindGroup = createBindGroup(device, getLayout(device), bindGroupEntries, 1);
assert(mBindGroup);
}
void WgBindGroupTextureStorageBgra::release()
{ {
releaseBindGroup(mBindGroup); releaseBindGroup(mBindGroup);
} }
@ -391,9 +427,9 @@ WGPUBindGroupLayout WgBindGroupTexComposeBlend::getLayout(WGPUDevice device)
{ {
if (layout) return layout; if (layout) return layout;
const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] { const WGPUBindGroupLayoutEntry bindGroupLayoutEntries[] {
makeBindGroupLayoutEntryStorageTexture(0, WGPUStorageTextureAccess_ReadOnly), makeBindGroupLayoutEntryStorage(0, WGPUStorageTextureAccess_ReadOnly, WGPUTextureFormat_RGBA8Unorm),
makeBindGroupLayoutEntryStorageTexture(1, WGPUStorageTextureAccess_ReadOnly), makeBindGroupLayoutEntryStorage(1, WGPUStorageTextureAccess_ReadOnly, WGPUTextureFormat_RGBA8Unorm),
makeBindGroupLayoutEntryStorageTexture(2, WGPUStorageTextureAccess_ReadWrite) makeBindGroupLayoutEntryStorage(2, WGPUStorageTextureAccess_ReadWrite, WGPUTextureFormat_RGBA8Unorm)
}; };
layout = createBindGroupLayout(device, bindGroupLayoutEntries, 3); layout = createBindGroupLayout(device, bindGroupLayoutEntries, 3);
assert(layout); assert(layout);

View file

@ -119,7 +119,19 @@ struct WgBindGroupTexture : public WgBindGroup
}; };
// @group(0 or 1) // @group(0 or 1)
struct WgBindGroupTextureStorage : public WgBindGroup struct WgBindGroupTextureStorageRgba : public WgBindGroup
{
static WGPUBindGroupLayout layout;
static WGPUBindGroupLayout getLayout(WGPUDevice device);
static void releaseLayout();
void initialize(WGPUDevice device, WGPUQueue queue,
WGPUTextureView uTexture);
void release();
};
// @group(0 or 1)
struct WgBindGroupTextureStorageBgra : public WgBindGroup
{ {
static WGPUBindGroupLayout layout; static WGPUBindGroupLayout layout;
static WGPUBindGroupLayout getLayout(WGPUDevice device); static WGPUBindGroupLayout getLayout(WGPUDevice device);

View file

@ -27,18 +27,19 @@
// context // context
//***************************************************************************** //*****************************************************************************
void WgContext::initialize() void WgContext::initialize(WGPUInstance instance, WGPUSurface surface)
{ {
// create instance
WGPUInstanceDescriptor instanceDesc{};
instanceDesc.nextInChain = nullptr;
instance = wgpuCreateInstance(&instanceDesc);
assert(instance); assert(instance);
assert(surface);
// store global instance and surface
this->instance = instance;
this->surface = surface;
// request adapter options // request adapter options
WGPURequestAdapterOptions requestAdapterOptions{}; WGPURequestAdapterOptions requestAdapterOptions{};
requestAdapterOptions.nextInChain = nullptr; requestAdapterOptions.nextInChain = nullptr;
requestAdapterOptions.compatibleSurface = nullptr; requestAdapterOptions.compatibleSurface = surface;
requestAdapterOptions.powerPreference = WGPUPowerPreference_HighPerformance; requestAdapterOptions.powerPreference = WGPUPowerPreference_HighPerformance;
requestAdapterOptions.forceFallbackAdapter = false; requestAdapterOptions.forceFallbackAdapter = false;
// on adapter request ended function // on adapter request ended function
@ -113,6 +114,11 @@ void WgContext::release()
wgpuAdapterRelease(adapter); wgpuAdapterRelease(adapter);
adapter = nullptr; adapter = nullptr;
} }
if (surface) {
wgpuSurfaceUnconfigure(surface);
wgpuSurfaceRelease(surface);
surface = nullptr;
}
if (instance) { if (instance) {
wgpuInstanceRelease(instance); wgpuInstanceRelease(instance);
instance = nullptr; instance = nullptr;
@ -170,7 +176,6 @@ WGPUTexture WgContext::createTexture2d(WGPUTextureUsageFlags usage, WGPUTextureF
WGPUTexture WgContext::createTexture2dMS(WGPUTextureUsageFlags usage, WGPUTextureFormat format, uint32_t width, uint32_t height, uint32_t sc, char const * label) WGPUTexture WgContext::createTexture2dMS(WGPUTextureUsageFlags usage, WGPUTextureFormat format, uint32_t width, uint32_t height, uint32_t sc, char const * label)
{ {
WGPUTextureDescriptor textureDesc{}; WGPUTextureDescriptor textureDesc{};
textureDesc.nextInChain = nullptr; textureDesc.nextInChain = nullptr;
textureDesc.label = label; textureDesc.label = label;
@ -326,7 +331,6 @@ void WgContext::releaseIndexBuffer(WGPUBuffer& buffer)
releaseBuffer(buffer); releaseBuffer(buffer);
} }
//***************************************************************************** //*****************************************************************************
// bind group // bind group
//***************************************************************************** //*****************************************************************************
@ -425,7 +429,7 @@ WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntryTexture(uint32_t b
} }
WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntryStorageTexture(uint32_t binding, WGPUStorageTextureAccess access) WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntryStorage(uint32_t binding, WGPUStorageTextureAccess access, WGPUTextureFormat format)
{ {
WGPUBindGroupLayoutEntry bindGroupLayoutEntry{}; WGPUBindGroupLayoutEntry bindGroupLayoutEntry{};
bindGroupLayoutEntry.nextInChain = nullptr; bindGroupLayoutEntry.nextInChain = nullptr;
@ -433,7 +437,7 @@ WGPUBindGroupLayoutEntry WgBindGroup::makeBindGroupLayoutEntryStorageTexture(uin
bindGroupLayoutEntry.visibility = WGPUShaderStage_Fragment | WGPUShaderStage_Compute; bindGroupLayoutEntry.visibility = WGPUShaderStage_Fragment | WGPUShaderStage_Compute;
bindGroupLayoutEntry.storageTexture.nextInChain = nullptr; bindGroupLayoutEntry.storageTexture.nextInChain = nullptr;
bindGroupLayoutEntry.storageTexture.access = access; bindGroupLayoutEntry.storageTexture.access = access;
bindGroupLayoutEntry.storageTexture.format = WGPUTextureFormat_BGRA8Unorm; bindGroupLayoutEntry.storageTexture.format = format;
bindGroupLayoutEntry.storageTexture.viewDimension = WGPUTextureViewDimension_2D; bindGroupLayoutEntry.storageTexture.viewDimension = WGPUTextureViewDimension_2D;
return bindGroupLayoutEntry; return bindGroupLayoutEntry;
} }
@ -634,7 +638,7 @@ WGPUColorTargetState WgRenderPipeline::makeColorTargetState(const WGPUBlendState
{ {
WGPUColorTargetState colorTargetState{}; WGPUColorTargetState colorTargetState{};
colorTargetState.nextInChain = nullptr; colorTargetState.nextInChain = nullptr;
colorTargetState.format = WGPUTextureFormat_BGRA8Unorm; colorTargetState.format = WGPUTextureFormat_RGBA8Unorm;
colorTargetState.blend = blendState; colorTargetState.blend = blendState;
colorTargetState.writeMask = writeMask; colorTargetState.writeMask = writeMask;
return colorTargetState; return colorTargetState;

View file

@ -44,6 +44,7 @@ struct WgPipelines;
struct WgContext { struct WgContext {
WGPUInstance instance{}; WGPUInstance instance{};
WGPUSurface surface{};
WGPUAdapter adapter{}; WGPUAdapter adapter{};
WGPUDevice device{}; WGPUDevice device{};
WGPUQueue queue{}; WGPUQueue queue{};
@ -58,7 +59,7 @@ struct WgContext {
WgPipelines* pipelines{}; // external handle (do not release) WgPipelines* pipelines{}; // external handle (do not release)
void initialize(); void initialize(WGPUInstance instance, WGPUSurface surface);
void release(); void release();
void executeCommandEncoder(WGPUCommandEncoder commandEncoder); void executeCommandEncoder(WGPUCommandEncoder commandEncoder);
@ -95,7 +96,7 @@ struct WgBindGroup
static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryBuffer(uint32_t binding); static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryBuffer(uint32_t binding);
static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntrySampler(uint32_t binding); static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntrySampler(uint32_t binding);
static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryTexture(uint32_t binding); static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryTexture(uint32_t binding);
static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryStorageTexture(uint32_t binding, WGPUStorageTextureAccess access); static WGPUBindGroupLayoutEntry makeBindGroupLayoutEntryStorage(uint32_t binding, WGPUStorageTextureAccess access, WGPUTextureFormat format);
static WGPUBuffer createBuffer(WGPUDevice device, WGPUQueue queue, const void *data, size_t size); static WGPUBuffer createBuffer(WGPUDevice device, WGPUQueue queue, const void *data, size_t size);
static WGPUBindGroup createBindGroup(WGPUDevice device, WGPUBindGroupLayout layout, const WGPUBindGroupEntry* bindGroupEntries, uint32_t count); static WGPUBindGroup createBindGroup(WGPUDevice device, WGPUBindGroupLayout layout, const WGPUBindGroupEntry* bindGroupEntries, uint32_t count);

View file

@ -270,7 +270,7 @@ void WgPipelineClear::initialize(WGPUDevice device)
{ {
// bind groups and layouts // bind groups and layouts
WGPUBindGroupLayout bindGroupLayouts[] = { WGPUBindGroupLayout bindGroupLayouts[] = {
WgBindGroupTextureStorage::getLayout(device) WgBindGroupTextureStorageRgba::getLayout(device)
}; };
// sheder source and labels // sheder source and labels
@ -289,8 +289,8 @@ void WgPipelineBlend::initialize(WGPUDevice device)
{ {
// bind groups and layouts // bind groups and layouts
WGPUBindGroupLayout bindGroupLayouts[] = { WGPUBindGroupLayout bindGroupLayouts[] = {
WgBindGroupTextureStorage::getLayout(device), WgBindGroupTextureStorageRgba::getLayout(device),
WgBindGroupTextureStorage::getLayout(device), WgBindGroupTextureStorageRgba::getLayout(device),
WgBindGroupBlendMethod::getLayout(device) WgBindGroupBlendMethod::getLayout(device)
}; };
@ -310,8 +310,8 @@ void WgPipelineCompose::initialize(WGPUDevice device)
{ {
// bind groups and layouts // bind groups and layouts
WGPUBindGroupLayout bindGroupLayouts[] = { WGPUBindGroupLayout bindGroupLayouts[] = {
WgBindGroupTextureStorage::getLayout(device), WgBindGroupTextureStorageRgba::getLayout(device),
WgBindGroupTextureStorage::getLayout(device), WgBindGroupTextureStorageRgba::getLayout(device),
WgBindGroupCompositeMethod::getLayout(device), WgBindGroupCompositeMethod::getLayout(device),
WgBindGroupOpacity::getLayout(device) WgBindGroupOpacity::getLayout(device)
}; };
@ -354,8 +354,8 @@ void WgPipelineAntiAliasing::initialize(WGPUDevice device)
{ {
// bind groups and layouts // bind groups and layouts
WGPUBindGroupLayout bindGroupLayouts[] = { WGPUBindGroupLayout bindGroupLayouts[] = {
WgBindGroupTextureStorage::getLayout(device), WgBindGroupTextureStorageRgba::getLayout(device),
WgBindGroupTextureStorage::getLayout(device) WgBindGroupTextureStorageBgra::getLayout(device)
}; };
// sheder source and labels // sheder source and labels
@ -400,7 +400,8 @@ void WgPipelines::release()
{ {
WgBindGroupTexComposeBlend::layout = nullptr; WgBindGroupTexComposeBlend::layout = nullptr;
WgBindGroupTextureSampled::releaseLayout(); WgBindGroupTextureSampled::releaseLayout();
WgBindGroupTextureStorage::releaseLayout(); WgBindGroupTextureStorageBgra::releaseLayout();
WgBindGroupTextureStorageRgba::releaseLayout();
WgBindGroupTexture::releaseLayout(); WgBindGroupTexture::releaseLayout();
WgBindGroupOpacity::releaseLayout(); WgBindGroupOpacity::releaseLayout();
WgBindGroupPicture::releaseLayout(); WgBindGroupPicture::releaseLayout();

View file

@ -121,7 +121,7 @@ struct WgPipelineImage: public WgRenderPipeline
struct WgPipelineClear: public WgComputePipeline struct WgPipelineClear: public WgComputePipeline
{ {
void initialize(WGPUDevice device) override; void initialize(WGPUDevice device) override;
void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorage& groupTexDst) void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorageRgba& groupTexDst)
{ {
set(encoder); set(encoder);
groupTexDst.set(encoder, 0); groupTexDst.set(encoder, 0);
@ -132,7 +132,7 @@ struct WgPipelineClear: public WgComputePipeline
struct WgPipelineBlend: public WgComputePipeline struct WgPipelineBlend: public WgComputePipeline
{ {
void initialize(WGPUDevice device) override; void initialize(WGPUDevice device) override;
void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorage& groupTexSrc, WgBindGroupTextureStorage& groupTexDst, WgBindGroupBlendMethod& blendMethod) void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorageRgba& groupTexSrc, WgBindGroupTextureStorageRgba& groupTexDst, WgBindGroupBlendMethod& blendMethod)
{ {
set(encoder); set(encoder);
groupTexSrc.set(encoder, 0); groupTexSrc.set(encoder, 0);
@ -145,7 +145,7 @@ struct WgPipelineBlend: public WgComputePipeline
struct WgPipelineCompose: public WgComputePipeline struct WgPipelineCompose: public WgComputePipeline
{ {
void initialize(WGPUDevice device) override; void initialize(WGPUDevice device) override;
void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorage& groupTexSrc, WgBindGroupTextureStorage& groupTexMsk, WgBindGroupCompositeMethod& groupComposeMethod, WgBindGroupOpacity& groupOpacity) void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorageRgba& groupTexSrc, WgBindGroupTextureStorageRgba& groupTexMsk, WgBindGroupCompositeMethod& groupComposeMethod, WgBindGroupOpacity& groupOpacity)
{ {
set(encoder); set(encoder);
groupTexSrc.set(encoder, 0); groupTexSrc.set(encoder, 0);
@ -173,7 +173,7 @@ struct WgPipelineComposeBlend: public WgComputePipeline
struct WgPipelineAntiAliasing: public WgComputePipeline struct WgPipelineAntiAliasing: public WgComputePipeline
{ {
void initialize(WGPUDevice device) override; void initialize(WGPUDevice device) override;
void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorage& groupTexSrc, WgBindGroupTextureStorage& groupTexDst) void use(WGPUComputePassEncoder encoder, WgBindGroupTextureStorageRgba& groupTexSrc, WgBindGroupTextureStorageBgra& groupTexDst)
{ {
set(encoder); set(encoder);
groupTexSrc.set(encoder, 0); groupTexSrc.set(encoder, 0);

View file

@ -26,7 +26,7 @@
// render storage // render storage
//***************************************************************************** //*****************************************************************************
void WgRenderStorage::initialize(WgContext& context, uint32_t w, uint32_t h, uint32_t samples) void WgRenderStorage::initialize(WgContext& context, uint32_t w, uint32_t h, uint32_t samples, WGPUTextureFormat format)
{ {
release(context); release(context);
// store target storage size // store target storage size
@ -41,8 +41,7 @@
WGPUTextureUsage_TextureBinding | WGPUTextureUsage_TextureBinding |
WGPUTextureUsage_StorageBinding | WGPUTextureUsage_StorageBinding |
WGPUTextureUsage_RenderAttachment, WGPUTextureUsage_RenderAttachment,
WGPUTextureFormat_BGRA8Unorm, format, width, height, "The target texture color");
width, height, "The target texture color");
texStencil = context.createTexture2d( texStencil = context.createTexture2d(
WGPUTextureUsage_RenderAttachment, WGPUTextureUsage_RenderAttachment,
WGPUTextureFormat_Stencil8, WGPUTextureFormat_Stencil8,
@ -54,7 +53,10 @@
assert(texViewColor); assert(texViewColor);
assert(texViewStencil); assert(texViewStencil);
// initialize bind group for blitting // initialize bind group for blitting
bindGroupTexStorage.initialize(context.device, context.queue, texViewColor); if (format == WGPUTextureFormat_RGBA8Unorm)
bindGroupTexStorageRgba.initialize(context.device, context.queue, texViewColor);
if (format == WGPUTextureFormat_BGRA8Unorm)
bindGroupTexStorageBgra.initialize(context.device, context.queue, texViewColor);
// initialize window binding groups // initialize window binding groups
WgShaderTypeMat4x4f viewMat(w, h); WgShaderTypeMat4x4f viewMat(w, h);
mBindGroupCanvas.initialize(context.device, context.queue, viewMat); mBindGroupCanvas.initialize(context.device, context.queue, viewMat);
@ -66,7 +68,7 @@ void WgRenderStorage::release(WgContext& context)
{ {
mRenderPassEncoder = nullptr; mRenderPassEncoder = nullptr;
mBindGroupCanvas.release(); mBindGroupCanvas.release();
bindGroupTexStorage.release(); bindGroupTexStorageRgba.release();
context.releaseTextureView(texViewStencil); context.releaseTextureView(texViewStencil);
context.releaseTextureView(texViewColor); context.releaseTextureView(texViewColor);
context.releaseTexture(texStencil); context.releaseTexture(texStencil);
@ -187,7 +189,7 @@ void WgRenderStorage::clear(WGPUCommandEncoder commandEncoder)
{ {
assert(commandEncoder); assert(commandEncoder);
WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder); WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder);
mPipelines->computeClear.use(computePassEncoder, bindGroupTexStorage); mPipelines->computeClear.use(computePassEncoder, bindGroupTexStorageRgba);
dispatchWorkgroups(computePassEncoder); dispatchWorkgroups(computePassEncoder);
endComputePass(computePassEncoder); endComputePass(computePassEncoder);
} }
@ -198,7 +200,7 @@ void WgRenderStorage::blend(WGPUCommandEncoder commandEncoder, WgRenderStorage*
assert(commandEncoder); assert(commandEncoder);
assert(targetSrc); assert(targetSrc);
WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder); WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder);
mPipelines->computeBlend.use(computePassEncoder, targetSrc->bindGroupTexStorage, bindGroupTexStorage, *blendMethod); mPipelines->computeBlend.use(computePassEncoder, targetSrc->bindGroupTexStorageRgba, bindGroupTexStorageRgba, *blendMethod);
dispatchWorkgroups(computePassEncoder); dispatchWorkgroups(computePassEncoder);
endComputePass(computePassEncoder); endComputePass(computePassEncoder);
}; };
@ -209,7 +211,7 @@ void WgRenderStorage::compose(WGPUCommandEncoder commandEncoder, WgRenderStorage
assert(commandEncoder); assert(commandEncoder);
assert(targetMsk); assert(targetMsk);
WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder); WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder);
mPipelines->computeCompose.use(computePassEncoder, bindGroupTexStorage, targetMsk->bindGroupTexStorage, *composeMethod, *opacity); mPipelines->computeCompose.use(computePassEncoder, bindGroupTexStorageRgba, targetMsk->bindGroupTexStorageRgba, *composeMethod, *opacity);
dispatchWorkgroups(computePassEncoder); dispatchWorkgroups(computePassEncoder);
endComputePass(computePassEncoder); endComputePass(computePassEncoder);
}; };
@ -242,7 +244,7 @@ void WgRenderStorage::antialias(WGPUCommandEncoder commandEncoder, WgRenderStora
assert(commandEncoder); assert(commandEncoder);
assert(targetSrc); assert(targetSrc);
WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder); WGPUComputePassEncoder computePassEncoder = beginComputePass(commandEncoder);
mPipelines->computeAntiAliasing.use(computePassEncoder, targetSrc->bindGroupTexStorage, bindGroupTexStorage); mPipelines->computeAntiAliasing.use(computePassEncoder, targetSrc->bindGroupTexStorageRgba, bindGroupTexStorageBgra);
dispatchWorkgroups(computePassEncoder); dispatchWorkgroups(computePassEncoder);
endComputePass(computePassEncoder); endComputePass(computePassEncoder);
} }

View file

@ -36,13 +36,14 @@ public:
WGPUTexture texStencil{}; WGPUTexture texStencil{};
WGPUTextureView texViewColor{}; WGPUTextureView texViewColor{};
WGPUTextureView texViewStencil{}; WGPUTextureView texViewStencil{};
WgBindGroupTextureStorage bindGroupTexStorage; WgBindGroupTextureStorageRgba bindGroupTexStorageRgba;
WgBindGroupTextureStorageBgra bindGroupTexStorageBgra;
uint32_t width{}; uint32_t width{};
uint32_t height{}; uint32_t height{};
uint32_t workgroupsCountX{}; uint32_t workgroupsCountX{};
uint32_t workgroupsCountY{}; uint32_t workgroupsCountY{};
public: public:
void initialize(WgContext& context, uint32_t w, uint32_t h, uint32_t samples = 1); void initialize(WgContext& context, uint32_t w, uint32_t h, uint32_t samples = 1, WGPUTextureFormat format = WGPUTextureFormat_RGBA8Unorm);
void release(WgContext& context); void release(WgContext& context);
void beginRenderPass(WGPUCommandEncoder commandEncoder, bool clear); void beginRenderPass(WGPUCommandEncoder commandEncoder, bool clear);

View file

@ -22,28 +22,22 @@
#include "tvgWgRenderer.h" #include "tvgWgRenderer.h"
#ifdef _WIN32
// TODO: cross-platform realization
#include <windows.h>
#endif
#define WG_SSAA_SAMPLES (2) #define WG_SSAA_SAMPLES (2)
WgRenderer::WgRenderer() WgRenderer::WgRenderer()
{ {
initialize();
} }
WgRenderer::~WgRenderer() WgRenderer::~WgRenderer()
{ {
release(); release();
mContext.release();
} }
void WgRenderer::initialize() void WgRenderer::initialize()
{ {
mContext.initialize();
mPipelines.initialize(mContext); mPipelines.initialize(mContext);
mOpacityPool.initialize(mContext); mOpacityPool.initialize(mContext);
mBlendMethodPool.initialize(mContext); mBlendMethodPool.initialize(mContext);
@ -70,10 +64,7 @@ void WgRenderer::release()
mRenderStorageRoot.release(mContext); mRenderStorageRoot.release(mContext);
mRenderStorageScreen.release(mContext); mRenderStorageScreen.release(mContext);
mRenderTarget.release(mContext); mRenderTarget.release(mContext);
wgpuSurfaceUnconfigure(mSurface);
wgpuSurfaceRelease(mSurface);
mPipelines.release(); mPipelines.release();
mContext.release();
} }
@ -274,7 +265,7 @@ bool WgRenderer::clear()
bool WgRenderer::sync() bool WgRenderer::sync()
{ {
WGPUSurfaceTexture backBuffer{}; WGPUSurfaceTexture backBuffer{};
wgpuSurfaceGetCurrentTexture(mSurface, &backBuffer); wgpuSurfaceGetCurrentTexture(mContext.surface, &backBuffer);
WGPUCommandEncoderDescriptor commandEncoderDesc{}; WGPUCommandEncoderDescriptor commandEncoderDesc{};
commandEncoderDesc.nextInChain = nullptr; commandEncoderDesc.nextInChain = nullptr;
@ -296,7 +287,7 @@ bool WgRenderer::sync()
mContext.executeCommandEncoder(commandEncoder); mContext.executeCommandEncoder(commandEncoder);
wgpuCommandEncoderRelease(commandEncoder); wgpuCommandEncoderRelease(commandEncoder);
wgpuSurfacePresent(mSurface); wgpuSurfacePresent(mContext.surface);
return true; return true;
} }
@ -314,25 +305,16 @@ bool WgRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
// target for native window handle // target for native window handle
bool WgRenderer::target(void* window, uint32_t w, uint32_t h) bool WgRenderer::target(WGPUInstance instance, WGPUSurface surface, uint32_t w, uint32_t h)
{ {
// store target surface properties // store target surface properties
mTargetSurface.stride = w; mTargetSurface.stride = w;
mTargetSurface.w = w > 0 ? w : 1; mTargetSurface.w = w > 0 ? w : 1;
mTargetSurface.h = h > 0 ? h : 1; mTargetSurface.h = h > 0 ? h : 1;
// surface descriptor from windows hwnd mContext.initialize(instance, surface);
WGPUSurfaceDescriptorFromWindowsHWND surfaceDescHwnd{};
surfaceDescHwnd.chain.next = nullptr;
surfaceDescHwnd.chain.sType = WGPUSType_SurfaceDescriptorFromWindowsHWND;
surfaceDescHwnd.hinstance = GetModuleHandle(NULL);
surfaceDescHwnd.hwnd = (HWND)window;
WGPUSurfaceDescriptor surfaceDesc{};
surfaceDesc.nextInChain = (const WGPUChainedStruct*)&surfaceDescHwnd;
surfaceDesc.label = "The surface";
mSurface = wgpuInstanceCreateSurface(mContext.instance, &surfaceDesc);
assert(mSurface);
// configure surface
WGPUSurfaceConfiguration surfaceConfiguration{}; WGPUSurfaceConfiguration surfaceConfiguration{};
surfaceConfiguration.nextInChain = nullptr; surfaceConfiguration.nextInChain = nullptr;
surfaceConfiguration.device = mContext.device; surfaceConfiguration.device = mContext.device;
@ -341,14 +323,15 @@ bool WgRenderer::target(void* window, uint32_t w, uint32_t h)
surfaceConfiguration.viewFormatCount = 0; surfaceConfiguration.viewFormatCount = 0;
surfaceConfiguration.viewFormats = nullptr; surfaceConfiguration.viewFormats = nullptr;
surfaceConfiguration.alphaMode = WGPUCompositeAlphaMode_Auto; surfaceConfiguration.alphaMode = WGPUCompositeAlphaMode_Auto;
surfaceConfiguration.width = mTargetSurface.w; surfaceConfiguration.width = w;
surfaceConfiguration.height = mTargetSurface.h; surfaceConfiguration.height = h;
surfaceConfiguration.presentMode = WGPUPresentMode_Mailbox; surfaceConfiguration.presentMode = WGPUPresentMode_Immediate;
wgpuSurfaceConfigure(mSurface, &surfaceConfiguration); wgpuSurfaceConfigure(mContext.surface, &surfaceConfiguration);
initialize();
mRenderTarget.initialize(mContext, w, h, WG_SSAA_SAMPLES); mRenderTarget.initialize(mContext, w, h, WG_SSAA_SAMPLES);
mRenderStorageRoot.initialize(mContext, w, h, WG_SSAA_SAMPLES); mRenderStorageRoot.initialize(mContext, w, h, WG_SSAA_SAMPLES);
mRenderStorageScreen.initialize(mContext, w, h); mRenderStorageScreen.initialize(mContext, w, h, 1, WGPUTextureFormat_BGRA8Unorm);
return true; return true;
} }

View file

@ -52,7 +52,7 @@ public:
bool sync() override; bool sync() override;
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h); bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
bool target(void* window, uint32_t w, uint32_t h); // temporary solution bool target(WGPUInstance instance, WGPUSurface surface, uint32_t w, uint32_t h);
Compositor* target(const RenderRegion& region, ColorSpace cs) override; Compositor* target(const RenderRegion& region, ColorSpace cs) override;
bool beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity) override; bool beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity) override;
@ -78,7 +78,6 @@ private:
Array<WgRenderStorage*> mRenderStorageStack; Array<WgRenderStorage*> mRenderStorageStack;
// native window handles // native window handles
WGPUSurface mSurface{};
WgContext mContext; WgContext mContext;
WgPipelines mPipelines; WgPipelines mPipelines;
Surface mTargetSurface; Surface mTargetSurface;

View file

@ -365,7 +365,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f {
// pipeline shader modules clear // pipeline shader modules clear
const char* cShaderSource_PipelineComputeClear = R"( const char* cShaderSource_PipelineComputeClear = R"(
@group(0) @binding(0) var imageDst : texture_storage_2d<bgra8unorm, read_write>; @group(0) @binding(0) var imageDst : texture_storage_2d<rgba8unorm, read_write>;
@compute @workgroup_size(8, 8) @compute @workgroup_size(8, 8)
fn cs_main( @builtin(global_invocation_id) id: vec3u) { fn cs_main( @builtin(global_invocation_id) id: vec3u) {
@ -376,8 +376,8 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) {
// pipeline shader modules blend // pipeline shader modules blend
const char* cShaderSource_PipelineComputeBlend = R"( const char* cShaderSource_PipelineComputeBlend = R"(
@group(0) @binding(0) var imageSrc : texture_storage_2d<bgra8unorm, read_write>; @group(0) @binding(0) var imageSrc : texture_storage_2d<rgba8unorm, read_write>;
@group(1) @binding(0) var imageDst : texture_storage_2d<bgra8unorm, read_write>; @group(1) @binding(0) var imageDst : texture_storage_2d<rgba8unorm, read_write>;
@group(2) @binding(0) var<uniform> blendMethod : u32; @group(2) @binding(0) var<uniform> blendMethod : u32;
@compute @workgroup_size(8, 8) @compute @workgroup_size(8, 8)
@ -420,8 +420,8 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) {
// pipeline shader modules compose // pipeline shader modules compose
const char* cShaderSource_PipelineComputeCompose = R"( const char* cShaderSource_PipelineComputeCompose = R"(
@group(0) @binding(0) var imageSrc : texture_storage_2d<bgra8unorm, read_write>; @group(0) @binding(0) var imageSrc : texture_storage_2d<rgba8unorm, read_write>;
@group(1) @binding(0) var imageMsk : texture_storage_2d<bgra8unorm, read_write>; @group(1) @binding(0) var imageMsk : texture_storage_2d<rgba8unorm, read_write>;
@group(2) @binding(0) var<uniform> composeMethod : u32; @group(2) @binding(0) var<uniform> composeMethod : u32;
@group(3) @binding(0) var<uniform> opacity : f32; @group(3) @binding(0) var<uniform> opacity : f32;
@ -455,9 +455,9 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) {
// pipeline shader modules compose blend // pipeline shader modules compose blend
const char* cShaderSource_PipelineComputeComposeBlend = R"( const char* cShaderSource_PipelineComputeComposeBlend = R"(
@group(0) @binding(0) var imageSrc : texture_storage_2d<bgra8unorm, read>; @group(0) @binding(0) var imageSrc : texture_storage_2d<rgba8unorm, read>;
@group(0) @binding(1) var imageMsk : texture_storage_2d<bgra8unorm, read>; @group(0) @binding(1) var imageMsk : texture_storage_2d<rgba8unorm, read>;
@group(0) @binding(2) var imageDst : texture_storage_2d<bgra8unorm, read_write>; @group(0) @binding(2) var imageDst : texture_storage_2d<rgba8unorm, read_write>;
@group(1) @binding(0) var<uniform> composeMethod : u32; @group(1) @binding(0) var<uniform> composeMethod : u32;
@group(2) @binding(0) var<uniform> blendMethod : u32; @group(2) @binding(0) var<uniform> blendMethod : u32;
@group(3) @binding(0) var<uniform> opacity : f32; @group(3) @binding(0) var<uniform> opacity : f32;
@ -517,8 +517,8 @@ fn cs_main( @builtin(global_invocation_id) id: vec3u) {
// pipeline shader modules anti-aliasing // pipeline shader modules anti-aliasing
const char* cShaderSource_PipelineComputeAntiAlias = R"( const char* cShaderSource_PipelineComputeAntiAlias = R"(
@group(0) @binding(0) var imageSrc : texture_storage_2d<bgra8unorm, read_write>; @group(0) @binding(0) var imageSrc : texture_storage_2d<rgba8unorm, read_write>;
@group(1) @binding(0) var imageDst : texture_storage_2d<bgra8unorm, read_write>; @group(1) @binding(0) var imageDst : texture_storage_2d<bgra8unorm, write>;
@compute @workgroup_size(8, 8) @compute @workgroup_size(8, 8)
fn cs_main( @builtin(global_invocation_id) id: vec3u) { fn cs_main( @builtin(global_invocation_id) id: vec3u) {