diff --git a/CMakeLists.txt b/CMakeLists.txt index 33c5fe9e78..875827da55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -684,7 +684,6 @@ if (FILAMENT_SUPPORTS_METAL) set(MATC_API_FLAGS ${MATC_API_FLAGS} -a metal) endif() -# With WebGPU, push constants are not supported. Skinning uses them. # WebGPU has a proposal to add push constants at https://github.com/gpuweb/gpuweb/blob/main/proposals/push-constants.md # With WebGPU, Tint does not support ClipDistance which is used in Stereo. Mentioned in comment # https://github.com/google/dawn/blob/855d17b08abdf02f9142bf5a8f14d0ea088810a4/src/tint/lang/spirv/reader/ast_parser/function.cc#L4434 diff --git a/filament/backend/src/webgpu/WebGPUDriver.cpp b/filament/backend/src/webgpu/WebGPUDriver.cpp index 5ffd2039e5..62548aeba5 100644 --- a/filament/backend/src/webgpu/WebGPUDriver.cpp +++ b/filament/backend/src/webgpu/WebGPUDriver.cpp @@ -1472,7 +1472,18 @@ void WebGPUDriver::commit(Handle sch) { void WebGPUDriver::setPushConstant(backend::ShaderStage stage, uint8_t index, backend::PushConstantVariant value) { - //todo + assert_invariant(mRenderPassEncoder && "Should be called within a renderpass"); + uint32_t data = 0; + if (std::holds_alternative(value)) { + int32_t v = std::get(value); + std::memcpy(&data, &v, sizeof(data)); + } else if (std::holds_alternative(value)) { + float v = std::get(value); + std::memcpy(&data, &v, sizeof(data)); + } else if (std::holds_alternative(value)) { + data = std::get(value) ? 1 : 0; + } + mRenderPassEncoder.SetImmediates(index * sizeof(uint32_t), &data, sizeof(uint32_t)); } void WebGPUDriver::insertEventMarker(char const* string) { diff --git a/filament/backend/src/webgpu/WebGPUPipelineLayoutCache.cpp b/filament/backend/src/webgpu/WebGPUPipelineLayoutCache.cpp index 813807571f..fe2642b94c 100644 --- a/filament/backend/src/webgpu/WebGPUPipelineLayoutCache.cpp +++ b/filament/backend/src/webgpu/WebGPUPipelineLayoutCache.cpp @@ -69,11 +69,14 @@ void WebGPUPipelineLayoutCache::populateKey(PipelineLayoutRequest const& request wgpu::PipelineLayout WebGPUPipelineLayoutCache::createPipelineLayout( PipelineLayoutRequest const& request) { + wgpu::Limits supportedLimits{}; + mDevice.GetLimits(&supportedLimits); + const wgpu::PipelineLayoutDescriptor descriptor{ .label = wgpu::StringView(request.label.c_str_safe()), .bindGroupLayoutCount = request.bindGroupLayoutCount, .bindGroupLayouts = request.bindGroupLayouts.data(), - // TODO investigate immediateDataRangeByteSize + .immediateSize = supportedLimits.maxImmediateSize, }; const wgpu::PipelineLayout layout{ mDevice.CreatePipelineLayout(&descriptor) }; FILAMENT_CHECK_POSTCONDITION(layout) diff --git a/filament/backend/src/webgpu/platform/WebGPUPlatform.cpp b/filament/backend/src/webgpu/platform/WebGPUPlatform.cpp index f881420454..5c9f942000 100644 --- a/filament/backend/src/webgpu/platform/WebGPUPlatform.cpp +++ b/filament/backend/src/webgpu/platform/WebGPUPlatform.cpp @@ -250,6 +250,8 @@ void printInstanceDetails(wgpu::Instance const& instance) { //either returns a valid instance or panics [[nodiscard]] wgpu::Instance createInstance() { wgpu::DawnTogglesDescriptor dawnTogglesDescriptor{}; + // allow_unsafe_apis is required to expose the immediate_address_space and maxImmediateSize limit. + std::vector toggles = {"allow_unsafe_apis"}; #if defined(FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING) #if FWGPU_ENABLED(FWGPU_PRINT_SYSTEM) FWGPU_LOGI << "setting on toggle enable_immediate_error_handling"; @@ -260,10 +262,10 @@ void printInstanceDetails(wgpu::Instance const& instance) { * occurred when breaking into the un-captured error callback. * https://crbug.com/dawn/1789 */ - static const char* toggleName = "enable_immediate_error_handling"; - dawnTogglesDescriptor.enabledToggleCount = 1; - dawnTogglesDescriptor.enabledToggles = &toggleName; + toggles.push_back("enable_immediate_error_handling"); #endif + dawnTogglesDescriptor.enabledToggleCount = toggles.size(); + dawnTogglesDescriptor.enabledToggles = toggles.data(); const wgpu::InstanceFeatureName features[] = {wgpu::InstanceFeatureName::TimedWaitAny}; wgpu::InstanceDescriptor instanceDescriptor{ .nextInChain = &dawnTogglesDescriptor, @@ -626,6 +628,7 @@ wgpu::Device WebGPUPlatform::requestDevice(wgpu::Adapter const& adapter) { limitsToRequest.maxStorageTexturesPerShaderStage = std::min(MAX_MIPMAP_STORAGE_TEXTURES_PER_STAGE, supportedLimits.maxStorageTexturesPerShaderStage); + limitsToRequest.maxImmediateSize = supportedLimits.maxImmediateSize; deviceDescriptor.requiredLimits = &limitsToRequest; deviceDescriptor.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous, diff --git a/libs/filamat/src/GLSLPostProcessor.cpp b/libs/filamat/src/GLSLPostProcessor.cpp index 627b4ba626..dfda827e26 100644 --- a/libs/filamat/src/GLSLPostProcessor.cpp +++ b/libs/filamat/src/GLSLPostProcessor.cpp @@ -613,7 +613,10 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) { writerOptions.allow_non_uniform_derivatives = true; writerOptions.disable_unreachable_code_warning = true; writerOptions.allowed_features.extensions.insert(tint::wgsl::Extension::kClipDistances); - tint::Result wgslOut = tint::wgsl::writer::WgslFromIR(tintReadResult.Get(), writerOptions); + writerOptions.allowed_features.features.insert( + tint::wgsl::LanguageFeature::kImmediateAddressSpace); + tint::Result wgslOut = + tint::wgsl::writer::WgslFromIR(tintReadResult.Get(), writerOptions); if (wgslOut != tintSuccess) { slog.e << "Tint writer error: " << wgslOut.Failure().reason << io::endl; diff --git a/libs/filamat/src/shaders/CodeGenerator.cpp b/libs/filamat/src/shaders/CodeGenerator.cpp index b15d12dfbc..a243b1a165 100644 --- a/libs/filamat/src/shaders/CodeGenerator.cpp +++ b/libs/filamat/src/shaders/CodeGenerator.cpp @@ -923,28 +923,6 @@ utils::io::sstream& CodeGenerator::generatePushConstants(utils::io::sstream& out return "float"; } }; - // This is a workaround for WebGPU not supporting push constants for skinning. - // We replace the push constant with a regular constant struct initialized to 0. - if (mTargetApi == TargetApi::WEBGPU) { - assert_invariant( - pushConstants.size() == 1 && - "The current workaround for WebGPU push constants assumes for now that only 1"); - assert_invariant(pushConstants[0].name == CString("morphingBufferOffset") && - "The current workaround for WebGPU push constants assumes only the " - "morphingBufferOffset constant is present."); - assert_invariant(pushConstants[0].type == ConstantType::INT && - "The current workaround for WebGPU push constants assumes " - "morphingBufferOffset is an integer type."); - out << "struct " << STRUCT_NAME << " {\n"; - for (auto const& constant: pushConstants) { - out << " " << getType(constant.type) << " " << constant.name.c_str() << ";\n"; - } - out << "};\n"; - out << "const " << STRUCT_NAME << " " << PUSH_CONSTANT_STRUCT_VAR_NAME << " = " - << STRUCT_NAME << "(0);\n"; - return out; - } - bool const outputSpirv = mTargetLanguage == TargetLanguage::SPIRV && mTargetApi != TargetApi::OPENGL; if (outputSpirv) { diff --git a/libs/viewer/src/ViewerGui.cpp b/libs/viewer/src/ViewerGui.cpp index 7a0b4b9bc3..78ea955bac 100644 --- a/libs/viewer/src/ViewerGui.cpp +++ b/libs/viewer/src/ViewerGui.cpp @@ -578,7 +578,10 @@ void ViewerGui::applyAnimation(double currentTime, FilamentInstance* instance) { mCurrentStartTime = currentTime; mResetAnimation = false; } - const double elapsedSeconds = currentTime - mCurrentStartTime; + double elapsedSeconds = currentTime - mCurrentStartTime; + if (mSettings.animation.time >= 0.0f) { + elapsedSeconds = mSettings.animation.time; + } if (animationCount > 0 && mCurrentAnimation >= 0) { if (mCurrentAnimation == animationCount) { for (size_t i = 0; i < animationCount; i++) { diff --git a/samples/common/configuration.cpp b/samples/common/configuration.cpp index 7a72605bf5..ad34921a6a 100644 --- a/samples/common/configuration.cpp +++ b/samples/common/configuration.cpp @@ -31,7 +31,6 @@ std::unordered_map gFilters; // TODO: This is not necessary once we can support these variants in webgpu. char const* WEBGPU_VARIANT_FILTERS[] = { - "skinning", "stereo", }; diff --git a/test/renderdiff/tests/gltf_models.txt b/test/renderdiff/tests/gltf_models.txt index 401c0c5957..7b709ca076 100644 --- a/test/renderdiff/tests/gltf_models.txt +++ b/test/renderdiff/tests/gltf_models.txt @@ -6,6 +6,7 @@ BoxInterleaved BoxTextured BoxTexturedNonPowerOfTwo Duck +Fox IridescenceSuzanne IridescentDishWithOlives Lantern diff --git a/test/renderdiff/tests/presubmit.json b/test/renderdiff/tests/presubmit.json index 949202d8cc..2c72c05229 100644 --- a/test/renderdiff/tests/presubmit.json +++ b/test/renderdiff/tests/presubmit.json @@ -30,6 +30,11 @@ "name": "transmission_models", "models": ["TransmissionRoughnessTest", "IridescentDishWithOlives"], "rendering": {} + }, + { + "name": "animation_models", + "models": ["Fox"], + "rendering": {} } ], "tests": [ @@ -68,6 +73,17 @@ "rendering": { "view.ssao.enabled": true } + }, + { + "name": "Skinning", + "description": "Bone skinning animation test", + "apply_presets": ["base", "animation_models"], + "rendering": { + "animation": { + "enabled": true, + "time": 0.5 + } + } } ] }