Compare commits
2 Commits
validation
...
jc/enableT
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7da1c0ad5 | ||
|
|
04ff88fab2 |
@@ -283,6 +283,8 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
|||||||
src/webgpu/WebGPUSwapChain.h
|
src/webgpu/WebGPUSwapChain.h
|
||||||
src/webgpu/WebGPUTexture.cpp
|
src/webgpu/WebGPUTexture.cpp
|
||||||
src/webgpu/WebGPUTexture.h
|
src/webgpu/WebGPUTexture.h
|
||||||
|
src/webgpu/WebGPUTimerQuery.cpp
|
||||||
|
src/webgpu/WebGPUTimerQuery.h
|
||||||
src/webgpu/WebGPUVertexBuffer.cpp
|
src/webgpu/WebGPUVertexBuffer.cpp
|
||||||
src/webgpu/WebGPUVertexBuffer.h
|
src/webgpu/WebGPUVertexBuffer.h
|
||||||
src/webgpu/WebGPUVertexBufferInfo.cpp
|
src/webgpu/WebGPUVertexBufferInfo.cpp
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "WebGPURenderTarget.h"
|
#include "WebGPURenderTarget.h"
|
||||||
#include "WebGPUSwapChain.h"
|
#include "WebGPUSwapChain.h"
|
||||||
#include "WebGPUTexture.h"
|
#include "WebGPUTexture.h"
|
||||||
|
#include "WebGPUTimerQuery.h"
|
||||||
#include "WebGPUVertexBuffer.h"
|
#include "WebGPUVertexBuffer.h"
|
||||||
#include "WebGPUVertexBufferInfo.h"
|
#include "WebGPUVertexBufferInfo.h"
|
||||||
#include <backend/platforms/WebGPUPlatform.h>
|
#include <backend/platforms/WebGPUPlatform.h>
|
||||||
@@ -101,8 +102,9 @@ template class ConcreteDispatcher<WebGPUDriver>;
|
|||||||
void WebGPUDriver::terminate() {
|
void WebGPUDriver::terminate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebGPUDriver::tick(int) {
|
void WebGPUDriver::tick(int /*dummy*/) {
|
||||||
mDevice.Tick();
|
mDevice.Tick();
|
||||||
|
mAdapter.GetInstance().ProcessEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebGPUDriver::beginFrame(int64_t monotonic_clock_ns,
|
void WebGPUDriver::beginFrame(int64_t monotonic_clock_ns,
|
||||||
@@ -216,9 +218,6 @@ void WebGPUDriver::destroyStream(Handle<HwStream> sh) {
|
|||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebGPUDriver::destroyTimerQuery(Handle<HwTimerQuery> tqh) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebGPUDriver::destroyDescriptorSetLayout(
|
void WebGPUDriver::destroyDescriptorSetLayout(
|
||||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle) {
|
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle) {
|
||||||
if (descriptorSetLayoutHandle) {
|
if (descriptorSetLayoutHandle) {
|
||||||
@@ -268,7 +267,31 @@ Handle<HwFence> WebGPUDriver::createFenceS() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Handle<HwTimerQuery> WebGPUDriver::createTimerQueryS() noexcept {
|
Handle<HwTimerQuery> WebGPUDriver::createTimerQueryS() noexcept {
|
||||||
return Handle<HwTimerQuery>((Handle<HwTimerQuery>::HandleId) mNextFakeHandle++);
|
return allocAndConstructHandle<WebGPUTimerQuery, HwTimerQuery>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> timerQueryHandle, int /*dummy*/) {
|
||||||
|
// nothing to do, timer query was constructed in createTimerQueryS
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebGPUDriver::destroyTimerQuery(Handle<HwTimerQuery> timerQueryHandle) {
|
||||||
|
if (timerQueryHandle) {
|
||||||
|
destructHandle<WebGPUTimerQuery>(timerQueryHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TimerQueryResult WebGPUDriver::getTimerQueryValue(Handle<HwTimerQuery> timerQueryHandle, uint64_t* elapsedTime) {
|
||||||
|
auto* timerQuery = handleCast<WebGPUTimerQuery>(timerQueryHandle);
|
||||||
|
return timerQuery->getQueryResult(elapsedTime) ? TimerQueryResult::AVAILABLE
|
||||||
|
: TimerQueryResult::NOT_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebGPUDriver::beginTimerQuery(Handle<HwTimerQuery> timerQueryHandle) {
|
||||||
|
mTimerQuery = handleCast<WebGPUTimerQuery>(timerQueryHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebGPUDriver::endTimerQuery(Handle<HwTimerQuery> timerQueryHandle) {
|
||||||
|
mTimerQuery = handleCast<WebGPUTimerQuery>(timerQueryHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<HwIndexBuffer> WebGPUDriver::createIndexBufferS() noexcept {
|
Handle<HwIndexBuffer> WebGPUDriver::createIndexBufferS() noexcept {
|
||||||
@@ -462,8 +485,6 @@ void WebGPUDriver::createFenceR(Handle<HwFence> fh, int) {
|
|||||||
//todo
|
//todo
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {}
|
|
||||||
|
|
||||||
void WebGPUDriver::createDescriptorSetLayoutR(
|
void WebGPUDriver::createDescriptorSetLayoutR(
|
||||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle,
|
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle,
|
||||||
backend::DescriptorSetLayout&& info) {
|
backend::DescriptorSetLayout&& info) {
|
||||||
@@ -727,10 +748,6 @@ void WebGPUDriver::setupExternalImage(void* image) {
|
|||||||
//todo
|
//todo
|
||||||
}
|
}
|
||||||
|
|
||||||
TimerQueryResult WebGPUDriver::getTimerQueryValue(Handle<HwTimerQuery> tqh, uint64_t* elapsedTime) {
|
|
||||||
return TimerQueryResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebGPUDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
void WebGPUDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||||
//todo
|
//todo
|
||||||
}
|
}
|
||||||
@@ -924,8 +941,10 @@ void WebGPUDriver::commit(Handle<HwSwapChain> sch) {
|
|||||||
mCommandBuffer = mCommandEncoder.Finish(&commandBufferDescriptor);
|
mCommandBuffer = mCommandEncoder.Finish(&commandBufferDescriptor);
|
||||||
assert_invariant(mCommandBuffer);
|
assert_invariant(mCommandBuffer);
|
||||||
mCommandEncoder = nullptr;
|
mCommandEncoder = nullptr;
|
||||||
|
if (mTimerQuery) {
|
||||||
|
mTimerQuery->beginTimeElapsedQuery();
|
||||||
|
}
|
||||||
mQueue.Submit(1, &mCommandBuffer);
|
mQueue.Submit(1, &mCommandBuffer);
|
||||||
|
|
||||||
static bool firstRender = true;
|
static bool firstRender = true;
|
||||||
// For the first frame rendered, we need to make sure the work is done before presenting or we
|
// For the first frame rendered, we need to make sure the work is done before presenting or we
|
||||||
// get a purple flash
|
// get a purple flash
|
||||||
@@ -940,6 +959,15 @@ void WebGPUDriver::commit(Handle<HwSwapChain> sch) {
|
|||||||
<< static_cast<uint32_t>(wStatus);
|
<< static_cast<uint32_t>(wStatus);
|
||||||
}
|
}
|
||||||
firstRender = false;
|
firstRender = false;
|
||||||
|
} else {
|
||||||
|
mQueue.OnSubmittedWorkDone(wgpu::CallbackMode::AllowSpontaneous,
|
||||||
|
[=](wgpu::QueueWorkDoneStatus status) {
|
||||||
|
if (status == wgpu::QueueWorkDoneStatus::Success) {
|
||||||
|
if (mTimerQuery) {
|
||||||
|
mTimerQuery->endTimeElapsedQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
mCommandBuffer = nullptr;
|
mCommandBuffer = nullptr;
|
||||||
mTextureView = nullptr;
|
mTextureView = nullptr;
|
||||||
@@ -1151,12 +1179,6 @@ void WebGPUDriver::scissor(
|
|||||||
//todo
|
//todo
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebGPUDriver::beginTimerQuery(Handle<HwTimerQuery> tqh) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebGPUDriver::endTimerQuery(Handle<HwTimerQuery> tqh) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebGPUDriver::resetState(int) {
|
void WebGPUDriver::resetState(int) {
|
||||||
//todo
|
//todo
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
class WebGPUSwapChain;
|
class WebGPUSwapChain;
|
||||||
|
class WebGPUTimerQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebGPU backend (driver) implementation
|
* WebGPU backend (driver) implementation
|
||||||
@@ -78,6 +79,7 @@ private:
|
|||||||
WebGPURenderTarget* mDefaultRenderTarget = nullptr;
|
WebGPURenderTarget* mDefaultRenderTarget = nullptr;
|
||||||
WebGPURenderTarget* mCurrentRenderTarget = nullptr;
|
WebGPURenderTarget* mCurrentRenderTarget = nullptr;
|
||||||
spd::MipmapGenerator mMipMapGenerator;
|
spd::MipmapGenerator mMipMapGenerator;
|
||||||
|
WebGPUTimerQuery* mTimerQuery = nullptr;
|
||||||
|
|
||||||
tsl::robin_map<uint32_t, wgpu::RenderPipeline> mPipelineMap;
|
tsl::robin_map<uint32_t, wgpu::RenderPipeline> mPipelineMap;
|
||||||
|
|
||||||
@@ -116,6 +118,11 @@ private:
|
|||||||
return mHandleAllocator.allocate<D>();
|
return mHandleAllocator.allocate<D>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename D, typename B, typename... ARGS>
|
||||||
|
Handle<B> allocAndConstructHandle(ARGS&&... args) {
|
||||||
|
return mHandleAllocator.allocateAndConstruct<D>(std::forward<ARGS>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename D, typename B, typename... ARGS>
|
template<typename D, typename B, typename... ARGS>
|
||||||
D* constructHandle(Handle<B>& handle, ARGS&&... args) noexcept {
|
D* constructHandle(Handle<B>& handle, ARGS&&... args) noexcept {
|
||||||
return mHandleAllocator.construct<D>(handle, std::forward<ARGS>(args)...);
|
return mHandleAllocator.construct<D>(handle, std::forward<ARGS>(args)...);
|
||||||
|
|||||||
60
filament/backend/src/webgpu/WebGPUTimerQuery.cpp
Normal file
60
filament/backend/src/webgpu/WebGPUTimerQuery.cpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "WebGPUTimerQuery.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace filament::backend {
|
||||||
|
|
||||||
|
void WebGPUTimerQuery::beginTimeElapsedQuery() {
|
||||||
|
mStatus->elapsedNanoseconds = 0;
|
||||||
|
// Capture the timer query status via a weak_ptr because the WGPUTimerQuery could be destroyed
|
||||||
|
// before the block executes.
|
||||||
|
std::weak_ptr<WebGPUTimerQuery::Status> statusPtr = mStatus;
|
||||||
|
|
||||||
|
if (auto s = statusPtr.lock()) {
|
||||||
|
s->elapsedNanoseconds = std::chrono::steady_clock::now().time_since_epoch().count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebGPUTimerQuery::endTimeElapsedQuery() {
|
||||||
|
// Capture the timer query status via a weak_ptr because the WGPUTimerQuery could be destroyed
|
||||||
|
// before the block executes.
|
||||||
|
if (mStatus->elapsedNanoseconds != 0) {
|
||||||
|
std::weak_ptr<WebGPUTimerQuery::Status> statusPtr = mStatus;
|
||||||
|
if (auto s = statusPtr.lock()) {
|
||||||
|
s->previousElapsed = s->elapsedNanoseconds =
|
||||||
|
std::chrono::steady_clock::now().time_since_epoch().count() -
|
||||||
|
s->elapsedNanoseconds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebGPUTimerQuery::getQueryResult(uint64_t* outElapsedTime) {
|
||||||
|
if (mStatus->previousElapsed == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (outElapsedTime) {
|
||||||
|
*outElapsedTime = mStatus->previousElapsed;
|
||||||
|
mStatus->previousElapsed = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace filament::backend
|
||||||
50
filament/backend/src/webgpu/WebGPUTimerQuery.h
Normal file
50
filament/backend/src/webgpu/WebGPUTimerQuery.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TNT_FILAMENT_BACKEND_WEBGPUTIMERQUERY_H
|
||||||
|
#define TNT_FILAMENT_BACKEND_WEBGPUTIMERQUERY_H
|
||||||
|
|
||||||
|
#include "DriverBase.h"
|
||||||
|
|
||||||
|
#include <webgpu/webgpu_cpp.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace filament::backend {
|
||||||
|
|
||||||
|
class WebGPUTimerQuery : public HwTimerQuery {
|
||||||
|
public:
|
||||||
|
WebGPUTimerQuery()
|
||||||
|
: mStatus(std::make_shared<Status>()) {}
|
||||||
|
|
||||||
|
void beginTimeElapsedQuery();
|
||||||
|
void endTimeElapsedQuery();
|
||||||
|
bool getQueryResult(uint64_t* outElapsedTimeNanoseconds);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Status {
|
||||||
|
std::atomic<uint64_t> elapsedNanoseconds{ 0 };
|
||||||
|
std::atomic<uint64_t> previousElapsed{ 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<Status> mStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace filament::backend
|
||||||
|
|
||||||
|
#endif //TNT_FILAMENT_BACKEND_WEBGPUTIMERQUERY_H
|
||||||
Reference in New Issue
Block a user