diff --git a/native/cocos/renderer/gfx-agent/DescriptorSetAgent.cpp b/native/cocos/renderer/gfx-agent/DescriptorSetAgent.cpp index b4df711e628..620cc9def43 100644 --- a/native/cocos/renderer/gfx-agent/DescriptorSetAgent.cpp +++ b/native/cocos/renderer/gfx-agent/DescriptorSetAgent.cpp @@ -98,16 +98,17 @@ void DescriptorSetAgent::forceUpdate() { }); } -void DescriptorSetAgent::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index) { +void DescriptorSetAgent::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags) { DescriptorSet::bindBuffer(binding, buffer, index); - ENQUEUE_MESSAGE_4( + ENQUEUE_MESSAGE_5( DeviceAgent::getInstance()->getMessageQueue(), DescriptorSetBindBuffer, actor, getActor(), binding, binding, buffer, static_cast(buffer)->getActor(), index, index, + flags, flags, { actor->bindBuffer(binding, buffer, index); }); diff --git a/native/cocos/renderer/gfx-agent/DescriptorSetAgent.h b/native/cocos/renderer/gfx-agent/DescriptorSetAgent.h index a89eaaa09e7..d4290ea0cf3 100644 --- a/native/cocos/renderer/gfx-agent/DescriptorSetAgent.h +++ b/native/cocos/renderer/gfx-agent/DescriptorSetAgent.h @@ -38,7 +38,7 @@ class CC_DLL DescriptorSetAgent final : public Agent { void update() override; void forceUpdate() override; - void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index) override; + void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags) override; void bindTexture(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags) override; void bindSampler(uint32_t binding, Sampler *sampler, uint32_t index) override; diff --git a/native/cocos/renderer/gfx-base/GFXDescriptorSet.cpp b/native/cocos/renderer/gfx-base/GFXDescriptorSet.cpp index 242886cb173..a2000ebd88d 100644 --- a/native/cocos/renderer/gfx-base/GFXDescriptorSet.cpp +++ b/native/cocos/renderer/gfx-base/GFXDescriptorSet.cpp @@ -61,13 +61,7 @@ void DescriptorSet::destroy() { } void DescriptorSet::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index) { - const uint32_t descriptorIndex = _layout->getDescriptorIndices()[binding] + index; - const uint32_t newId = getObjectID(buffer); - if (_buffers[descriptorIndex].id != newId) { - _buffers[descriptorIndex].ptr = buffer; - _buffers[descriptorIndex].id = newId; - _isDirty = true; - } + bindBuffer(binding, buffer, index, AccessFlagBit::NONE); } void DescriptorSet::bindTexture(uint32_t binding, Texture *texture, uint32_t index) { @@ -85,6 +79,17 @@ void DescriptorSet::bindTexture(uint32_t binding, Texture *texture, uint32_t ind } } +void DescriptorSet::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags) { + const uint32_t descriptorIndex = _layout->getDescriptorIndices()[binding] + index; + const uint32_t newId = getObjectID(buffer); + if (_buffers[descriptorIndex].id != newId) { + _buffers[descriptorIndex].ptr = buffer; + _buffers[descriptorIndex].id = newId; + _buffers[descriptorIndex].flags = flags; + _isDirty = true; + } +} + void DescriptorSet::bindSampler(uint32_t binding, Sampler *sampler, uint32_t index) { const uint32_t descriptorIndex = _layout->getDescriptorIndices()[binding] + index; const uint32_t newId = getObjectID(sampler); diff --git a/native/cocos/renderer/gfx-base/GFXDescriptorSet.h b/native/cocos/renderer/gfx-base/GFXDescriptorSet.h index cb0b6897d02..fcebdc86616 100644 --- a/native/cocos/renderer/gfx-base/GFXDescriptorSet.h +++ b/native/cocos/renderer/gfx-base/GFXDescriptorSet.h @@ -41,10 +41,11 @@ class CC_DLL DescriptorSet : public GFXObject, public RefCounted { virtual void update() = 0; virtual void forceUpdate() = 0; - virtual void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index); + virtual void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags); virtual void bindSampler(uint32_t binding, Sampler *sampler, uint32_t index); virtual void bindTexture(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags); + void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index); void bindTexture(uint32_t binding, Texture *texture, uint32_t index); // Functions invoked by JSB adapter diff --git a/native/cocos/renderer/gfx-validator/DescriptorSetValidator.cpp b/native/cocos/renderer/gfx-validator/DescriptorSetValidator.cpp index b487e9262b3..d9d15e85823 100644 --- a/native/cocos/renderer/gfx-validator/DescriptorSetValidator.cpp +++ b/native/cocos/renderer/gfx-validator/DescriptorSetValidator.cpp @@ -113,7 +113,7 @@ void DescriptorSetValidator::updateReferenceStamp() { _referenceStamp = DeviceValidator::getInstance()->currentFrame(); } -void DescriptorSetValidator::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index) { +void DescriptorSetValidator::bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags) { CC_ASSERT(isInited()); auto *vBuffer = static_cast(buffer); CC_ASSERT(buffer && vBuffer->isInited()); @@ -139,9 +139,9 @@ void DescriptorSetValidator::bindBuffer(uint32_t binding, Buffer *buffer, uint32 /////////// execute /////////// - DescriptorSet::bindBuffer(binding, buffer, index); + DescriptorSet::bindBuffer(binding, buffer, index, flags); - _actor->bindBuffer(binding, vBuffer->getActor(), index); + _actor->bindBuffer(binding, vBuffer->getActor(), index, flags); } void DescriptorSetValidator::bindTexture(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags) { diff --git a/native/cocos/renderer/gfx-validator/DescriptorSetValidator.h b/native/cocos/renderer/gfx-validator/DescriptorSetValidator.h index 95e14838c67..020ad418980 100644 --- a/native/cocos/renderer/gfx-validator/DescriptorSetValidator.h +++ b/native/cocos/renderer/gfx-validator/DescriptorSetValidator.h @@ -38,7 +38,7 @@ class CC_DLL DescriptorSetValidator final : public Agent { void update() override; void forceUpdate() override; - void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index) override; + void bindBuffer(uint32_t binding, Buffer *buffer, uint32_t index, AccessFlags flags) override; void bindTexture(uint32_t binding, Texture *texture, uint32_t index, AccessFlags flags) override; void bindSampler(uint32_t binding, Sampler *sampler, uint32_t index) override; diff --git a/native/cocos/renderer/gfx-wgpu/CMakeLists.txt b/native/cocos/renderer/gfx-wgpu/CMakeLists.txt index 8083028fb4b..2881f3643cd 100644 --- a/native/cocos/renderer/gfx-wgpu/CMakeLists.txt +++ b/native/cocos/renderer/gfx-wgpu/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.8) set(APP_NAME "webgpu" CACHE STRING "Project Name") project(${APP_NAME}_wasm) +message(${CMAKE_BUILD_TYPE}) if (NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) endif() @@ -11,11 +12,13 @@ set(ENGINE_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..) include(${ENGINE_ROOT_DIR}/cmake/predefine.cmake) -# include (${ENGINE_ROOT_DIR}/external/CMakeLists.txt) +include (${ENGINE_ROOT_DIR}/external/CMakeLists.txt) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wextra -Wno-nonportable-include-path -fno-exceptions -v") -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -g3 -D_DEBUG=1 -Wno-unused -O0 -std=c++17") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w -DNDEBUG=1 -O3 -std=c++17") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wextra -Wno-nonportable-include-path -fno-exceptions -v -D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES=D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -g3 -D_DEBUG=1 -Wno-unused -O0 -std=c++17 -D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w -DNDEBUG=1 -O3 -std=c++17 -D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES") + +message(${CMAKE_BUILD_TYPE}) AUX_SOURCE_DIRECTORY( ./states @@ -100,7 +103,7 @@ AUX_SOURCE_DIRECTORY( add_executable(${APP_NAME}_wasm ${WASM_EXPORTS} ${NATIVE_SRC}) target_include_directories( - ${APP_NAME}_wasm PRIVATE "${CMAKE_CURRENT_LIST_DIR}/inc" + ${APP_NAME}_wasm PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include" ${CC_EXTERNAL_INCLUDES} ${CMAKE_CURRENT_LIST_DIR} ${ENGINE_ROOT_DIR} @@ -122,4 +125,10 @@ set(EMS_LINK_FLAGS "-flto --bind --no-entry -O3 -s USE_ES6_IMPORT_META=0 -s EXPORT_ES6=1 -s MODULARIZE=1 -s EXPORT_NAME='wasmDevice' -s ENVIRONMENT=web -s WASM=1 -s USE_WEBGPU=1 -s NO_EXIT_RUNTIME=1 -s LLD_REPORT_UNDEFINED -s ALLOW_MEMORY_GROWTH=1" ) +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + string(APPEND EMS_LINK_FLAGS " -s ASSERTIONS=2") +endif() + +set_target_properties(${APP_NAME}_wasm PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ENGINE_ROOT_DIR}/external/emscripten/webgpu) + set_target_properties(${APP_NAME}_wasm PROPERTIES CXX_STANDARD 17 LINK_FLAGS ${EMS_LINK_FLAGS}) diff --git a/native/cocos/renderer/gfx-wgpu/WGPUBuffer.cpp b/native/cocos/renderer/gfx-wgpu/WGPUBuffer.cpp index 84f335b34de..03cd9d69bde 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUBuffer.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUBuffer.cpp @@ -27,6 +27,7 @@ #include "WGPUDevice.h" #include "WGPUObject.h" #include "WGPUUtils.h" +#include namespace cc { namespace gfx { @@ -34,6 +35,7 @@ namespace gfx { namespace { CCWGPUBuffer *dftUniformBuffer = nullptr; CCWGPUBuffer *dftStorageBuffer = nullptr; +static uint32_t BUFFER_ALIGNMENT = 16; } // namespace using namespace emscripten; @@ -54,7 +56,7 @@ void CCWGPUBuffer::doInit(const BufferInfo &info) { _gpuBufferObject->indirectObjs.resize(drawInfoCount); } - _size = ceil(info.size / 4.0) * 4; + _size = boost::alignment::align_up(_size, BUFFER_ALIGNMENT); WGPUBufferDescriptor descriptor = { .nextInChain = nullptr, @@ -113,7 +115,7 @@ void CCWGPUBuffer::doResize(uint32_t size, uint32_t count) { _gpuBufferObject->indirectObjs.resize(drawInfoCount); } - _size = ceil(size / 4.0) * 4; + _size = boost::alignment::align_up(size, BUFFER_ALIGNMENT); WGPUBufferDescriptor descriptor = { .nextInChain = nullptr, @@ -172,7 +174,7 @@ void CCWGPUBuffer::update(const void *buffer, uint32_t size) { update(drawInfo, drawInfoCount); } else { size_t offset = _isBufferView ? _offset : 0; - uint32_t alignedSize = ceil(size / 4.0) * 4; + uint32_t alignedSize = boost::alignment::align_up(size, BUFFER_ALIGNMENT); size_t buffSize = alignedSize; wgpuQueueWriteBuffer(CCWGPUDevice::getInstance()->gpuDeviceObject()->wgpuQueue, _gpuBufferObject->wgpuBuffer, offset, buffer, buffSize); } diff --git a/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.cpp b/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.cpp index 1900ad1e405..2100682ad86 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.cpp @@ -25,6 +25,7 @@ #include "WGPUCommandBuffer.h" #include #include +#include #include "WGPUBuffer.h" #include "WGPUDescriptorSet.h" #include "WGPUDescriptorSetLayout.h" @@ -55,7 +56,7 @@ CCWGPUCommandBuffer::~CCWGPUCommandBuffer() { doDestroy(); } void CCWGPUCommandBuffer::doInit(const CommandBufferInfo &info) { - _gpuCommandBufferObj = ccnew CCWGPUCommandBufferObject; + _gpuCommandBufferObj = ccnew CCWGPUCommandBufferObject{}; _gpuCommandBufferObj->type = info.type; _gpuCommandBufferObj->queue = static_cast(info.queue); _gpuCommandBufferObj->stateCache.descriptorSets.resize(4); //(info.queue->getDevice()->getMaxDescriptorSetLayoutBindings()); @@ -77,8 +78,6 @@ void CCWGPUCommandBuffer::doDestroy() { } void CCWGPUCommandBuffer::begin(RenderPass * /*renderPass*/, uint32_t /*subpass*/, Framebuffer * /*frameBuffer*/) { - // TODO_Zeqiang: subpass support - // printf("begin\n"); reset(); _numTriangles = 0; @@ -93,19 +92,7 @@ void CCWGPUCommandBuffer::begin(RenderPass * /*renderPass*/, uint32_t /*subpass* void CCWGPUCommandBuffer::end() { auto *pipelineState = _gpuCommandBufferObj->stateCache.pipelineState; if (pipelineState) { - if (pipelineState->getBindPoint() == PipelineBindPoint::GRAPHICS) { - auto *queue = _gpuCommandBufferObj->queue; - _gpuCommandBufferObj->wgpuCommandBuffer = wgpuCommandEncoderFinish(_gpuCommandBufferObj->wgpuCommandEncoder, nullptr); - wgpuCommandEncoderRelease(_gpuCommandBufferObj->wgpuCommandEncoder); - _gpuCommandBufferObj->wgpuCommandEncoder = wgpuDefaultHandle; - } else { - wgpuComputePassEncoderEnd(_gpuCommandBufferObj->wgpuComputeEncoder); - wgpuComputePassEncoderRelease(_gpuCommandBufferObj->wgpuComputeEncoder); - _gpuCommandBufferObj->wgpuCommandBuffer = wgpuCommandEncoderFinish(_gpuCommandBufferObj->wgpuCommandEncoder, nullptr); - wgpuCommandEncoderRelease(_gpuCommandBufferObj->wgpuCommandEncoder); - _gpuCommandBufferObj->wgpuComputeEncoder = wgpuDefaultHandle; - _gpuCommandBufferObj->wgpuCommandEncoder = wgpuDefaultHandle; - } + _gpuCommandBufferObj->wgpuCommandBuffer = wgpuCommandEncoderFinish(_gpuCommandBufferObj->wgpuCommandEncoder, nullptr); } } @@ -170,7 +157,9 @@ void CCWGPUCommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *f } ccstd::vector depthStencils; - if (dsTexture) { + if(renderPass->getDepthStencilAttachment().format == Format::UNKNOWN) { + renderPassDesc.depthStencilAttachment = nullptr; + } else if(dsTexture) { WGPURenderPassDepthStencilAttachment depthStencil = { .view = static_cast(dsTexture)->gpuTextureObject()->selfView, .depthLoadOp = toWGPULoadOp(depthStencilConfig.depthLoadOp), @@ -184,10 +173,7 @@ void CCWGPUCommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *f }; depthStencils.emplace_back(depthStencil); } else { - if (depthStencilConfig.format == Format::UNKNOWN) { - renderPassDesc.depthStencilAttachment = nullptr; - } else { - WGPURenderPassDepthStencilAttachment depthStencil = { + WGPURenderPassDepthStencilAttachment depthStencil = { .view = swapchain->gpuSwapchainObject()->swapchainDepthStencil->gpuTextureObject()->selfView, .depthLoadOp = toWGPULoadOp(depthStencilConfig.depthLoadOp), .depthStoreOp = toWGPUStoreOp(depthStencilConfig.depthStoreOp), @@ -199,7 +185,6 @@ void CCWGPUCommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *f .stencilReadOnly = false, }; depthStencils.emplace_back(depthStencil); - } } setViewport({renderArea.x, renderArea.y, renderArea.width, renderArea.height, 0.0F, 1.0F}); @@ -225,7 +210,6 @@ void CCWGPUCommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *f } // namespace gfx void CCWGPUCommandBuffer::endRenderPass() { - // printf("endr\n"); wgpuRenderPassEncoderEnd(_gpuCommandBufferObj->wgpuRenderPassEncoder); wgpuRenderPassEncoderRelease(_gpuCommandBufferObj->wgpuRenderPassEncoder); _gpuCommandBufferObj->wgpuRenderPassEncoder = wgpuDefaultHandle; @@ -322,7 +306,6 @@ void CCWGPUCommandBuffer::bindStates() { if (!pipelineState) { return; } - ccstd::set setInUse; auto *pipelineLayout = static_cast(pipelineState->layout()); @@ -334,14 +317,28 @@ void CCWGPUCommandBuffer::bindStates() { const auto &descriptorSets = _gpuCommandBufferObj->stateCache.descriptorSets; for (size_t i = 0; i < setLayouts.size(); i++) { if (descriptorSets[i].descriptorSet) { + // optional: prune descriptor set for redundant resources + { + auto *ccShader = static_cast(pipelineState->getShader()); + const auto &bindingInshader = ccShader->gpuShaderObject()->bindings; + if (bindingInshader.size() > i) { + descriptorSets[i].descriptorSet->prune(bindingInshader[i]); + } else { + descriptorSets[i].descriptorSet->prune({}); + } + descriptorSets[i].descriptorSet->forceUpdate(); + } + descriptorSets[i].descriptorSet->prepare(); if (descriptorSets[i].descriptorSet->dynamicOffsetCount() != descriptorSets[i].dynamicOffsetCount) { + std::string str = "force " + std::to_string(i); + wgpuRenderPassEncoderSetLabel(_gpuCommandBufferObj->wgpuRenderPassEncoder, str.c_str()); uint32_t *dynOffsets = dynamicOffsetBuffer; - const Pairs &dynamicOffsets = descriptorSets[i].descriptorSet->dynamicOffsets(); + const auto &dynamicOffsets = descriptorSets[i].descriptorSet->dynamicOffsets(); uint32_t givenOffsetIndex = 0; for (size_t j = 0; j < descriptorSets[i].descriptorSet->dynamicOffsetCount(); ++j) { - if (j >= descriptorSets[i].dynamicOffsetCount || dynamicOffsets[j].second == 0) { + if (j >= descriptorSets[i].dynamicOffsetCount) { dynOffsets[j] = 0; } else { dynOffsets[j] = descriptorSets[i].dynamicOffsets[givenOffsetIndex++]; @@ -352,11 +349,9 @@ void CCWGPUCommandBuffer::bindStates() { descriptorSets[i].descriptorSet->gpuBindGroupObject()->bindgroup, descriptorSets[i].descriptorSet->dynamicOffsetCount(), dynOffsets); - setInUse.insert(i); - if (setLayouts[i] != descriptorSets[i].descriptorSet->getLayout()) { - pipelineLayoutChanged = true; - } } else { + std::string str = "same " + std::to_string(i); + wgpuRenderPassEncoderSetLabel(_gpuCommandBufferObj->wgpuRenderPassEncoder, str.c_str()); wgpuRenderPassEncoderSetBindGroup(_gpuCommandBufferObj->wgpuRenderPassEncoder, i, descriptorSets[i].descriptorSet->gpuBindGroupObject()->bindgroup, @@ -364,32 +359,26 @@ void CCWGPUCommandBuffer::bindStates() { descriptorSets[i].dynamicOffsets); } setInUse.insert(i); + pipelineLayoutChanged |= (setLayouts[i] != descriptorSets[i].descriptorSet->getLayout()); } else { // missing + std::string str = "missing " + std::to_string(i); + wgpuRenderPassEncoderSetLabel(_gpuCommandBufferObj->wgpuRenderPassEncoder, str.c_str()); wgpuRenderPassEncoderSetBindGroup(_gpuCommandBufferObj->wgpuRenderPassEncoder, i, static_cast(CCWGPUDescriptorSet::defaultBindGroup()), 0, nullptr); + pipelineLayoutChanged = true; } } - for (size_t i = 0; i < setLayouts.size(); i++) { - if (setInUse.find(i) == setInUse.end()) { - wgpuRenderPassEncoderSetBindGroup(_gpuCommandBufferObj->wgpuRenderPassEncoder, - i, - static_cast(CCWGPUDescriptorSet::defaultBindGroup()), - 0, - nullptr); - } - } - - if (1) { + if (pipelineLayoutChanged && setLayouts.size()) { ccstd::vector dsSets; for (size_t i = 0; i < setLayouts.size(); i++) { dsSets.push_back(descriptorSets[i].descriptorSet); } - createPipelineLayoutFallback(dsSets, pipelineLayout); + createPipelineLayoutFallback(dsSets, pipelineLayout, false); } else { pipelineLayout->prepare(setInUse); } @@ -444,6 +433,7 @@ void CCWGPUCommandBuffer::bindStates() { #endif const auto *indexBuffer = static_cast(ia->getIndexBuffer()); if (indexBuffer) { + CC_ASSERT(indexBuffer->getStride() >= 2); wgpuRenderPassEncoderSetIndexBuffer(_gpuCommandBufferObj->wgpuRenderPassEncoder, indexBuffer->gpuBufferObject()->wgpuBuffer, indexBuffer->getStride() == 2 ? WGPUIndexFormat::WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, @@ -487,17 +477,45 @@ void CCWGPUCommandBuffer::bindStates() { wgpuRenderPassEncoderSetStencilReference(_gpuCommandBufferObj->wgpuRenderPassEncoder, pipelineState->getDepthStencilState().stencilRefFront); } else if (pipelineState->getBindPoint() == PipelineBindPoint::COMPUTE) { auto *pipelineState = _gpuCommandBufferObj->stateCache.pipelineState; - + const auto &setLayouts = pipelineLayout->getSetLayouts(); // bindgroup & descriptorset const auto &descriptorSets = _gpuCommandBufferObj->stateCache.descriptorSets; + bool pipelineLayoutChanged = false; for (size_t i = 0; i < descriptorSets.size(); i++) { - if (descriptorSets[i].descriptorSet->gpuBindGroupObject()->bindgroup) { + if (descriptorSets[i].descriptorSet) { + // optional: prune descriptor set for redundant resources + { + auto *ccShader = static_cast(pipelineState->getShader()); + const auto &bindingInshader = ccShader->gpuShaderObject()->bindings; + if (bindingInshader.size() > i) { + descriptorSets[i].descriptorSet->prune(bindingInshader[i]); + } else { + descriptorSets[i].descriptorSet->prune({}); + } + descriptorSets[i].descriptorSet->forceUpdate(); + } + + descriptorSets[i].descriptorSet->prepare(); wgpuComputePassEncoderSetBindGroup(_gpuCommandBufferObj->wgpuComputeEncoder, i, descriptorSets[i].descriptorSet->gpuBindGroupObject()->bindgroup, descriptorSets[i].dynamicOffsetCount, descriptorSets[i].dynamicOffsets); + pipelineLayoutChanged |= (setLayouts[i] != descriptorSets[i].descriptorSet->getLayout()); + setInUse.insert(i); + } else { + pipelineLayoutChanged = true; + } + } + + if (pipelineLayoutChanged && setLayouts.size()) { + ccstd::vector dsSets; + for (size_t i = 0; i < setLayouts.size(); i++) { + dsSets.push_back(descriptorSets[i].descriptorSet); } + createPipelineLayoutFallback(dsSets, pipelineLayout, true); + } else { + pipelineLayout->prepare(setInUse); } pipelineState->prepare(setInUse); @@ -777,6 +795,10 @@ void CCWGPUCommandBuffer::copyBuffersToTexture(const uint8_t *const *buffers, Te } } +void CCWGPUCommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) { + // blitTexture(srcTexture, dstTexture, regions, count, Filter::POINT); +} + void CCWGPUCommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { for (size_t i = 0; i < count; i++) { auto *srcTex = static_cast(srcTexture); @@ -824,9 +846,11 @@ void CCWGPUCommandBuffer::execute(CommandBuffer *const * /*cmdBuffs*/, uint32_t void CCWGPUCommandBuffer::dispatch(const DispatchInfo &info) { WGPUComputePassDescriptor cmoputeDesc = {}; - if (!_gpuCommandBufferObj->wgpuComputeEncoder) { - _gpuCommandBufferObj->wgpuComputeEncoder = wgpuCommandEncoderBeginComputePass(_gpuCommandBufferObj->wgpuCommandEncoder, &cmoputeDesc); - } + // if (!_gpuCommandBufferObj->wgpuComputeEncoder) { + _gpuCommandBufferObj->wgpuComputeEncoder = wgpuCommandEncoderBeginComputePass(_gpuCommandBufferObj->wgpuCommandEncoder, &cmoputeDesc); + // } + + bindStates(); if (info.indirectBuffer) { auto *indirectBuffer = static_cast(info.indirectBuffer); @@ -840,6 +864,8 @@ void CCWGPUCommandBuffer::dispatch(const DispatchInfo &info) { info.groupCountY, info.groupCountZ); } + wgpuComputePassEncoderEnd(_gpuCommandBufferObj->wgpuComputeEncoder); + wgpuComputePassEncoderRelease(_gpuCommandBufferObj->wgpuComputeEncoder); } void CCWGPUCommandBuffer::pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) { @@ -850,6 +876,7 @@ void CCWGPUCommandBuffer::reset() { _gpuCommandBufferObj->wgpuCommandEncoder = wgpuDefaultHandle; _gpuCommandBufferObj->wgpuRenderPassEncoder = wgpuDefaultHandle; _gpuCommandBufferObj->wgpuComputeEncoder = wgpuDefaultHandle; + _gpuCommandBufferObj->computeCmdBuffs.clear(); CCWGPUStateCache stateCache = {}; } diff --git a/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.h b/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.h index 345ba104f4c..d52ee6e23cd 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.h @@ -68,8 +68,10 @@ class CCWGPUCommandBuffer final : public CommandBuffer { void execute(CommandBuffer *const *cmdBuffs, uint32_t count) override; void dispatch(const DispatchInfo &info) override; void pipelineBarrier(const GeneralBarrier *barrier, const BufferBarrier *const *bufferBarriers, const Buffer *const *buffers, uint32_t bufferBarrierCount, const TextureBarrier *const *textureBarriers, const Texture *const *textures, uint32_t textureBarrierCount) override; + void copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override; void updateIndirectBuffer(Buffer *buff, const DrawInfoList &info); + void resolveTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) override{}; // TODO_Zeqiang: wgpu query pool void beginQuery(QueryPool *queryPool, uint32_t id) override{}; diff --git a/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSet.cpp b/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSet.cpp index ced80b79159..72a79fdca36 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSet.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSet.cpp @@ -65,107 +65,49 @@ void CCWGPUDescriptorSet::clearCache() { } void CCWGPUDescriptorSet::doInit(const DescriptorSetInfo &info) { - _gpuBindGroupObj = ccnew CCWGPUBindGroupObject; + _gpuBindGroupObj = ccnew CCWGPUBindGroupObject{}; + _gpuDescriptorObj = ccnew CCWGPUGPUDescriptorSetObject{}; - auto *dsLayout = static_cast(_layout); - CCWGPUBindGroupLayoutObject *layoutEntries = dsLayout->gpuLayoutEntryObject(); + auto *tLayout = const_cast(_layout); + auto *dsLayout = static_cast(tLayout); const auto &bindings = dsLayout->getBindings(); CCWGPUDeviceObject *deviceObj = CCWGPUDevice::getInstance()->gpuDeviceObject(); for (size_t i = 0; i < bindings.size(); i++) { // effect.ts: INPUT_ATTACHMENT as combined texture but no sampler_texture desc type. if (hasFlag(COMBINED_ST_IN_USE, bindings[i].descriptorType)) { - // 1. texture - CCWGPUTexture *texture = deviceObj->defaultResources.commonTexture; - WGPUBindGroupEntry texEntry = { - .binding = bindings[i].binding, - .textureView = texture->gpuTextureObject()->selfView, - }; - _gpuBindGroupObj->bindGroupEntries.push_back(texEntry); - _textureIdxMap.insert(std::make_pair(bindings[i].binding, _gpuBindGroupObj->bindGroupEntries.size() - 1)); - dsLayout->updateTextureLayout(texEntry.binding, texture); - - // 2. sampler - CCWGPUSampler *sampler = deviceObj->defaultResources.unfilterableSampler; - WGPUBindGroupEntry smpEntry = { - .binding = bindings[i].binding + CC_WGPU_MAX_ATTACHMENTS, - .sampler = sampler->gpuSampler(), - }; - _gpuBindGroupObj->bindGroupEntries.push_back(smpEntry); - _samplerIdxMap.insert(std::make_pair(bindings[i].binding, _gpuBindGroupObj->bindGroupEntries.size() - 1)); - dsLayout->updateSamplerLayout(smpEntry.binding, sampler); } else if (hasFlag(DESCRIPTOR_BUFFER_TYPE, bindings[i].descriptorType)) { - CCWGPUBuffer *buffer = hasFlag(DescriptorType::DYNAMIC_STORAGE_BUFFER | DescriptorType::STORAGE_BUFFER, bindings[i].descriptorType) - ? deviceObj->defaultResources.storageBuffer - : deviceObj->defaultResources.uniformBuffer; - WGPUBindGroupEntry bufferEntry = { - .binding = bindings[i].binding, - .buffer = buffer->gpuBufferObject()->wgpuBuffer, - .size = buffer->getSize(), - .offset = buffer->getOffset(), - }; - if (hasAnyFlags(bindings[i].descriptorType, DescriptorType::DYNAMIC_STORAGE_BUFFER | DescriptorType::DYNAMIC_UNIFORM_BUFFER)) { - _dynamicOffsets.push_back({bindings[i].binding, 0}); + _dynamicOffsets.emplace(i, bindings[i].binding); } - _gpuBindGroupObj->bindGroupEntries.push_back(bufferEntry); - } else if (bindings[i].descriptorType == DescriptorType::STORAGE_IMAGE) { - CCWGPUTexture *texture = deviceObj->defaultResources.storageTexture; - WGPUBindGroupEntry texEntry = { - .binding = bindings[i].binding, - .textureView = texture->gpuTextureObject()->selfView, - }; - _gpuBindGroupObj->bindGroupEntries.push_back(texEntry); - dsLayout->updateTextureLayout(texEntry.binding, texture); - } else if (bindings[i].descriptorType == DescriptorType::TEXTURE) { - CCWGPUTexture *texture = deviceObj->defaultResources.commonTexture; - WGPUBindGroupEntry texEntry = { - .binding = bindings[i].binding, - .textureView = texture->gpuTextureObject()->selfView, - }; - _gpuBindGroupObj->bindGroupEntries.push_back(texEntry); - dsLayout->updateTextureLayout(texEntry.binding, texture); - } else if (bindings[i].descriptorType == DescriptorType::SAMPLER) { - CCWGPUSampler *sampler = deviceObj->defaultResources.unfilterableSampler; - WGPUBindGroupEntry smpEntry = { - .binding = bindings[i].binding, - .sampler = sampler->gpuSampler(), - }; - _gpuBindGroupObj->bindGroupEntries.push_back(smpEntry); - dsLayout->updateSamplerLayout(smpEntry.binding, sampler); - } else { - WGPUBindGroupEntry texEntry = { - .binding = bindings[i].binding, - }; - _gpuBindGroupObj->bindGroupEntries.push_back(texEntry); } } + _gpuDescriptorObj->gpuDescriptors.resize(bindings.size()); + _gpuDescriptorObj->descriptorIndices = info.layout->getBindingIndices(); + + _bindingSatisfied = [](uint32_t) { return true; }; + (void)defaultBindGroup(); } ccstd::hash_t CCWGPUDescriptorSet::hash() const { - ccstd::hash_t hash = 9527; - for (const auto &bufferWrapper : _buffers) { - auto *buffer = bufferWrapper.ptr; - if (buffer) { - auto *wgpuBuffer = static_cast(buffer)->gpuBufferObject()->wgpuBuffer; - ccstd::hash_combine(hash, wgpuBuffer); + ccstd::hash_t hash = _gpuBindGroupObj->bindGroupEntries.size(); + + for (const auto &entry : _gpuBindGroupObj->bindGroupEntries) { + ccstd::hash_combine(hash, entry.binding); + if (entry.buffer) { + ccstd::hash_combine(hash, entry.buffer); + ccstd::hash_combine(hash, entry.offset); + ccstd::hash_combine(hash, entry.size); } - } - for (const auto &textureWrapper : _textures) { - auto *texture = textureWrapper.ptr; - if (texture) { - auto *wgpuTextureView = static_cast(texture)->gpuTextureObject()->selfView; - ccstd::hash_combine(hash, wgpuTextureView); + if (entry.sampler) { + ccstd::hash_combine(hash, entry.sampler); } - } - for (const auto &samplerWrapper : _samplers) { - auto *sampler = samplerWrapper.ptr; - if (sampler) { - auto *wgpuSampler = static_cast(sampler)->gpuSampler(); - ccstd::hash_combine(hash, wgpuSampler); + if (entry.textureView) { + ccstd::hash_combine(hash, entry.textureView); } } + return hash; } @@ -174,74 +116,106 @@ void CCWGPUDescriptorSet::doDestroy() { delete _gpuBindGroupObj; _gpuBindGroupObj = nullptr; } + if (_gpuDescriptorObj) { + delete _gpuDescriptorObj; + _gpuDescriptorObj = nullptr; + } +} + +void CCWGPUDescriptorSet::setGpuDescriptors(DescriptorSet *set) { + auto *ccDesc = static_cast(set); + const auto &descs = ccDesc->gpuDescriptors(); + + auto *tLayout = const_cast(_layout); + auto *dsLayout = static_cast(tLayout); + auto *srcTmpLayout = set->getLayout(); + + dsLayout->setBindings(srcTmpLayout->getBindings()); + dsLayout->setBindingIndices(srcTmpLayout->getBindingIndices()); + dsLayout->setDescriptorIndices(srcTmpLayout->getDescriptorIndices()); + + _gpuDescriptorObj->gpuDescriptors = descs.gpuDescriptors; + _gpuDescriptorObj->descriptorIndices = descs.descriptorIndices; + + _buffers = ccDesc->_buffers; + _textures = ccDesc->_textures; + _samplers = ccDesc->_samplers; + + _isDirty = true; +} + +void CCWGPUDescriptorSet::prune(ccstd::vector bindings) { + _gpuBindGroupObj->bindingInShader = std::set(bindings.begin(), bindings.end()); + + _bindingSatisfied = [&](uint32_t binding) { + return (!_gpuBindGroupObj->bindingInShader.empty()) && (_gpuBindGroupObj->bindingInShader.find(binding) != _gpuBindGroupObj->bindingInShader.end()); + }; } void CCWGPUDescriptorSet::update() { if (!_isDirty) { return; } - auto *dsLayout = static_cast(_layout); + auto *tLayout = const_cast(_layout); + auto *dsLayout = static_cast(tLayout); const auto &bindings = dsLayout->getBindings(); - for (size_t i = 0; i < bindings.size(); i++) { + _gpuBindGroupObj->bindGroupEntries.clear(); + _dynamicOffsetNum = 0; + + for (size_t i = 0; i < _gpuDescriptorObj->gpuDescriptors.size(); i++) { + if (!_bindingSatisfied(bindings[i].binding)) { + continue; + } + _gpuDescriptorObj->gpuDescriptors[i].type = bindings[i].descriptorType; const auto &binding = bindings[i]; uint8_t resourceIndex = _layout->getDescriptorIndices()[i]; if (hasFlag(DESCRIPTOR_BUFFER_TYPE, bindings[i].descriptorType)) { - if (_buffers[resourceIndex].ptr) { - auto *buffer = static_cast(_buffers[resourceIndex].ptr); - auto &bindGroupEntry = _gpuBindGroupObj->bindGroupEntries[i]; - buffer->check(); - bindGroupEntry.binding = binding.binding; - bindGroupEntry.buffer = buffer->gpuBufferObject()->wgpuBuffer; - bindGroupEntry.offset = buffer->getOffset(); - bindGroupEntry.size = buffer->getSize(); - dsLayout->updateBufferLayout(bindGroupEntry.binding, buffer); - uint8_t bindIndex = binding.binding; - if (hasAnyFlags(binding.descriptorType, DescriptorType::DYNAMIC_STORAGE_BUFFER | DescriptorType::DYNAMIC_UNIFORM_BUFFER)) { - auto iter = std::find_if(_dynamicOffsets.begin(), _dynamicOffsets.end(), [bindIndex](const std::pair dynIndex) { - return dynIndex.first == bindIndex; - }); - // assert(iter != _dynamicOffsets.end()); //can't happen - (*iter).second = 1; - } + auto *ccBuffer = _buffers[resourceIndex].ptr ? static_cast(_buffers[resourceIndex].ptr) : CCWGPUBuffer::defaultUniformBuffer(); + auto *buffer = static_cast(ccBuffer); + auto &bindGroupEntry = _gpuBindGroupObj->bindGroupEntries.emplace_back(); + buffer->check(); + bindGroupEntry.binding = binding.binding; + bindGroupEntry.buffer = buffer->gpuBufferObject()->wgpuBuffer; + bindGroupEntry.offset = buffer->getOffset(); + bindGroupEntry.size = buffer->getSize(); + dsLayout->updateBufferLayout(i, buffer, _buffers[resourceIndex].flags); + uint8_t bindIndex = binding.binding; + if (hasAnyFlags(binding.descriptorType, DescriptorType::DYNAMIC_STORAGE_BUFFER | DescriptorType::DYNAMIC_UNIFORM_BUFFER)) { + _dynamicOffsets[i] = bindIndex; + _dynamicOffsetNum++; } + + _gpuDescriptorObj->gpuDescriptors[i].buffer = ccBuffer; } else if (hasFlag(COMBINED_ST_IN_USE, bindings[i].descriptorType)) { - auto texIter = _textureIdxMap.find(binding.binding); - auto smpIter = _samplerIdxMap.find(binding.binding); - // assert((texIter != _textureIdxMap.end()) + (smpIter != _samplerIdxMap.end()) == 1); - uint8_t textureIdx = texIter != _textureIdxMap.end() ? texIter->second : 255; - uint8_t samplerIdx = smpIter != _samplerIdxMap.end() ? smpIter->second : 255; - - if (textureIdx != 255 && _textures[resourceIndex].ptr) { - auto &bindGroupEntry = _gpuBindGroupObj->bindGroupEntries[textureIdx]; - auto *texture = static_cast(_textures[resourceIndex].ptr); - bindGroupEntry.binding = binding.binding; - bindGroupEntry.textureView = texture->gpuTextureObject()->selfView; - dsLayout->updateTextureLayout(bindGroupEntry.binding, texture); - _gpuBindGroupObj->bindingSet.insert(binding.binding); - } - if (samplerIdx != 255 && _samplers[resourceIndex].ptr) { - auto &bindGroupEntry = _gpuBindGroupObj->bindGroupEntries[samplerIdx]; - auto *sampler = static_cast(_samplers[resourceIndex].ptr); - bindGroupEntry.binding = binding.binding + CC_WGPU_MAX_ATTACHMENTS; - bindGroupEntry.sampler = sampler->gpuSampler(); - dsLayout->updateSamplerLayout(bindGroupEntry.binding, sampler); - _gpuBindGroupObj->bindingSet.insert(binding.binding + CC_WGPU_MAX_ATTACHMENTS); - } + // printf("texture update %d %d %p\n", i, resourceIndex, _textures[resourceIndex].ptr); + auto *ccTexture = _textures[resourceIndex].ptr ? static_cast(_textures[resourceIndex].ptr) : CCWGPUTexture::defaultCommonTexture(); + auto &bindGroupEntry = _gpuBindGroupObj->bindGroupEntries.emplace_back(); + bindGroupEntry.binding = binding.binding; + bindGroupEntry.textureView = static_cast(ccTexture->getPlaneView(0)); + dsLayout->updateTextureLayout(i, ccTexture); + _gpuDescriptorObj->gpuDescriptors[i].texture = ccTexture; + + auto &sBindGroupEntry = _gpuBindGroupObj->bindGroupEntries.emplace_back(); + auto *ccSampler = _samplers[resourceIndex].ptr ? static_cast(_samplers[resourceIndex].ptr) : CCWGPUSampler::defaultFilterableSampler(); + sBindGroupEntry.binding = binding.binding + CC_WGPU_MAX_ATTACHMENTS; + sBindGroupEntry.sampler = ccSampler->gpuSampler(); + dsLayout->updateSamplerLayout(i, ccSampler); + _gpuDescriptorObj->gpuDescriptors[i].sampler = ccSampler; } else if (DescriptorType::STORAGE_IMAGE == bindings[i].descriptorType || DescriptorType::TEXTURE == bindings[i].descriptorType) { - if (_textures[resourceIndex].ptr) { - auto &bindGroupEntry = _gpuBindGroupObj->bindGroupEntries[resourceIndex]; - auto *texture = static_cast(_textures[resourceIndex].ptr); - bindGroupEntry.binding = binding.binding; - bindGroupEntry.textureView = texture->gpuTextureObject()->selfView; - dsLayout->updateTextureLayout(bindGroupEntry.binding, texture); - } + auto *ccTexture = _textures[resourceIndex].ptr ? static_cast(_textures[resourceIndex].ptr) : CCWGPUTexture::defaultCommonTexture(); + auto &bindGroupEntry = _gpuBindGroupObj->bindGroupEntries[resourceIndex]; + bindGroupEntry.binding = binding.binding; + bindGroupEntry.textureView = static_cast(ccTexture->getPlaneView(0)); + dsLayout->updateTextureLayout(i, ccTexture); + _gpuDescriptorObj->gpuDescriptors[i].texture = ccTexture; } else if (DescriptorType::SAMPLER == bindings[i].descriptorType) { + auto *ccSampler = _samplers[resourceIndex].ptr ? static_cast(_samplers[resourceIndex].ptr) : CCWGPUSampler::defaultFilterableSampler(); auto &bindGroupEntry = _gpuBindGroupObj->bindGroupEntries[resourceIndex]; - auto *sampler = static_cast(_samplers[resourceIndex].ptr); bindGroupEntry.binding = binding.binding; - bindGroupEntry.sampler = sampler->gpuSampler(); - dsLayout->updateSamplerLayout(bindGroupEntry.binding, sampler); + bindGroupEntry.sampler = ccSampler->gpuSampler(); + dsLayout->updateSamplerLayout(i, ccSampler); + _gpuDescriptorObj->gpuDescriptors[i].sampler = ccSampler; } else { printf("*******unexpected binding type detected!\n"); } @@ -263,20 +237,15 @@ void CCWGPUDescriptorSet::prepare() { update(); } - const auto &entries = _gpuBindGroupObj->bindGroupEntries; - if (_isDirty || forceUpdate || !_gpuBindGroupObj->bindgroup) { - auto *dsLayout = static_cast(_layout); - dsLayout->prepare(_gpuBindGroupObj->bindingSet, forceUpdate); - - // ccstd::vector bindGroupEntries; - // bindGroupEntries.assign(_gpuBindGroupObj->bindGroupEntries.begin(), _gpuBindGroupObj->bindGroupEntries.end()); - // bindGroupEntries.erase(std::remove_if( - // bindGroupEntries.begin(), bindGroupEntries.end(), [this, &bindGroupEntries](const WGPUBindGroupEntry &entry) { - // return _gpuBindGroupObj->bindingSet.find(entry.binding) == _gpuBindGroupObj->bindingSet.end(); - // }), - // bindGroupEntries.end()); - if (entries.empty()) { + // TODDO(Zeqiang): no const cast + auto *tLayout = const_cast(_layout); + auto *dsLayout = static_cast(tLayout); + + dsLayout->prepare(_gpuBindGroupObj->bindingInShader, forceUpdate); + + const auto &entries = _gpuBindGroupObj->bindGroupEntries; + if (_gpuBindGroupObj->bindingInShader.empty()) { _gpuBindGroupObj->bindgroup = dftBindGroup; _bornHash = 0; } else { @@ -286,9 +255,7 @@ void CCWGPUDescriptorSet::prepare() { // layout might be changed later. _bornHash = dsLayout->getHash(); CCWGPUDeviceObject *deviceObj = CCWGPUDevice::getInstance()->gpuDeviceObject(); - // if (_gpuBindGroupObj->bindgroup && _gpuBindGroupObj->bindgroup != dftBindGroup) { - // wgpuBindGroupRelease(_gpuBindGroupObj->bindgroup); - // } + label = std::to_string(_bornHash); WGPUBindGroupDescriptor bindGroupDesc = { .nextInChain = nullptr, @@ -299,7 +266,6 @@ void CCWGPUDescriptorSet::prepare() { }; _gpuBindGroupObj->bindgroup = wgpuDeviceCreateBindGroup(CCWGPUDevice::getInstance()->gpuDeviceObject()->wgpuDevice, &bindGroupDesc); - // printf("create new bg\n"); _isDirty = false; if (buffIter != _buffers.end()) @@ -318,14 +284,13 @@ void CCWGPUDescriptorSet::prepare() { } else { _gpuBindGroupObj->bindgroup = static_cast(iter->second.bindGroup); _bornHash = iter->second.bornHash; - // printf("reuse bg\n"); } } } } uint8_t CCWGPUDescriptorSet::dynamicOffsetCount() const { - return _dynamicOffsets.size(); + return _dynamicOffsetNum; } void *CCWGPUDescriptorSet::defaultBindGroup() { diff --git a/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSet.h b/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSet.h index 9c370f61ac0..6d4232babb8 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSet.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSet.h @@ -34,7 +34,19 @@ namespace gfx { struct CCWGPUBindGroupObject; -using Pairs = ccstd::vector>; +struct WGPUGPUDescriptor { + DescriptorType type = DescriptorType::UNKNOWN; + Buffer *buffer = nullptr; + Texture *texture = nullptr; + Sampler *sampler = nullptr; +}; +using CCWGPUGPUDescriptorList = ccstd::vector; + +// web interface +struct CCWGPUGPUDescriptorSetObject { + CCWGPUGPUDescriptorList gpuDescriptors; + ccstd::vector descriptorIndices; +}; class CCWGPUDescriptorSet final : public DescriptorSet { public: @@ -42,34 +54,42 @@ class CCWGPUDescriptorSet final : public DescriptorSet { ~CCWGPUDescriptorSet(); inline CCWGPUBindGroupObject *gpuBindGroupObject() { return _gpuBindGroupObj; } - inline Pairs &dynamicOffsets() { return _dynamicOffsets; } + inline const std::map &dynamicOffsets() { return _dynamicOffsets; } void update() override; - void forceUpdate() override{}; + void forceUpdate() override { + _isDirty = true; + update(); + }; + + void prune(ccstd::vector bindings); uint8_t dynamicOffsetCount() const; void prepare(); - ccstd::hash_t getHash() { return _bornHash; }; + ccstd::hash_t getHash() { return _bornHash; } static void *defaultBindGroup(); static void clearCache(); std::string label; + inline void setLayout(const DescriptorSetLayout *layout) { _layout = layout; } + + inline const CCWGPUGPUDescriptorSetObject gpuDescriptors() const { return *_gpuDescriptorObj; } + void setGpuDescriptors(DescriptorSet *set); + protected: void doInit(const DescriptorSetInfo &info) override; void doDestroy() override; ccstd::hash_t hash() const; CCWGPUBindGroupObject *_gpuBindGroupObj = nullptr; - - // seperate combined sampler-texture index - ccstd::unordered_map _textureIdxMap; - ccstd::unordered_map _samplerIdxMap; - + CCWGPUGPUDescriptorSetObject *_gpuDescriptorObj = nullptr; // dynamic offsets, inuse ? 1 : 0; - Pairs _dynamicOffsets; + std::map _dynamicOffsets; + uint32_t _dynamicOffsetNum{0}; ccstd::hash_t _hash{0}; ccstd::hash_t _bornHash{0}; // hash when created, this relate to reuse bindgroup layout + std::function _bindingSatisfied; }; } // namespace gfx diff --git a/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSetLayout.cpp b/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSetLayout.cpp index 432b1ad9ef7..2708ecca1cc 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSetLayout.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSetLayout.cpp @@ -32,6 +32,7 @@ #include "WGPUSampler.h" #include "WGPUTexture.h" #include "WGPUUtils.h" +#include "base/Assertf.h" namespace cc { namespace gfx { @@ -40,174 +41,8 @@ namespace { WGPUBindGroupLayout dftBindgroupLayout = wgpuDefaultHandle; ccstd::unordered_map layoutPool; -} // namespace - -using namespace emscripten; - -CCWGPUDescriptorSetLayout::CCWGPUDescriptorSetLayout() : DescriptorSetLayout() { -} - -CCWGPUDescriptorSetLayout::~CCWGPUDescriptorSetLayout() { - doDestroy(); -} - -void CCWGPUDescriptorSetLayout::doInit(const DescriptorSetLayoutInfo &info) { - _gpuLayoutEntryObj = ccnew CCWGPUBindGroupLayoutObject; - for (size_t i = 0; i < _bindings.size(); i++) { - if (_bindings[i].descriptorType == DescriptorType::UNKNOWN) - continue; - if (hasFlag(COMBINED_ST_IN_USE, _bindings[i].descriptorType)) { - // 1. texture - WGPUBindGroupLayoutEntry textureLayout = { - .nextInChain = nullptr, - .binding = _bindings[i].binding, - .visibility = toWGPUShaderStageFlag(_bindings[i].stageFlags), - .texture.sampleType = WGPUTextureSampleType_Float, - .texture.viewDimension = WGPUTextureViewDimension_2D, - }; - _gpuLayoutEntryObj->bindGroupLayoutEntries.push_back(textureLayout); - - // 2. sampler - WGPUBindGroupLayoutEntry samplerLayout = { - .nextInChain = nullptr, - .binding = _bindings[i].binding + CC_WGPU_MAX_ATTACHMENTS, - .visibility = toWGPUShaderStageFlag(_bindings[i].stageFlags), - .sampler.type = WGPUSamplerBindingType_NonFiltering, - }; - _gpuLayoutEntryObj->bindGroupLayoutEntries.push_back(samplerLayout); - } else if (hasFlag(DESCRIPTOR_BUFFER_TYPE, _bindings[i].descriptorType)) { - bool hasDynamicOffset = hasAnyFlags(_bindings[i].descriptorType, DescriptorType::DYNAMIC_STORAGE_BUFFER | DescriptorType::DYNAMIC_UNIFORM_BUFFER); - _dynamicOffsetCount += (hasDynamicOffset); - if (hasFlag(_bindings[i].descriptorType, DescriptorType::STORAGE_BUFFER | DescriptorType::DYNAMIC_STORAGE_BUFFER)) { - WGPUBindGroupLayoutEntry layout = { - .nextInChain = nullptr, - .binding = _bindings[i].binding, - .visibility = toWGPUShaderStageFlag(_bindings[i].stageFlags), - .buffer = {nullptr, WGPUBufferBindingType::WGPUBufferBindingType_Storage, hasDynamicOffset, 0}, - }; - _gpuLayoutEntryObj->bindGroupLayoutEntries.push_back(layout); - } else if (hasFlag(_bindings[i].descriptorType, DescriptorType::UNIFORM_BUFFER | DescriptorType::DYNAMIC_UNIFORM_BUFFER)) { - WGPUBindGroupLayoutEntry layout = { - .nextInChain = nullptr, - .binding = _bindings[i].binding, - .visibility = toWGPUShaderStageFlag(_bindings[i].stageFlags), - .buffer = {nullptr, WGPUBufferBindingType::WGPUBufferBindingType_Uniform, hasDynamicOffset, 0}, - }; - _gpuLayoutEntryObj->bindGroupLayoutEntries.push_back(layout); - } else { - printf("unsupport buffer descriptor type."); - } - } else if (_bindings[i].descriptorType == DescriptorType::SAMPLER) { - WGPUBindGroupLayoutEntry layout = { - .nextInChain = nullptr, - .binding = _bindings[i].binding, - .visibility = toWGPUShaderStageFlag(_bindings[i].stageFlags), - .sampler = {nullptr, WGPUSamplerBindingType::WGPUSamplerBindingType_NonFiltering}, - }; - _gpuLayoutEntryObj->bindGroupLayoutEntries.push_back(layout); - } else if (_bindings[i].descriptorType == DescriptorType::STORAGE_IMAGE) { - WGPUBindGroupLayoutEntry layout = { - .nextInChain = nullptr, - .binding = _bindings[i].binding, - .visibility = toWGPUShaderStageFlag(_bindings[i].stageFlags), - .storageTexture = { - nullptr, - WGPUStorageTextureAccess::WGPUStorageTextureAccess_WriteOnly, - WGPUTextureFormat::WGPUTextureFormat_RGBA8Unorm, - WGPUTextureViewDimension::WGPUTextureViewDimension_2D, - }, - }; - _gpuLayoutEntryObj->bindGroupLayoutEntries.push_back(layout); - } else { - WGPUBindGroupLayoutEntry layout = { - .nextInChain = nullptr, - .binding = _bindings[i].binding, - .visibility = toWGPUShaderStageFlag(_bindings[i].stageFlags), - }; - _gpuLayoutEntryObj->bindGroupLayoutEntries.push_back(layout); - } - } - - (void)defaultBindGroupLayout(); - - _hash = hash(); -} - -void CCWGPUDescriptorSetLayout::updateBufferLayout(uint8_t binding, const CCWGPUBuffer *buffer) { - // auto iter = std::find_if(_gpuLayoutEntryObj->bindGroupLayoutEntries.begin(), _gpuLayoutEntryObj->bindGroupLayoutEntries.end(), [binding](const WGPUBindGroupLayoutEntry &entry) { - // return entry.binding == binding; - // }); - - // if (iter != _gpuLayoutEntryObj->bindGroupLayoutEntries.end()) { - // auto bindingIter = std::find_if(_bindings.begin(), _bindings.end(), [binding](const auto &binding) { - // return binding.binding == binding; - // }); - // } - // _internalChanged = true; -} - -void CCWGPUDescriptorSetLayout::updateTextureLayout(uint8_t binding, const CCWGPUTexture *texture) { - auto iter = std::find_if(_gpuLayoutEntryObj->bindGroupLayoutEntries.begin(), _gpuLayoutEntryObj->bindGroupLayoutEntries.end(), [binding](const WGPUBindGroupLayoutEntry &entry) { - return entry.binding == binding; - }); - - if (iter != _gpuLayoutEntryObj->bindGroupLayoutEntries.end()) { - auto bindingIter = std::find_if(_bindings.begin(), _bindings.end(), [binding](const auto &bindingElem) { - return bindingElem.binding == binding; - }); - if (texture) { - if (texture->getInfo().usage == TextureUsageBit::STORAGE) { - (*iter).storageTexture.nextInChain = nullptr; - (*iter).storageTexture.access = WGPUStorageTextureAccess::WGPUStorageTextureAccess_WriteOnly; - (*iter).storageTexture.format = toWGPUTextureFormat(texture->getFormat()); - TextureType type = texture->isTextureView() ? texture->getViewInfo().type : texture->getInfo().type; - (*iter).storageTexture.viewDimension = toWGPUTextureViewDimension(type); - } else { - (*iter).texture.nextInChain = nullptr; - (*iter).texture.sampleType = textureSampleTypeTrait(texture->getFormat()); - const CCWGPUTexture *ccTex = static_cast(texture->isTextureView() ? texture->getViewInfo().texture : texture); - TextureType type = ccTex->getViewInfo().type; - (*iter).texture.viewDimension = toWGPUTextureViewDimension(type); - (*iter).texture.multisampled = ccTex->getInfo().samples != SampleCount::X1; - } - } else { - (*iter).texture.nextInChain = nullptr; - (*iter).texture.sampleType = WGPUTextureSampleType::WGPUTextureSampleType_Float; - (*iter).texture.viewDimension = WGPUTextureViewDimension::WGPUTextureViewDimension_2D; - (*iter).texture.multisampled = false; - } - _internalChanged = true; - } -} - -void CCWGPUDescriptorSetLayout::updateSamplerLayout(uint8_t binding, const CCWGPUSampler *sampler) { - auto iter = std::find_if(_gpuLayoutEntryObj->bindGroupLayoutEntries.begin(), _gpuLayoutEntryObj->bindGroupLayoutEntries.end(), [binding](const WGPUBindGroupLayoutEntry &entry) { - return entry.binding == binding; - }); - - if (iter != _gpuLayoutEntryObj->bindGroupLayoutEntries.end()) { - auto bindingIter = std::find_if(_bindings.begin(), _bindings.end(), [binding](const auto &bindingElem) { - return bindingElem.binding == binding; - }); - if (sampler) { - const SamplerInfo &info = sampler->getInfo(); - if ((info.minFilter == Filter::POINT || info.minFilter == Filter::NONE) && - (info.magFilter == Filter::POINT || info.magFilter == Filter::NONE) && - (info.mipFilter == Filter::POINT || info.mipFilter == Filter::NONE)) { - (*iter).sampler.type = WGPUSamplerBindingType::WGPUSamplerBindingType_NonFiltering; - } else { - (*iter).sampler.type = WGPUSamplerBindingType::WGPUSamplerBindingType_Filtering; - } - } else { - (*iter).sampler.type = WGPUSamplerBindingType::WGPUSamplerBindingType_NonFiltering; - } - _internalChanged = true; - } -} - -ccstd::hash_t CCWGPUDescriptorSetLayout::hash() const { - const auto &entries = _gpuLayoutEntryObj->bindGroupLayoutEntries; +ccstd::hash_t hash(const ccstd::vector &entries) { ccstd::hash_t hash = 9527; ccstd::hash_combine(hash, entries.size()); for (size_t i = 0; i < entries.size(); i++) { @@ -236,12 +71,118 @@ ccstd::hash_t CCWGPUDescriptorSetLayout::hash() const { return hash; } +bool checkInUse(uint8_t binding, const ccstd::set &bindingInUse, bool samplerBinding) { + bool res = bindingInUse.find(binding) != bindingInUse.end(); + if (!res && samplerBinding) { + res |= bindingInUse.find(binding - CC_WGPU_MAX_ATTACHMENTS) != bindingInUse.end(); + } + return res; +} + +} // namespace + +using namespace emscripten; + +CCWGPUDescriptorSetLayout::CCWGPUDescriptorSetLayout() : DescriptorSetLayout() { +} + +CCWGPUDescriptorSetLayout::~CCWGPUDescriptorSetLayout() { + doDestroy(); +} + +void CCWGPUDescriptorSetLayout::doInit(const DescriptorSetLayoutInfo &info) { + _gpuLayoutEntryObj = ccnew CCWGPUBindGroupLayoutObject; + (void)defaultBindGroupLayout(); +} + +void CCWGPUDescriptorSetLayout::updateBufferLayout(uint8_t index, const CCWGPUBuffer *buffer, AccessFlags flags) { + WGPUBindGroupLayoutEntry bufferEntry{}; + bufferEntry.binding = _bindings[index].binding; + bufferEntry.visibility = toWGPUShaderStageFlag(_bindings[index].stageFlags); + + CC_ASSERT(buffer); + + WGPUBufferBindingLayout bufferLayout{}; + bool storageFlag = hasFlag(_bindings[index].descriptorType, DescriptorType::STORAGE_BUFFER | DescriptorType::DYNAMIC_STORAGE_BUFFER); + if (storageFlag) { + bufferLayout.type = flags > AccessFlagBit::PRESENT ? WGPUBufferBindingType_Storage : WGPUBufferBindingType_ReadOnlyStorage; + } else { + bufferLayout.type = WGPUBufferBindingType_Uniform; + } + bufferLayout.hasDynamicOffset = hasAnyFlags(_bindings[index].descriptorType, DescriptorType::DYNAMIC_STORAGE_BUFFER | DescriptorType::DYNAMIC_UNIFORM_BUFFER); + + bufferEntry.buffer = bufferLayout; + _gpuLayoutEntryObj->bindGroupLayoutEntries[bufferEntry.binding] = bufferEntry; +} + +namespace { +WGPUTextureFormat formatTraits(const CCWGPUTexture *texture, uint32_t plane) { + if (texture->getFormat() == Format::DEPTH_STENCIL) { + return plane ? WGPUTextureFormat_Stencil8 : WGPUTextureFormat_Depth24Plus; + } + return toWGPUTextureFormat(texture->getFormat()); +} + +WGPUTextureSampleType sampletypeTraits(const CCWGPUTexture *texture, uint32_t plane) { + if (texture->getFormat() == Format::DEPTH_STENCIL) { + return plane ? WGPUTextureSampleType_Uint : WGPUTextureSampleType_UnfilterableFloat; + } + return textureSampleTypeTrait(texture->getFormat()); +} +} // namespace + +void CCWGPUDescriptorSetLayout::updateTextureLayout(uint8_t index, const CCWGPUTexture *texture, uint32_t plane) { + WGPUBindGroupLayoutEntry textureEntry{}; + textureEntry.binding = _bindings[index].binding; + textureEntry.visibility = toWGPUShaderStageFlag(_bindings[index].stageFlags); + + CC_ASSERT(texture); + + if (texture->getInfo().usage == TextureUsageBit::STORAGE) { + WGPUStorageTextureBindingLayout storageTextureLayout{}; + storageTextureLayout.access = WGPUStorageTextureAccess::WGPUStorageTextureAccess_WriteOnly; + storageTextureLayout.format = formatTraits(texture, plane); + TextureType type = texture->isTextureView() ? texture->getViewInfo().type : texture->getInfo().type; + storageTextureLayout.viewDimension = toWGPUTextureViewDimension(type); + textureEntry.storageTexture = storageTextureLayout; + } else { + WGPUTextureBindingLayout textureLayout{}; + textureLayout.sampleType = sampletypeTraits(texture, plane); // textureSampleTypeTrait(texture->getFormat()); + const CCWGPUTexture *ccTex = static_cast(texture->isTextureView() ? texture->getViewInfo().texture : texture); + TextureType type = ccTex->getViewInfo().type; + textureLayout.viewDimension = toWGPUTextureViewDimension(type); + textureLayout.multisampled = ccTex->getInfo().samples != SampleCount::X1; + textureEntry.texture = textureLayout; + } + _gpuLayoutEntryObj->bindGroupLayoutEntries[textureEntry.binding] = textureEntry; +} + +void CCWGPUDescriptorSetLayout::updateSamplerLayout(uint8_t index, const CCWGPUSampler *sampler) { + WGPUBindGroupLayoutEntry samplerEntry{}; + samplerEntry.binding = _bindings[index].binding + CC_WGPU_MAX_ATTACHMENTS; + samplerEntry.visibility = toWGPUShaderStageFlag(_bindings[index].stageFlags); + + CC_ASSERT(sampler); + + WGPUSamplerBindingLayout samplerLayout{}; + const SamplerInfo &info = sampler->getInfo(); + if ((info.minFilter == Filter::POINT || info.minFilter == Filter::NONE) && + (info.magFilter == Filter::POINT || info.magFilter == Filter::NONE) && + (info.mipFilter == Filter::POINT || info.mipFilter == Filter::NONE)) { + samplerLayout.type = WGPUSamplerBindingType::WGPUSamplerBindingType_NonFiltering; + } else { + samplerLayout.type = WGPUSamplerBindingType::WGPUSamplerBindingType_Filtering; + } + samplerEntry.sampler = samplerLayout; + + _gpuLayoutEntryObj->bindGroupLayoutEntries[samplerEntry.binding] = samplerEntry; +} + void CCWGPUDescriptorSetLayout::print() const { size_t hashVal = _hash; printf("\npr this %p %p %zu\n", _gpuLayoutEntryObj, this, hashVal); const auto &entries = _gpuLayoutEntryObj->bindGroupLayoutEntries; - for (size_t j = 0; j < entries.size(); j++) { - const auto &entry = entries[j]; + for (const auto &[bd, entry] : entries) { if ((entry.buffer.type != WGPUBufferBindingType_Undefined) + (entry.sampler.type != WGPUSamplerBindingType_Undefined) + (entry.texture.sampleType != WGPUTextureSampleType_Undefined) + @@ -249,7 +190,7 @@ void CCWGPUDescriptorSetLayout::print() const { 1) { printf("******missing %d, %d, %d, %d, %d\n", entry.binding, entry.buffer.type, entry.sampler.type, entry.texture.sampleType, entry.storageTexture.access); } - printf("%d, %d\n", entry.binding, entry.visibility); + printf("%d, %d, %d\n", entry.binding, entry.visibility, entries.size()); if (entry.buffer.type != WGPUBufferBindingType_Undefined) { printf("b %d %d %d\n", entry.buffer.type, entry.buffer.hasDynamicOffset ? 1 : 0, entry.buffer.minBindingSize); } @@ -266,44 +207,28 @@ void CCWGPUDescriptorSetLayout::print() const { } void CCWGPUDescriptorSetLayout::prepare(ccstd::set &bindingInUse, bool forceUpdate) { - // if (_gpuLayoutEntryObj->bindGroupLayout && !forceUpdate) { - // return; - // } - // ccstd::vector bindGroupLayoutEntries; - // bindGroupLayoutEntries.assign(_gpuLayoutEntryObj->bindGroupLayoutEntries.begin(), _gpuLayoutEntryObj->bindGroupLayoutEntries.end()); - // bindGroupLayoutEntries.erase(std::remove_if( - // bindGroupLayoutEntries.begin(), bindGroupLayoutEntries.end(), [&bindingInUse, &bindGroupLayoutEntries](const WGPUBindGroupLayoutEntry &entry) { - // return bindingInUse.find(entry.binding) == bindingInUse.end(); - // }), - // bindGroupLayoutEntries.end()); - - _hash = hash(); + ccstd::vector bindGroupLayoutEntries{}; + bindGroupLayoutEntries.reserve(_gpuLayoutEntryObj->bindGroupLayoutEntries.size()); + for (const auto &[bd, layoutEntry] : _gpuLayoutEntryObj->bindGroupLayoutEntries) { + if(checkInUse(static_cast(bd), bindingInUse, layoutEntry.sampler.type != WGPUSamplerBindingType_Undefined)) { + bindGroupLayoutEntries.emplace_back(layoutEntry); + } + } + + _hash = hash(bindGroupLayoutEntries); auto iter = layoutPool.find(_hash); - // printf("dsl upd %zu\n", _hash); if (iter != layoutPool.end()) { _gpuLayoutEntryObj->bindGroupLayout = iter->second; return; } - const auto &entries = _gpuLayoutEntryObj->bindGroupLayoutEntries; - - // for (size_t j = 0; j < entries.size(); j++) { - // const auto& entry = entries[j]; - // if ((entry.buffer.type != WGPUBufferBindingType_Undefined) + - // (entry.sampler.type != WGPUSamplerBindingType_Undefined) + - // (entry.texture.sampleType != WGPUTextureSampleType_Undefined) + - // (entry.storageTexture.access != WGPUStorageTextureAccess_Undefined) != - // 1) { - // printf("******missing %d, %d, %d, %d, %d\n", entry.binding, entry.buffer.type, entry.sampler.type, entry.texture.sampleType, entry.storageTexture.access); - // } - // // printf("l binding, b, t, s %d, %d, %d, %d, %d\n", entry.binding, entry.buffer.type, entry.sampler.type, entry.texture.sampleType, entry.storageTexture.access); - // } + const auto &entries = bindGroupLayoutEntries; if (entries.empty()) { _gpuLayoutEntryObj->bindGroupLayout = dftBindgroupLayout; } else { WGPUBindGroupLayoutDescriptor descriptor = { .nextInChain = nullptr, - .label = std::to_string(_hash).c_str(), + .label = "",//std::to_string(_hash).c_str(), .entryCount = entries.size(), .entries = entries.data(), }; diff --git a/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSetLayout.h b/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSetLayout.h index 00db97bacbd..2af10719649 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSetLayout.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUDescriptorSetLayout.h @@ -44,13 +44,15 @@ class CCWGPUDescriptorSetLayout final : public DescriptorSetLayout { inline CCWGPUBindGroupLayoutObject *gpuLayoutEntryObject() { return _gpuLayoutEntryObj; } - void updateBufferLayout(uint8_t binding, const CCWGPUBuffer *buffer); - void updateTextureLayout(uint8_t binding, const CCWGPUTexture *texture); - void updateSamplerLayout(uint8_t binding, const CCWGPUSampler *sampler); + void updateBufferLayout(uint8_t index, const CCWGPUBuffer *buffer, AccessFlags flags); + void updateTextureLayout(uint8_t index, const CCWGPUTexture *texture, uint32_t plane = 0); + void updateSamplerLayout(uint8_t index, const CCWGPUSampler *sampler); - void prepare(ccstd::set &bindingInUse, bool forceUpdate = false); + inline void setBindings(const DescriptorSetLayoutBindingList &list) { _bindings.assign(list.begin(), list.end()); } + inline void setBindingIndices(const ccstd::vector &list) { _bindingIndices.assign(list.begin(), list.end()); } + inline void setDescriptorIndices(const ccstd::vector &indices) { _descriptorIndices.assign(indices.begin(), indices.end()); } - inline uint8_t dynamicOffsetCount() { return _dynamicOffsetCount; } + void prepare(ccstd::set &bindingInUse, bool forceUpdate = false); static void *defaultBindGroupLayout(); static void *getBindGroupLayoutByHash(ccstd::hash_t hash); @@ -65,13 +67,9 @@ class CCWGPUDescriptorSetLayout final : public DescriptorSetLayout { void doInit(const DescriptorSetLayoutInfo &info) override; void doDestroy() override; - ccstd::hash_t hash() const; ccstd::hash_t _hash{0}; - bool _internalChanged{false}; CCWGPUBindGroupLayoutObject *_gpuLayoutEntryObj = nullptr; - - uint8_t _dynamicOffsetCount = 0; }; } // namespace gfx diff --git a/native/cocos/renderer/gfx-wgpu/WGPUDevice.cpp b/native/cocos/renderer/gfx-wgpu/WGPUDevice.cpp index 0735a14e7d7..f824acbbbc9 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUDevice.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUDevice.cpp @@ -132,8 +132,7 @@ bool CCWGPUDevice::doInit(const DeviceInfo &info) { .type = CommandBufferType::PRIMARY, }; _cmdBuff = this->Device::createCommandBuffer(cmdInfo); - // Sept 6th 2022: not implemented by emscripten - // _gpuDeviceObj->instance.wgpuInstance = wgpuCreateInstance({}); + _gpuDeviceObj->instance.wgpuInstance = wgpuCreateInstance({}); #ifdef CC_WGPU_WASM WGPUSurfaceDescriptorFromCanvasHTMLSelector canvDesc = {}; @@ -142,7 +141,7 @@ bool CCWGPUDevice::doInit(const DeviceInfo &info) { WGPUSurfaceDescriptor surfDesc = {}; surfDesc.nextInChain = reinterpret_cast(&canvDesc); - _gpuDeviceObj->instance.wgpuSurface = wgpuInstanceCreateSurface(nullptr, &surfDesc); + _gpuDeviceObj->instance.wgpuSurface = wgpuInstanceCreateSurface(_gpuDeviceObj->instance.wgpuInstance, &surfDesc); #elif defined(CC_WGPU_DAWN) _gpuDeviceObj->instance.wgpuInstance = wgpuCreateInstance({}); @@ -486,7 +485,7 @@ void CCWGPUDevice::debug() { } void CCWGPUDevice::initConfigs() { - WGPUAdapterProperties props; + WGPUAdapterProperties props{}; wgpuAdapterGetProperties(_gpuDeviceObj->instance.wgpuAdapter, &props); // _deviceName = props.name; // _vendor = props.driverDescription; diff --git a/native/cocos/renderer/gfx-wgpu/WGPUDevice.h b/native/cocos/renderer/gfx-wgpu/WGPUDevice.h index ad99398ae6d..e0691df45f6 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUDevice.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUDevice.h @@ -91,6 +91,8 @@ class CCWGPUDevice final : public Device { using Device::getSampler; using Device::initialize; + void frameSync() override {}; + Shader *createShader(const ShaderInfo &, const std::vector> &); void copyBuffersToTexture(const std::vector> &buffers, Texture *dst, const std::vector ®ions) { @@ -117,7 +119,6 @@ class CCWGPUDevice final : public Device { EXPORT_EMS( void copyTextureToBuffers(Texture *src, const emscripten::val &buffers, const emscripten::val ®ions); emscripten::val copyTextureToBuffers(Texture * src, const BufferTextureCopyList ®ions); - Shader * createShader(const ShaderInfo &info, const emscripten::val &spirvVal); void copyBuffersToTexture(const emscripten::val &v, Texture *dst, const std::vector ®ions);) void initFeatures(); diff --git a/native/cocos/renderer/gfx-wgpu/WGPUEMSImpl.cpp b/native/cocos/renderer/gfx-wgpu/WGPUEMSImpl.cpp index 03aa932ed7b..44160fec98b 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUEMSImpl.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUEMSImpl.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include "WGPUBuffer.h" #include "WGPUCommandBuffer.h" #include "WGPUDef.h" @@ -153,21 +154,6 @@ void CCWGPUDevice::copyTextureToBuffers(Texture* src, const emscripten::val& buf // @hana-alice } -Shader* CCWGPUDevice::createShader(const ShaderInfo& info, const emscripten::val& spirvVal) { - CHECK_PTR(spirvVal); - - auto len = spirvVal[length_val].as(); - std::vector> spvData; - for (size_t i = 0; i < len; ++i) { - spvData.emplace_back(std::move(convertJSArrayToNumberVector_local(spirvVal[i]))); - } - - auto* shader = new CCWGPUShader(); - // shader->initialize(shaderInfo); - shader->initialize(info, spvData); - return shader; -} - void CCWGPUDevice::copyBuffersToTexture(const emscripten::val& v, Texture* dst, const std::vector& regions) { CHECK_VOID(v); auto len = v[length_val].as(); @@ -182,4 +168,9 @@ void CCWGPUDevice::copyBuffersToTexture(const emscripten::val& v, Texture* dst, return copyBuffersToTexture(buffers.data(), dst, regions.data(), regions.size()); } +void CCWGPUShader::reflectBinding(const emscripten::val &vals) { + const std::vector& bindings = convertJSArrayToNumberVector(vals); + _gpuShaderObject->bindings.emplace_back(bindings); +} + } // namespace cc::gfx diff --git a/native/cocos/renderer/gfx-wgpu/WGPUExports.h b/native/cocos/renderer/gfx-wgpu/WGPUExports.h index f5d0a6e002b..a9547026a0f 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUExports.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUExports.h @@ -45,7 +45,7 @@ #include "states/WGPUGeneralBarrier.h" #include "states/WGPUTextureBarrier.h" -REGISTER_GFX_PTRS_FOR_STRUCT(Device, Buffer, Texture, GeneralBarrier, Queue, RenderPass, Shader, PipelineLayout, DescriptorSetLayout, CommandBuffer, DescriptorSet); +REGISTER_GFX_PTRS_FOR_STRUCT(Device, Buffer, Texture, GeneralBarrier, Queue, RenderPass, Shader, PipelineLayout, DescriptorSetLayout, CommandBuffer, DescriptorSet, Sampler, CCWGPUGPUDescriptorSetObject); namespace cc::gfx { @@ -106,17 +106,20 @@ EMSCRIPTEN_BINDINGS(WEBGPU_DEVICE_WASM_EXPORT) { EXPORT_STRUCT_POD(Attribute, name, format, isNormalized, stream, isInstanced, location); EXPORT_STRUCT_POD(ShaderInfo, name, stages, attributes, blocks, buffers, samplerTextures, samplers, textures, images, subpassInputs); EXPORT_STRUCT_NPOD(InputAssemblerInfo, attributes, vertexBuffers, indexBuffer, indirectBuffer); - EXPORT_STRUCT_NPOD(ColorAttachment, format, sampleCount, loadOp, storeOp, barrier, isGeneralLayout); - EXPORT_STRUCT_NPOD(DepthStencilAttachment, format, sampleCount, depthLoadOp, depthStoreOp, stencilLoadOp, stencilStoreOp, barrier, isGeneralLayout); + EXPORT_STRUCT_NPOD(ColorAttachment, format, sampleCount, loadOp, storeOp, barrier); + EXPORT_STRUCT_NPOD(DepthStencilAttachment, format, sampleCount, depthLoadOp, depthStoreOp, stencilLoadOp, stencilStoreOp, barrier); EXPORT_STRUCT_POD(SubpassInfo, inputs, colors, resolves, preserves, depthStencil, depthStencilResolve, depthResolveMode, stencilResolveMode); // MAYBE TODO(Zeqiang): all ts related backend no need to care about barriers. - EXPORT_STRUCT_POD(SubpassDependency, srcSubpass, dstSubpass, bufferBarrierCount, textureBarrierCount); + EXPORT_STRUCT_POD(SubpassDependency, srcSubpass, dstSubpass, prevAccesses, nextAccesses); EXPORT_STRUCT_POD(RenderPassInfo, colorAttachments, depthStencilAttachment, subpasses, dependencies); EXPORT_STRUCT_POD(GeneralBarrierInfo, prevAccesses, nextAccesses, type); - EXPORT_STRUCT_NPOD(TextureBarrierInfo, prevAccesses, nextAccesses, type, baseMipLevel, levelCount, baseSlice, sliceCount, discardContents, srcQueue, dstQueue); + EXPORT_STRUCT_POD(ResourceRange, width, height, depthOrArraySize, firstSlice, numSlices, mipLevel, levelCount, basePlane, planeCount); + EXPORT_STRUCT_NPOD(TextureBarrierInfo, prevAccesses, nextAccesses, type, range, discardContents, srcQueue, dstQueue); EXPORT_STRUCT_NPOD(BufferBarrierInfo, prevAccesses, nextAccesses, type, offset, size, discardContents, srcQueue, dstQueue); EXPORT_STRUCT_NPOD(FramebufferInfo, renderPass, colorTextures, depthStencilTexture); + EXPORT_STRUCT_NPOD(WGPUGPUDescriptor, type, buffer, texture, sampler); + EXPORT_STRUCT_NPOD(CCWGPUGPUDescriptorSetObject, gpuDescriptors, descriptorIndices); EXPORT_STRUCT_NPOD(DescriptorSetLayoutBinding, binding, descriptorType, count, stageFlags, immutableSamplers); EXPORT_STRUCT_POD(DescriptorSetLayoutInfo, bindings); EXPORT_STRUCT_NPOD(DescriptorSetInfo, layout); @@ -174,6 +177,7 @@ EMSCRIPTEN_BINDINGS(WEBGPU_DEVICE_WASM_EXPORT) { // /* pure_virtual(), */ allow_raw_pointer>()) // .function("flushCommands", &Device::flushCommands, allow_raw_pointers()) .function("present", select_overload(&Device::present)) + .function("enableAutoBarrier", &Device::enableAutoBarrier) .property("queue", &Device::getQueue) .property("commandBuffer", &Device::getCommandBuffer) .property("capabilities", &Device::getCapabilities) @@ -190,8 +194,7 @@ EMSCRIPTEN_BINDINGS(WEBGPU_DEVICE_WASM_EXPORT) { .function("acquire", select_overload &)>(&CCWGPUDevice::acquire), /* pure_virtual(), */ allow_raw_pointer>()) - .function("createShaderNative", select_overload(&CCWGPUDevice::createShader), - /* pure_virtual(), */ allow_raw_pointer>()) + .function("createShaderNative", select_overload(&CCWGPUDevice::createShader)) .function("copyTextureToBuffers", select_overload(&CCWGPUDevice::copyTextureToBuffers), /* pure_virtual(), */ allow_raw_pointers()) .function("copyBuffersToTexture", select_overload &)>(&CCWGPUDevice::copyBuffersToTexture), @@ -288,6 +291,7 @@ EMSCRIPTEN_BINDINGS(WEBGPU_DEVICE_WASM_EXPORT) { .function("update", &DescriptorSet::update) .function("bindBuffer", select_overload(&DescriptorSet::bindBuffer), allow_raw_pointer>()) .function("bindBuffer", select_overload(&DescriptorSet::bindBuffer), allow_raw_pointer>()) + .function("bindBuffer", select_overload(&DescriptorSet::bindBuffer), allow_raw_pointer>()) .function("bindTexture", select_overload(&DescriptorSet::bindTexture), allow_raw_pointer>()) .function("bindTexture", select_overload(&DescriptorSet::bindTexture), allow_raw_pointer>()) .function("bindSampler", select_overload(&DescriptorSet::bindSampler), allow_raw_pointer>()) @@ -301,6 +305,8 @@ EMSCRIPTEN_BINDINGS(WEBGPU_DEVICE_WASM_EXPORT) { .property("layout", &DescriptorSet::getLayout) .property("objectID", select_overload(&DescriptorSet::getObjectID)); class_>("CCWGPUDescriptorSet") + // .property("gpuDescriptorSet", &CCWGPUDescriptorSet::gpuDescriptors) + .function("updateFrom", &CCWGPUDescriptorSet::setGpuDescriptors) .constructor<>(); class_("PipelineLayout") @@ -312,7 +318,6 @@ EMSCRIPTEN_BINDINGS(WEBGPU_DEVICE_WASM_EXPORT) { .constructor<>(); class_("Shader") - .function("initialize", &Shader::initialize) .function("destroy", &Shader::destroy) .property("name", &Shader::getName) .property("attributes", &Shader::getAttributes) @@ -326,6 +331,8 @@ EMSCRIPTEN_BINDINGS(WEBGPU_DEVICE_WASM_EXPORT) { .property("subpassInputs", &Shader::getSubpassInputs) .property("objectID", select_overload(&Shader::getObjectID)); class_>("CCWGPUShader") + .function("initialize", &CCWGPUShader::initWithWGSL) + .function("reflectBinding", &CCWGPUShader::reflectBinding) .constructor<>(); class_("InputAssembler") diff --git a/native/cocos/renderer/gfx-wgpu/WGPUObject.h b/native/cocos/renderer/gfx-wgpu/WGPUObject.h index 819c3390847..4371c12163f 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUObject.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUObject.h @@ -42,7 +42,6 @@ namespace cc { namespace gfx { constexpr uint8_t CC_WGPU_MAX_ATTACHMENTS = 16; -constexpr uint8_t CC_WGPU_MAX_STREAM = 256; // not sure constexpr decltype(nullptr) wgpuDefaultHandle = nullptr; constexpr ccstd::hash_t WGPU_HASH_SEED = 0x811C9DC5; constexpr uint8_t CC_WGPU_MAX_FRAME_COUNT = 3; @@ -101,6 +100,7 @@ struct CCWGPUTextureObject { WGPUTexture wgpuTexture = wgpuDefaultHandle; WGPUTextureView wgpuTextureView = wgpuDefaultHandle; WGPUTextureView selfView = wgpuDefaultHandle; + std::vector planeViews; }; // The indirect drawIndexed parameters encoded in the buffer must be a tightly packed block @@ -161,13 +161,14 @@ struct CCWGPUSamplerObject { struct CCWGPUBindGroupLayoutObject { WGPUBindGroupLayout bindGroupLayout = wgpuDefaultHandle; - ccstd::vector bindGroupLayoutEntries; + ccstd::map bindGroupLayoutEntries; }; struct CCWGPUBindGroupObject { WGPUBindGroup bindgroup = wgpuDefaultHandle; ccstd::vector bindGroupEntries; - ccstd::set bindingSet; + ccstd::set bindingSet; // bindingInDesc + ccstd::set bindingInShader; // bindingInShader }; struct CCWGPUPipelineLayoutObject { @@ -182,11 +183,14 @@ struct CCWGPUPipelineStateObject { uint32_t maxAttrLength = 0; }; +using BindingList = ccstd::vector; struct CCWGPUShaderObject { ccstd::string name; WGPUShaderModule wgpuShaderVertexModule = wgpuDefaultHandle; WGPUShaderModule wgpuShaderFragmentModule = wgpuDefaultHandle; WGPUShaderModule wgpuShaderComputeModule = wgpuDefaultHandle; + + ccstd::vector bindings; }; struct CCWGPUInputAssemblerObject { @@ -244,6 +248,7 @@ struct CCWGPUCommandBufferObject { WGPURenderPassDescriptor renderPassDescriptor; CCWGPUStateCache stateCache; + ccstd::vector computeCmdBuffs; ccstd::unordered_map redundantVertexBufferMap; }; diff --git a/native/cocos/renderer/gfx-wgpu/WGPUPipelineLayout.h b/native/cocos/renderer/gfx-wgpu/WGPUPipelineLayout.h index 819bb01c1fe..c0bb9068af1 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUPipelineLayout.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUPipelineLayout.h @@ -64,7 +64,7 @@ class CCWGPUPipelineLayout final : public PipelineLayout { ccstd::hash_t _hash{0}; - friend void createPipelineLayoutFallback(const ccstd::vector &descriptorSets, PipelineLayout *pipelineLayout); + friend void createPipelineLayoutFallback(const ccstd::vector &descriptorSets, PipelineLayout *pipelineLayout, bool skipEmpty); }; } // namespace gfx diff --git a/native/cocos/renderer/gfx-wgpu/WGPUPipelineState.cpp b/native/cocos/renderer/gfx-wgpu/WGPUPipelineState.cpp index 03fc57270f8..634e32ac987 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUPipelineState.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUPipelineState.cpp @@ -24,6 +24,7 @@ #include "WGPUPipelineState.h" #include +#include #include #include "WGPUDescriptorSetLayout.h" #include "WGPUDevice.h" @@ -101,10 +102,10 @@ ccstd::hash_t hash(const WGPURenderPipelineDescriptor &desc) { hash_combine(hash, desc.fragment->constants[i].key); hash_combine(hash, desc.fragment->constants[i].value); } + hash_combine(hash, desc.fragment->targetCount); for (uint32_t i = 0; i < desc.fragment->targetCount; ++i) { hash_combine(hash, desc.fragment->targets[i].format); - hash_combine(hash, desc.fragment->targets[i].blend); if (desc.fragment->targets[i].blend) { hash_combine(hash, desc.fragment->targets[i].blend->color.operation); hash_combine(hash, desc.fragment->targets[i].blend->color.srcFactor); @@ -115,8 +116,6 @@ ccstd::hash_t hash(const WGPURenderPipelineDescriptor &desc) { } hash_combine(hash, desc.fragment->targets[i].writeMask); } - } else { - hash_combine(hash, 0); } return hash; } @@ -295,7 +294,7 @@ void CCWGPUPipelineState::prepare(const ccstd::set &setInUse) { .nextInChain = nullptr, .format = toWGPUTextureFormat(dsAttachment.format), .depthWriteEnabled = _depthStencilState.depthWrite != 0, - .depthCompare = _depthStencilState.depthTest ? toWGPUCompareFunction(_depthStencilState.depthFunc) : WGPUCompareFunction_Undefined, + .depthCompare = _depthStencilState.depthTest ? toWGPUCompareFunction(_depthStencilState.depthFunc) : WGPUCompareFunction_Always, .stencilFront = stencilFront, .stencilBack = stencilBack, .stencilReadMask = _depthStencilState.stencilReadMaskFront, diff --git a/native/cocos/renderer/gfx-wgpu/WGPUQueue.cpp b/native/cocos/renderer/gfx-wgpu/WGPUQueue.cpp index 7ab53a0641a..c42bba1cde8 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUQueue.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUQueue.cpp @@ -82,17 +82,26 @@ void CCWGPUQueue::submit(CommandBuffer *const *cmdBuffs, uint32_t count) { // CCWGPUDevice::getInstance()->stagingBuffer()->unmap(); ccstd::vector wgpuCmdBuffs(count); + ccstd::vector wgpuCmdEncoders(count); for (size_t i = 0; i < count; ++i) { const auto *cmdBuff = static_cast(cmdBuffs[i]); wgpuCmdBuffs[i] = cmdBuff->gpuCommandBufferObject()->wgpuCommandBuffer; + wgpuCmdEncoders[i] = cmdBuff->gpuCommandBufferObject()->wgpuCommandEncoder; _numDrawCalls += cmdBuff->getNumDrawCalls(); _numInstances += cmdBuff->getNumInstances(); _numTriangles += cmdBuff->getNumTris(); + + const_cast(cmdBuff)->reset(); } wgpuQueueSubmit(_gpuQueueObject->wgpuQueue, count, wgpuCmdBuffs.data()); - std::for_each(wgpuCmdBuffs.begin(), wgpuCmdBuffs.end(), [](auto wgpuCmdBuffer) { wgpuCommandBufferRelease(wgpuCmdBuffer); }); + std::for_each(wgpuCmdBuffs.begin(), wgpuCmdBuffs.end(), [](auto wgpuCmdBuffer) { + wgpuCommandBufferRelease(wgpuCmdBuffer); + }); + std::for_each(wgpuCmdEncoders.begin(), wgpuCmdEncoders.end(), [](auto wgpuCmdEncoder) { + wgpuCommandEncoderRelease(wgpuCmdEncoder); + }); auto *recycleBin = CCWGPUDevice::getInstance()->recycleBin(); wgpuQueueOnSubmittedWorkDone(_gpuQueueObject->wgpuQueue, 0, wgpuQueueSubmitCallback, recycleBin); diff --git a/native/cocos/renderer/gfx-wgpu/WGPUSampler.cpp b/native/cocos/renderer/gfx-wgpu/WGPUSampler.cpp index 65e1c662f57..ff2523e39f1 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUSampler.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUSampler.cpp @@ -39,15 +39,16 @@ CCWGPUSampler *dftUnfilterableSampler = nullptr; using namespace emscripten; CCWGPUSampler::CCWGPUSampler(const SamplerInfo &info) : Sampler(info) { + ccstd::string tag = std::to_string(static_cast(info.minFilter)) + " " + std::to_string(static_cast(info.magFilter)) + " " + std::to_string(static_cast(info.mipFilter)); WGPUSamplerDescriptor descriptor = { .nextInChain = nullptr, - .label = (std::to_string(static_cast(info.minFilter)) + " " + std::to_string(static_cast(info.magFilter)) + " " + std::to_string(static_cast(info.mipFilter))).c_str(), + .label = tag.c_str(), .addressModeU = toWGPUAddressMode(info.addressU), .addressModeV = toWGPUAddressMode(info.addressV), .addressModeW = toWGPUAddressMode(info.addressW), .magFilter = toWGPUFilterMode(info.magFilter), .minFilter = toWGPUFilterMode(info.minFilter), - .mipmapFilter = toWGPUFilterMode(info.mipFilter), + .mipmapFilter = toWGPUMipmapFilterMode(info.mipFilter), .lodMinClamp = 0.0f, .lodMaxClamp = std::numeric_limits::max(), .compare = WGPUCompareFunction_Undefined, // toWGPUCompareFunction(info.cmpFunc), diff --git a/native/cocos/renderer/gfx-wgpu/WGPUShader.cpp b/native/cocos/renderer/gfx-wgpu/WGPUShader.cpp index 6bbc29381da..9173e6d5c6f 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUShader.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUShader.cpp @@ -27,6 +27,7 @@ #include "WGPUDevice.h" #include "WGPUObject.h" #include "WGPUUtils.h" +#include "gfx-base/GFXDef-common.h" #define USE_NATIVE_SPIRV 0 #if USE_NATIVE_SPIRV #include "gfx-base/SPIRVUtils.h" @@ -87,6 +88,41 @@ void CCWGPUShader::initialize(const ShaderInfo &info, const std::vectorname = info.name; + for (size_t i = 0; i < info.stages.size(); i++) { + const auto &stage = info.stages[i]; + WGPUShaderModuleWGSLDescriptor wgslDesc = {}; + wgslDesc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; + wgslDesc.code = stage.source.c_str(); + WGPUShaderModuleDescriptor desc = {}; + desc.nextInChain = reinterpret_cast(&wgslDesc); + desc.label = _name.c_str(); + if (stage.stage == ShaderStageFlagBit::VERTEX) { + _gpuShaderObject->wgpuShaderVertexModule = wgpuDeviceCreateShaderModule(CCWGPUDevice::getInstance()->gpuDeviceObject()->wgpuDevice, &desc); + } else if (stage.stage == ShaderStageFlagBit::FRAGMENT) { + _gpuShaderObject->wgpuShaderFragmentModule = wgpuDeviceCreateShaderModule(CCWGPUDevice::getInstance()->gpuDeviceObject()->wgpuDevice, &desc); + } else if (stage.stage == ShaderStageFlagBit::COMPUTE) { + _gpuShaderObject->wgpuShaderComputeModule = wgpuDeviceCreateShaderModule(CCWGPUDevice::getInstance()->gpuDeviceObject()->wgpuDevice, &desc); + } else { + printf("unsupport shader stage."); + } + } +} + const std::string spirvProcess(const uint32_t *data, size_t size, const UniformSamplerTextureList &list) { #if USE_NATIVE_SPIRV spirv_cross::CompilerMSL compiler(data, size); @@ -140,6 +176,7 @@ const std::string spirvProcess(const uint32_t *data, size_t size, const UniformS } void CCWGPUShader::doInit(const ShaderInfo &info) { + initWithWGSL(info); #if USE_NATIVE_SPIRV _gpuShaderObject = ccnew CCWGPUShaderObject; if (!spirv) { @@ -194,4 +231,4 @@ void CCWGPUShader::doDestroy() { } } // namespace gfx -} // namespace cc \ No newline at end of file +} // namespace cc diff --git a/native/cocos/renderer/gfx-wgpu/WGPUShader.h b/native/cocos/renderer/gfx-wgpu/WGPUShader.h index 023084d8e96..8ba4d93dccd 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUShader.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUShader.h @@ -23,6 +23,7 @@ ****************************************************************************/ #pragma once +#include "gfx-base/GFXDef-common.h" #ifdef CC_WGPU_WASM #include "WGPUDef.h" #endif @@ -45,8 +46,12 @@ class CCWGPUShader final : public Shader { // ems export EXPORT_EMS( - void initialize(const ShaderInfo &info, emscripten::val &spirvs);) + void initialize(const ShaderInfo &info, emscripten::val &spirvs); + void reflectBinding(const emscripten::val& bindings); + ) + void initialize(const ShaderInfo &info, const std::vector> &spirvs); + void initWithWGSL(const ShaderInfo& info); protected: void doInit(const ShaderInfo &info) override; diff --git a/native/cocos/renderer/gfx-wgpu/WGPUTexture.cpp b/native/cocos/renderer/gfx-wgpu/WGPUTexture.cpp index 77f723e0c13..efadb8094dd 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUTexture.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUTexture.cpp @@ -35,6 +35,38 @@ namespace gfx { namespace { CCWGPUTexture *dftCommonTexture = nullptr; CCWGPUTexture *dftStorageTexture = nullptr; + +void generatePlaneViews(CCWGPUTexture *texture) { + if (texture->getFormat() == Format::DEPTH_STENCIL) { + auto *gpuTextureObj = texture->gpuTextureObject(); + WGPUTextureViewDescriptor depthView = { + .nextInChain = nullptr, + .label = nullptr, + .format = WGPUTextureFormat_Depth24Plus, + .dimension = WGPUTextureViewDimension_2D, + .baseMipLevel = 0, + .mipLevelCount = 1, + .baseArrayLayer = 0, + .arrayLayerCount = 1, + .aspect = WGPUTextureAspect_DepthOnly, + }; + gpuTextureObj->planeViews.emplace_back(wgpuTextureCreateView(gpuTextureObj->wgpuTexture, &depthView)); + + WGPUTextureViewDescriptor stencilView = { + .nextInChain = nullptr, + .label = nullptr, + .format = WGPUTextureFormat_Stencil8, + .dimension = WGPUTextureViewDimension_2D, + .baseMipLevel = 0, + .mipLevelCount = 1, + .baseArrayLayer = 0, + .arrayLayerCount = 1, + .aspect = WGPUTextureAspect_StencilOnly, + }; + gpuTextureObj->planeViews.emplace_back(wgpuTextureCreateView(gpuTextureObj->wgpuTexture, &stencilView)); + } +} + } // namespace using namespace emscripten; @@ -84,6 +116,7 @@ void CCWGPUTexture::doInit(const TextureInfo &info) { }; _gpuTextureObj->selfView = wgpuTextureCreateView(_gpuTextureObj->wgpuTexture, &texViewDesc); + generatePlaneViews(this); _internalChanged = true; } // namespace gfx @@ -103,6 +136,9 @@ void CCWGPUTexture::doInit(const TextureViewInfo &info) { auto *ccTexture = static_cast(info.texture); WGPUTexture wgpuTexture = ccTexture->gpuTextureObject()->wgpuTexture; _gpuTextureObj->selfView = _gpuTextureObj->wgpuTextureView = wgpuTextureCreateView(wgpuTexture, &descriptor); + + generatePlaneViews(this); + _internalChanged = true; } @@ -137,6 +173,8 @@ void CCWGPUTexture::doInit(const SwapchainTextureInfo &info) { .aspect = aspect, }; _gpuTextureObj->selfView = wgpuTextureCreateView(_gpuTextureObj->wgpuTexture, &texViewDesc); + + generatePlaneViews(this); } else { _gpuTextureObj->selfView = wgpuSwapChainGetCurrentTextureView(swapchain->gpuSwapchainObject()->wgpuSwapChain); } @@ -144,6 +182,13 @@ void CCWGPUTexture::doInit(const SwapchainTextureInfo &info) { } } +void *CCWGPUTexture::getPlaneView(uint32_t plane) { + if (_info.format == Format::DEPTH_STENCIL || _viewInfo.format == Format::DEPTH_STENCIL) { + return _gpuTextureObj->planeViews[plane]; + } + return _gpuTextureObj->selfView; +} + void CCWGPUTexture::doDestroy() { if (_gpuTextureObj) { if (_gpuTextureObj->wgpuTexture) { @@ -156,6 +201,11 @@ void CCWGPUTexture::doDestroy() { if (_gpuTextureObj->selfView && !_isTextureView) { wgpuTextureViewRelease(_gpuTextureObj->selfView); } + if (!_gpuTextureObj->planeViews.empty()) { + for (auto view : _gpuTextureObj->planeViews) { + wgpuTextureViewRelease(view); + } + } delete _gpuTextureObj; _gpuTextureObj = nullptr; } diff --git a/native/cocos/renderer/gfx-wgpu/WGPUTexture.h b/native/cocos/renderer/gfx-wgpu/WGPUTexture.h index 6d448128d64..258c3dd44ed 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUTexture.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUTexture.h @@ -63,6 +63,8 @@ class CCWGPUTexture final : public Texture { inline auto getTextureSamples() const { return _info.samples; }; inline auto getTextureFlags() const { return _info.flags; }; + void* getPlaneView(uint32_t plane); + protected: void doInit(const TextureInfo &info) override; void doInit(const TextureViewInfo &info) override; diff --git a/native/cocos/renderer/gfx-wgpu/WGPUUtils.cpp b/native/cocos/renderer/gfx-wgpu/WGPUUtils.cpp index f41674337bc..bfe1ec2c066 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUUtils.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUUtils.cpp @@ -33,7 +33,7 @@ namespace cc::gfx { -void createPipelineLayoutFallback(const ccstd::vector& descriptorSets, PipelineLayout* pipelineLayout) { +void createPipelineLayoutFallback(const ccstd::vector& descriptorSets, PipelineLayout* pipelineLayout, bool skipEmpty) { ccstd::hash_t hash = descriptorSets.size() * 2 + 1; ccstd::hash_combine(hash, descriptorSets.size()); std::string label = ""; @@ -41,16 +41,17 @@ void createPipelineLayoutFallback(const ccstd::vector& descripto for (size_t i = 0; i < descriptorSets.size(); ++i) { auto* descriptorSet = static_cast(descriptorSets[i]); if (descriptorSet && descriptorSet->getHash() != 0) { - auto* descriptorSetLayout = static_cast(descriptorSet->getLayout()); + auto* tLayout = const_cast(descriptorSet->getLayout()); + auto* descriptorSetLayout = static_cast(tLayout); auto* wgpuBindGroupLayout = static_cast(CCWGPUDescriptorSetLayout::getBindGroupLayoutByHash(descriptorSet->getHash())); descriptorSetLayouts.push_back(wgpuBindGroupLayout); ccstd::hash_combine(hash, i); ccstd::hash_combine(hash, descriptorSet->getHash()); - label += std::to_string(descriptorSet->getHash()) + "-" + descriptorSet->label + "-" + std::to_string(descriptorSetLayout->getHash()) + " "; - } else { - descriptorSetLayouts.push_back(static_cast(CCWGPUDescriptorSetLayout::defaultBindGroupLayout())); + //label += std::to_string(descriptorSet->getHash()) + "-" + descriptorSet->label + "-" + std::to_string(descriptorSetLayout->getHash()) + " "; + } else if (!skipEmpty) { + auto bindgroup = static_cast(CCWGPUDescriptorSetLayout::defaultBindGroupLayout()); + descriptorSetLayouts.push_back(bindgroup); ccstd::hash_combine(hash, i); - ccstd::hash_combine(hash, 0); } } @@ -140,23 +141,23 @@ fn frag_main() -> @location(0) vec4 { } )"; - WGPUShaderModuleWGSLDescriptor wgslShaderDescVert; - wgslShaderDescVert.source = clearQuadVert; + WGPUShaderModuleWGSLDescriptor wgslShaderDescVert{}; + wgslShaderDescVert.code = clearQuadVert; wgslShaderDescVert.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; WGPUShaderModuleDescriptor shaderDescVert; shaderDescVert.nextInChain = reinterpret_cast(&wgslShaderDescVert); shaderDescVert.label = "clearQuadVert"; clearPassData.vertShader = wgpuDeviceCreateShaderModule(wgpuDevice, &shaderDescVert); - WGPUShaderModuleWGSLDescriptor wgslShaderDescFrag; - wgslShaderDescFrag.source = clearQuadFrag; + WGPUShaderModuleWGSLDescriptor wgslShaderDescFrag{}; + wgslShaderDescFrag.code = clearQuadFrag; wgslShaderDescFrag.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; WGPUShaderModuleDescriptor shaderDescFrag; shaderDescFrag.nextInChain = reinterpret_cast(&wgslShaderDescFrag); shaderDescFrag.label = "clearQuadFrag"; clearPassData.fragShader = wgpuDeviceCreateShaderModule(wgpuDevice, &shaderDescFrag); - WGPUBindGroupLayoutEntry bufferEntry; + WGPUBindGroupLayoutEntry bufferEntry{}; bufferEntry.binding = 0; bufferEntry.visibility = WGPUShaderStage_Fragment; bufferEntry.texture.sampleType = WGPUTextureSampleType_Undefined; @@ -166,44 +167,44 @@ fn frag_main() -> @location(0) vec4 { bufferEntry.sampler.type = WGPUSamplerBindingType_Undefined; bufferEntry.storageTexture.access = WGPUStorageTextureAccess_Undefined; - WGPUBindGroupLayoutDescriptor bgLayoutDesc; + WGPUBindGroupLayoutDescriptor bgLayoutDesc{}; bgLayoutDesc.label = "clearPassBGLayout"; bgLayoutDesc.entryCount = 1; bgLayoutDesc.entries = &bufferEntry; clearPassData.bindGroupLayout = wgpuDeviceCreateBindGroupLayout(wgpuDevice, &bgLayoutDesc); - WGPUPipelineLayoutDescriptor pipelineLayoutDesc; + WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; pipelineLayoutDesc.label = "clearPassPipelineLayout"; pipelineLayoutDesc.bindGroupLayoutCount = 1; pipelineLayoutDesc.bindGroupLayouts = &clearPassData.bindGroupLayout; clearPassData.pipelineLayout = wgpuDeviceCreatePipelineLayout(wgpuDevice, &pipelineLayoutDesc); - WGPUVertexState vertexState; + WGPUVertexState vertexState{}; vertexState.module = clearPassData.vertShader; vertexState.entryPoint = "vert_main"; - WGPUPrimitiveState primitiveState; + WGPUPrimitiveState primitiveState{}; primitiveState.topology = WGPUPrimitiveTopology_TriangleList; primitiveState.stripIndexFormat = WGPUIndexFormat_Undefined; primitiveState.frontFace = WGPUFrontFace_CCW; primitiveState.cullMode = WGPUCullMode_None; - WGPUColorTargetState colorState; + WGPUColorTargetState colorState{}; colorState.format = format; colorState.writeMask = WGPUColorWriteMask_All; - WGPUFragmentState fragState; + WGPUFragmentState fragState{}; fragState.module = clearPassData.fragShader; fragState.entryPoint = "frag_main"; fragState.targetCount = 1; fragState.targets = &colorState; - WGPUMultisampleState multisample; + WGPUMultisampleState multisample{}; multisample.count = 1; multisample.alphaToCoverageEnabled = false; multisample.mask = 0xFFFFFFFF; - WGPURenderPipelineDescriptor pipelineDesc; + WGPURenderPipelineDescriptor pipelineDesc{}; pipelineDesc.label = "clearPassPipeline"; pipelineDesc.layout = clearPassData.pipelineLayout; pipelineDesc.vertex = vertexState; @@ -223,7 +224,7 @@ fn frag_main() -> @location(0) vec4 { auto dstView = wgpuTextureView; - WGPUBufferDescriptor bufferDesc; + WGPUBufferDescriptor bufferDesc{}; bufferDesc.usage = WGPUBufferUsage_Uniform; bufferDesc.size = 16; bufferDesc.mappedAtCreation = true; @@ -234,8 +235,7 @@ fn frag_main() -> @location(0) vec4 { memcpy(mappedBuffer, colorArr, 16); wgpuBufferUnmap(uniformBuffer); - WGPUBindGroupEntry entry; - entry.nextInChain = nullptr; + WGPUBindGroupEntry entry{}; entry.binding = 0; entry.sampler = wgpuDefaultHandle; entry.buffer = uniformBuffer; @@ -243,22 +243,20 @@ fn frag_main() -> @location(0) vec4 { entry.size = 16; entry.textureView = wgpuDefaultHandle; - WGPUBindGroupDescriptor bindgroupDesc; + WGPUBindGroupDescriptor bindgroupDesc{}; bindgroupDesc.layout = clearPassData.bindGroupLayout; bindgroupDesc.entryCount = 1; bindgroupDesc.entries = &entry; auto bindGroup = wgpuDeviceCreateBindGroup(wgpuDevice, &bindgroupDesc); - WGPURenderPassColorAttachment colorAttachment; + WGPURenderPassColorAttachment colorAttachment{}; colorAttachment.view = dstView; colorAttachment.resolveTarget = wgpuDefaultHandle; colorAttachment.loadOp = WGPULoadOp_Load; colorAttachment.storeOp = WGPUStoreOp_Store; colorAttachment.clearValue = {0.88, 0.88, 0.88, 1.0}; - WGPURenderPassDescriptor rpDesc; - rpDesc.nextInChain = nullptr; - rpDesc.label = nullptr; + WGPURenderPassDescriptor rpDesc{}; rpDesc.colorAttachmentCount = 1; rpDesc.colorAttachments = &colorAttachment; rpDesc.depthStencilAttachment = nullptr; @@ -347,37 +345,37 @@ fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { } )"; - WGPUSamplerDescriptor samplerDesc; + WGPUSamplerDescriptor samplerDesc{}; samplerDesc.label = "filterSampler"; samplerDesc.addressModeU = WGPUAddressMode_MirrorRepeat; samplerDesc.addressModeV = WGPUAddressMode_MirrorRepeat; samplerDesc.addressModeW = WGPUAddressMode_MirrorRepeat; samplerDesc.magFilter = WGPUFilterMode_Linear; samplerDesc.minFilter = WGPUFilterMode_Linear; - samplerDesc.mipmapFilter = WGPUFilterMode_Linear; + samplerDesc.mipmapFilter = WGPUMipmapFilterMode_Linear; samplerDesc.lodMinClamp = 0.0; samplerDesc.lodMaxClamp = 32.0; samplerDesc.compare = WGPUCompareFunction_Undefined; samplerDesc.maxAnisotropy = 1; mipmapData.sampler = wgpuDeviceCreateSampler(wgpuDevice, &samplerDesc); - WGPUShaderModuleWGSLDescriptor wgslShaderDescVert; - wgslShaderDescVert.source = textureQuadVert; + WGPUShaderModuleWGSLDescriptor wgslShaderDescVert{}; + wgslShaderDescVert.code = textureQuadVert; wgslShaderDescVert.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; WGPUShaderModuleDescriptor shaderDescVert; shaderDescVert.nextInChain = reinterpret_cast(&wgslShaderDescVert); shaderDescVert.label = "textureQuadVert"; mipmapData.vertShader = wgpuDeviceCreateShaderModule(wgpuDevice, &shaderDescVert); - WGPUShaderModuleWGSLDescriptor wgslShaderDescFrag; - wgslShaderDescFrag.source = textureQuadFrag; + WGPUShaderModuleWGSLDescriptor wgslShaderDescFrag{}; + wgslShaderDescFrag.code = textureQuadFrag; wgslShaderDescFrag.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; WGPUShaderModuleDescriptor shaderDescFrag; shaderDescFrag.nextInChain = reinterpret_cast(&wgslShaderDescFrag); shaderDescFrag.label = "textureQuadFrag"; mipmapData.fragShader = wgpuDeviceCreateShaderModule(wgpuDevice, &shaderDescFrag); - WGPUBindGroupLayoutEntry samplerEntry; + WGPUBindGroupLayoutEntry samplerEntry{}; samplerEntry.binding = 0; samplerEntry.visibility = WGPUShaderStage_Fragment; samplerEntry.sampler.type = WGPUSamplerBindingType_Filtering; @@ -385,7 +383,7 @@ fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { samplerEntry.texture.sampleType = WGPUTextureSampleType_Undefined; samplerEntry.storageTexture.access = WGPUStorageTextureAccess_Undefined; - WGPUBindGroupLayoutEntry textureEntry; + WGPUBindGroupLayoutEntry textureEntry{}; textureEntry.binding = 1; textureEntry.visibility = WGPUShaderStage_Fragment; textureEntry.texture.sampleType = textureSampleTypeTrait(ccTexture->getFormat()); @@ -396,44 +394,46 @@ fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { textureEntry.storageTexture.access = WGPUStorageTextureAccess_Undefined; WGPUBindGroupLayoutEntry entries[2] = {samplerEntry, textureEntry}; - WGPUBindGroupLayoutDescriptor bgLayoutDesc; + WGPUBindGroupLayoutDescriptor bgLayoutDesc{}; bgLayoutDesc.label = "fullscreenTexturedQuadBGLayout"; bgLayoutDesc.entryCount = 2; bgLayoutDesc.entries = entries; mipmapData.bindGroupLayout = wgpuDeviceCreateBindGroupLayout(wgpuDevice, &bgLayoutDesc); - WGPUPipelineLayoutDescriptor pipelineLayoutDesc; + WGPUPipelineLayoutDescriptor pipelineLayoutDesc{}; pipelineLayoutDesc.label = "fullscreenTexturedQuadPipelineLayout"; pipelineLayoutDesc.bindGroupLayoutCount = 1; pipelineLayoutDesc.bindGroupLayouts = &mipmapData.bindGroupLayout; mipmapData.pipelineLayout = wgpuDeviceCreatePipelineLayout(wgpuDevice, &pipelineLayoutDesc); - WGPUVertexState vertexState; + WGPUVertexState vertexState{}; vertexState.module = mipmapData.vertShader; vertexState.entryPoint = "vert_main"; + vertexState.bufferCount = 0; + vertexState.buffers = nullptr; - WGPUPrimitiveState primitiveState; + WGPUPrimitiveState primitiveState{}; primitiveState.topology = WGPUPrimitiveTopology_TriangleList; primitiveState.stripIndexFormat = WGPUIndexFormat_Undefined; primitiveState.frontFace = WGPUFrontFace_CCW; primitiveState.cullMode = WGPUCullMode_None; - WGPUColorTargetState colorState; + WGPUColorTargetState colorState{}; colorState.format = format; colorState.writeMask = WGPUColorWriteMask_All; - WGPUFragmentState fragState; + WGPUFragmentState fragState{}; fragState.module = mipmapData.fragShader; fragState.entryPoint = "frag_main"; fragState.targetCount = 1; fragState.targets = &colorState; - WGPUMultisampleState multisample; + WGPUMultisampleState multisample{}; multisample.count = 1; multisample.alphaToCoverageEnabled = false; multisample.mask = 0xFFFFFFFF; - WGPURenderPipelineDescriptor pipelineDesc; + WGPURenderPipelineDescriptor pipelineDesc{}; pipelineDesc.label = "fullscreenTexturedQuadPipeline"; pipelineDesc.layout = mipmapData.pipelineLayout; pipelineDesc.vertex = vertexState; @@ -444,7 +444,7 @@ fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { mipmapData.pipeline = wgpuDeviceCreateRenderPipeline(wgpuDevice, &pipelineDesc); } - WGPUTextureViewDescriptor desc; + WGPUTextureViewDescriptor desc{}; desc.format = format; desc.dimension = WGPUTextureViewDimension_2D; desc.baseMipLevel = fromLevel; @@ -481,7 +481,7 @@ fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { entries[1].buffer = wgpuDefaultHandle; entries[1].sampler = wgpuDefaultHandle; - WGPUBindGroupDescriptor bindgroupDesc; + WGPUBindGroupDescriptor bindgroupDesc{}; bindgroupDesc.layout = mipmapData.bindGroupLayout; bindgroupDesc.entryCount = 2; bindgroupDesc.entries = entries; @@ -494,8 +494,7 @@ fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { colorAttachment.storeOp = WGPUStoreOp_Store; colorAttachment.clearValue = {0.88, 0.88, 0.88, 1.0}; - WGPURenderPassDescriptor rpDesc; - rpDesc.nextInChain = nullptr; + WGPURenderPassDescriptor rpDesc{}; rpDesc.label = nullptr; rpDesc.colorAttachmentCount = 1; rpDesc.colorAttachments = &colorAttachment; diff --git a/native/cocos/renderer/gfx-wgpu/WGPUUtils.h b/native/cocos/renderer/gfx-wgpu/WGPUUtils.h index f79f50c4896..eb3e7839a36 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUUtils.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUUtils.h @@ -309,6 +309,19 @@ static WGPUAddressMode toWGPUAddressMode(Address addrMode) { } } +static WGPUMipmapFilterMode toWGPUMipmapFilterMode(Filter filter) { + switch (filter) { + case Filter::NONE: + return WGPUMipmapFilterMode::WGPUMipmapFilterMode_Nearest; + case Filter::POINT: + return WGPUMipmapFilterMode::WGPUMipmapFilterMode_Nearest; + case Filter::LINEAR: + return WGPUMipmapFilterMode::WGPUMipmapFilterMode_Linear; + case Filter::ANISOTROPIC: + return WGPUMipmapFilterMode::WGPUMipmapFilterMode_Linear; + } +} + static WGPUFilterMode toWGPUFilterMode(Filter filter) { switch (filter) { case Filter::NONE: @@ -644,7 +657,7 @@ void genMipMap(Texture* texture, uint8_t fromLevel, uint8_t levelCount, uint32_t class DescriptorSet; class PipelineLayout; // descriptor set layout in descriptor set not consistent with the binding in pipeline layout. -void createPipelineLayoutFallback(const ccstd::vector& descriptorSets, PipelineLayout* pipelineLayout); +void createPipelineLayoutFallback(const ccstd::vector& descriptorSets, PipelineLayout* pipelineLayout, bool skipEmpty = false); class Texture; class CommandBuffer;