Compare commits
2 Commits
kpiascik/v
...
jc/enableT
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7da1c0ad5 | ||
|
|
04ff88fab2 |
@@ -283,6 +283,8 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
src/webgpu/WebGPUSwapChain.h
|
||||
src/webgpu/WebGPUTexture.cpp
|
||||
src/webgpu/WebGPUTexture.h
|
||||
src/webgpu/WebGPUTimerQuery.cpp
|
||||
src/webgpu/WebGPUTimerQuery.h
|
||||
src/webgpu/WebGPUVertexBuffer.cpp
|
||||
src/webgpu/WebGPUVertexBuffer.h
|
||||
src/webgpu/WebGPUVertexBufferInfo.cpp
|
||||
|
||||
@@ -172,15 +172,11 @@ SPDPipeline& MipmapGenerator::GetOrCreatePipeline(const PipelineCacheKey& key) {
|
||||
entry.binding = i;
|
||||
entry.visibility = wgpu::ShaderStage::Compute;
|
||||
if (i == 0) {
|
||||
if (key.scalarType == SPDScalarType::I32) {
|
||||
entry.texture.sampleType = wgpu::TextureSampleType::Sint;
|
||||
} else if (key.scalarType == SPDScalarType::U32) {
|
||||
entry.texture.sampleType = wgpu::TextureSampleType::Uint;
|
||||
} else if (key.scalarType == SPDScalarType::F32 || key.scalarType == SPDScalarType::F16) {
|
||||
entry.texture.sampleType = wgpu::TextureSampleType::Float;
|
||||
} else {
|
||||
entry.texture.sampleType = wgpu::TextureSampleType::UnfilterableFloat;
|
||||
}
|
||||
entry.texture.sampleType = (key.scalarType == SPDScalarType::I32)
|
||||
? wgpu::TextureSampleType::Sint
|
||||
: (key.scalarType == SPDScalarType::U32)
|
||||
? wgpu::TextureSampleType::Uint
|
||||
: wgpu::TextureSampleType::UnfilterableFloat;
|
||||
entry.texture.viewDimension = wgpu::TextureViewDimension::e2DArray;
|
||||
} else {
|
||||
entry.storageTexture.access = wgpu::StorageTextureAccess::WriteOnly;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "WebGPURenderTarget.h"
|
||||
#include "WebGPUSwapChain.h"
|
||||
#include "WebGPUTexture.h"
|
||||
#include "WebGPUTimerQuery.h"
|
||||
#include "WebGPUVertexBuffer.h"
|
||||
#include "WebGPUVertexBufferInfo.h"
|
||||
#include <backend/platforms/WebGPUPlatform.h>
|
||||
@@ -101,8 +102,9 @@ template class ConcreteDispatcher<WebGPUDriver>;
|
||||
void WebGPUDriver::terminate() {
|
||||
}
|
||||
|
||||
void WebGPUDriver::tick(int) {
|
||||
void WebGPUDriver::tick(int /*dummy*/) {
|
||||
mDevice.Tick();
|
||||
mAdapter.GetInstance().ProcessEvents();
|
||||
}
|
||||
|
||||
void WebGPUDriver::beginFrame(int64_t monotonic_clock_ns,
|
||||
@@ -216,9 +218,6 @@ void WebGPUDriver::destroyStream(Handle<HwStream> sh) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
void WebGPUDriver::destroyTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::destroyDescriptorSetLayout(
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle) {
|
||||
if (descriptorSetLayoutHandle) {
|
||||
@@ -268,7 +267,31 @@ Handle<HwFence> WebGPUDriver::createFenceS() 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 {
|
||||
@@ -337,6 +360,9 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
||||
mDevice, flags);
|
||||
assert_invariant(mSwapChain);
|
||||
|
||||
FWGPU_LOGW << "WebGPU support is highly experimental, in development, and tested for only a "
|
||||
"small set of simple samples (e.g. hellotriangle and texturedquad), thus issues "
|
||||
"are likely to be encountered at this stage.";
|
||||
#if !FWGPU_ENABLED(FWGPU_PRINT_SYSTEM) && !defined(NDEBUG)
|
||||
char printSystemHex[16];
|
||||
snprintf(printSystemHex, sizeof(printSystemHex), "%#x", FWGPU_PRINT_SYSTEM);
|
||||
@@ -459,8 +485,6 @@ void WebGPUDriver::createFenceR(Handle<HwFence> fh, int) {
|
||||
//todo
|
||||
}
|
||||
|
||||
void WebGPUDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {}
|
||||
|
||||
void WebGPUDriver::createDescriptorSetLayoutR(
|
||||
Handle<HwDescriptorSetLayout> descriptorSetLayoutHandle,
|
||||
backend::DescriptorSetLayout&& info) {
|
||||
@@ -609,24 +633,11 @@ size_t WebGPUDriver::getMaxUniformBufferSize() {
|
||||
}
|
||||
|
||||
size_t WebGPUDriver::getMaxTextureSize(const SamplerType target) {
|
||||
size_t result = 2048u;
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
case SamplerType::SAMPLER_EXTERNAL:
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
result = mDeviceLimits.maxTextureDimension2D;
|
||||
break;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
result = mDeviceLimits.maxTextureDimension3D;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
return 2048u;
|
||||
}
|
||||
|
||||
size_t WebGPUDriver::getMaxArrayTextureLayers() {
|
||||
return mDeviceLimits.maxTextureArrayLayers;
|
||||
return 256u;
|
||||
}
|
||||
|
||||
void WebGPUDriver::updateIndexBuffer(Handle<HwIndexBuffer> indexBufferHandle,
|
||||
@@ -737,10 +748,6 @@ void WebGPUDriver::setupExternalImage(void* image) {
|
||||
//todo
|
||||
}
|
||||
|
||||
TimerQueryResult WebGPUDriver::getTimerQueryValue(Handle<HwTimerQuery> tqh, uint64_t* elapsedTime) {
|
||||
return TimerQueryResult::ERROR;
|
||||
}
|
||||
|
||||
void WebGPUDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||
//todo
|
||||
}
|
||||
@@ -934,8 +941,10 @@ void WebGPUDriver::commit(Handle<HwSwapChain> sch) {
|
||||
mCommandBuffer = mCommandEncoder.Finish(&commandBufferDescriptor);
|
||||
assert_invariant(mCommandBuffer);
|
||||
mCommandEncoder = nullptr;
|
||||
if (mTimerQuery) {
|
||||
mTimerQuery->beginTimeElapsedQuery();
|
||||
}
|
||||
mQueue.Submit(1, &mCommandBuffer);
|
||||
|
||||
static bool firstRender = true;
|
||||
// For the first frame rendered, we need to make sure the work is done before presenting or we
|
||||
// get a purple flash
|
||||
@@ -950,6 +959,15 @@ void WebGPUDriver::commit(Handle<HwSwapChain> sch) {
|
||||
<< static_cast<uint32_t>(wStatus);
|
||||
}
|
||||
firstRender = false;
|
||||
} else {
|
||||
mQueue.OnSubmittedWorkDone(wgpu::CallbackMode::AllowSpontaneous,
|
||||
[=](wgpu::QueueWorkDoneStatus status) {
|
||||
if (status == wgpu::QueueWorkDoneStatus::Success) {
|
||||
if (mTimerQuery) {
|
||||
mTimerQuery->endTimeElapsedQuery();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
mCommandBuffer = nullptr;
|
||||
mTextureView = nullptr;
|
||||
@@ -1161,12 +1179,6 @@ void WebGPUDriver::scissor(
|
||||
//todo
|
||||
}
|
||||
|
||||
void WebGPUDriver::beginTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::endTimerQuery(Handle<HwTimerQuery> tqh) {
|
||||
}
|
||||
|
||||
void WebGPUDriver::resetState(int) {
|
||||
//todo
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
namespace filament::backend {
|
||||
|
||||
class WebGPUSwapChain;
|
||||
class WebGPUTimerQuery;
|
||||
|
||||
/**
|
||||
* WebGPU backend (driver) implementation
|
||||
@@ -78,6 +79,7 @@ private:
|
||||
WebGPURenderTarget* mDefaultRenderTarget = nullptr;
|
||||
WebGPURenderTarget* mCurrentRenderTarget = nullptr;
|
||||
spd::MipmapGenerator mMipMapGenerator;
|
||||
WebGPUTimerQuery* mTimerQuery = nullptr;
|
||||
|
||||
tsl::robin_map<uint32_t, wgpu::RenderPipeline> mPipelineMap;
|
||||
|
||||
@@ -116,6 +118,11 @@ private:
|
||||
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>
|
||||
D* constructHandle(Handle<B>& handle, ARGS&&... args) noexcept {
|
||||
return mHandleAllocator.construct<D>(handle, std::forward<ARGS>(args)...);
|
||||
|
||||
@@ -101,7 +101,7 @@ template<typename WebGPUPrintable>
|
||||
return out.str();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string adapterInfoToString(wgpu::AdapterInfo const& info) {
|
||||
[[nodiscard]] std::string adapterInfoToString(wgpu::AdapterInfo const& info) {
|
||||
std::stringstream out;
|
||||
out << "vendor (" << info.vendorID << ") '" << info.vendor
|
||||
<< "' device (" << info.deviceID << ") '" << info.device
|
||||
|
||||
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