Compare commits

..

30 Commits

Author SHA1 Message Date
Andy Hovingh
5ef77cf003 webgpu: debug descriptor sets option/functionality 2025-05-05 22:42:18 -05:00
Konrad Piascik
fcc2819293 Fix windows compile errors 2025-05-05 20:14:37 -05:00
Juan David Caldas
75d6076326 Change order of args for DrawIndexed, makes the triangle spin 2025-05-05 17:22:13 -04:00
Andy Hovingh
b1c6fd5d16 webgpu: legacy draw call should call draw2 2025-05-04 12:04:15 -05:00
Andy Hovingh
a1170924f9 webgpu: sets bind groups in the render pass 2025-05-04 11:48:07 -05:00
Andy Hovingh
1b53a2b680 webgpu: depth texture and attachment 2025-05-03 11:11:59 -05:00
Andy Hovingh
6cb7762751 webgpu: (temporarily) fix invalid texture views (hello-triangle specific) 2025-05-03 09:22:56 -05:00
Andy Hovingh
f87abf32ba webgpu: fix dimension param when creating texture views 2025-05-02 16:38:30 -05:00
Andy Hovingh
f874778a11 webgpu: fix missing color targets in render pipeline 2025-05-02 15:30:05 -05:00
Andy Hovingh
c6c6cae21b webgpu: fix vertex attribute shader location 2025-05-02 15:29:23 -05:00
Andy Hovingh
4cd3d1917b webgpu: do not include constants that are absent in the WGSL 2025-05-02 14:18:12 -05:00
Andy Hovingh
c436fc5260 webgpu: fix dummy bindings for bind groups that don't have resources corresponding to their layouts. 2025-05-02 14:18:12 -05:00
bridgewaterrobbie
a5b5359449 WARNING: Used Gemini to try to fix my bug. Haven't reviewed it but makes related errors go away so it might be right 2025-05-02 14:18:11 -05:00
bridgewaterrobbie
cd4c02252c Set a few more dummy params. DON'T use CreateSampler desc as the layout complains 2025-05-02 14:18:11 -05:00
Syed Idris Shah
836b2a5669 Pass the descriptor to sampler creation api 2025-05-02 14:18:11 -05:00
bridgewaterrobbie
1686e560b3 Throw together dummy descriptor entries. Very messy and at least one major bug 2025-05-02 14:18:11 -05:00
bridgewaterrobbie
e18e452770 Hack: Get the material label (Some of this was debugging until I figured out different issue) 2025-05-02 14:18:11 -05:00
bridgewaterrobbie
50e78636b7 Minor- make layout str outside constructor so it is safe from being destructed before copy 2025-05-02 14:18:11 -05:00
bridgewaterrobbie
6777f9f619 Test adding a label to descriptor sets for WebGPU 2025-05-02 14:18:10 -05:00
bridgewaterrobbie
4a938ec198 NEVER MERGE ME debugging logs to get to the bottom of issues pt1 2025-05-02 14:18:10 -05:00
bridgewaterrobbie
3273023db7 TO REVERT: Hacks to make descriptorset behave itself
Earlier I made mistakes. This hack fixes them but is suboptimal
2025-05-02 14:18:10 -05:00
Juan David Caldas
4afca93c7c Return the string value for the Spec constant 2025-05-02 14:18:10 -05:00
Syed Idris Shah
860a36256c wip: fixing errors 2025-05-02 14:18:10 -05:00
Syed Idris Shah
afd1fef657 Dawn change to enable writeBuffer for size != multiple of 4 2025-05-02 14:18:10 -05:00
Syed Idris Shah
0250d68b4b wip: webgpu: render target impl 2025-05-02 14:18:06 -05:00
bridgewaterrobbie
418a8d75ad Sampler creation as part of the driver 2025-05-02 14:14:11 -05:00
bridgewaterrobbie
8d1caadd7e Add comment explaining public texture format enum conversion 2025-05-02 14:14:10 -05:00
bridgewaterrobbie
3d3aaff83e Add a required feature for Filament to requestDevice 2025-05-02 14:14:10 -05:00
bridgewaterrobbie
cd4aa0e01e Fix mistake- entries size is smaller than the max index, need to fill one at a time with emplace back 2025-05-02 14:14:10 -05:00
bridgewaterrobbie
3c10c20ea1 Texture and Texture View creation 2025-05-02 14:14:10 -05:00
10 changed files with 335 additions and 113 deletions

View File

@@ -5,18 +5,6 @@ set(TARGET backend)
set(PUBLIC_HDR_DIR include)
set(GENERATION_ROOT ${CMAKE_CURRENT_BINARY_DIR})
# ==================================================================================================
# Compilation options
# ==================================================================================================
#
set(BACKEND_SANITIZATION "" CACHE STRING "Sanitization option")
set_property(CACHE BACKEND_SANITIZATION PROPERTY STRINGS ";ASAN")
set(BACKEND_SANITIZERS)
if (BACKEND_SANITIZATION STREQUAL "ASAN")
set(BACKEND_SANITIZERS -fsanitize=address)
endif()
# ==================================================================================================
# Sources and headers
# ==================================================================================================
@@ -484,7 +472,6 @@ target_compile_options(${TARGET} PRIVATE
${OSMESA_COMPILE_FLAGS}
$<$<CONFIG:Release>:${OPTIMIZATION_FLAGS}>
$<$<AND:$<PLATFORM_ID:Darwin>,$<CONFIG:Release>>:${DARWIN_OPTIMIZATION_FLAGS}>
${BACKEND_SANITIZERS}
)
if (FILAMENT_SUPPORTS_METAL)
@@ -495,8 +482,6 @@ if (FILAMENT_SUPPORTS_WEBGPU)
target_compile_definitions(${TARGET} PRIVATE $<$<BOOL:${FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING}>:FILAMENT_WEBGPU_IMMEDIATE_ERROR_HANDLING>)
endif()
target_link_options(${TARGET} PRIVATE ${BACKEND_SANITIZERS})
target_link_libraries(${TARGET} PRIVATE
${OSMESA_LINKER_FLAGS}
$<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Release>>:${LINUX_LINKER_OPTIMIZATION_FLAGS}>
@@ -566,8 +551,6 @@ if (APPLE AND NOT IOS)
test/test_RenderExternalImage.cpp)
add_library(backend_test STATIC ${BACKEND_TEST_SRC})
target_link_libraries(backend_test PUBLIC ${BACKEND_TEST_LIBS})
target_compile_options(backend_test PRIVATE ${BACKEND_SANITIZERS})
target_link_options(backend_test PRIVATE ${BACKEND_SANITIZERS})
set(BACKEND_TEST_DEPS
OSDependent
@@ -606,7 +589,6 @@ if (APPLE AND NOT IOS)
# linker from removing "unused" symbols.
target_link_libraries(backend_test_mac PRIVATE -force_load backend_test)
set_target_properties(backend_test_mac PROPERTIES FOLDER Tests)
target_link_options(backend_test_mac PRIVATE ${BACKEND_SANITIZERS})
# This is needed after XCode 15.3
set_target_properties(backend_test_mac PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
@@ -616,8 +598,6 @@ endif()
if (LINUX)
add_executable(backend_test_linux test/linux_runner.cpp ${BACKEND_TEST_SRC})
target_compile_options(backend_test_linux PRIVATE ${BACKEND_SANITIZERS})
target_link_options(backend_test_linux PRIVATE ${BACKEND_SANITIZERS})
target_link_libraries(backend_test_linux PRIVATE ${BACKEND_TEST_LIBS})
set_target_properties(backend_test_linux PROPERTIES FOLDER Tests)
endif()

View File

@@ -34,12 +34,14 @@
#include <math/vec4.h>
#include <array>
#if !defined(NDEBUG)
#include <string>
#endif
#include <type_traits>
#include <variant>
#include <stddef.h>
#include <stdint.h>
#include <utils/StaticString.h>
/**
* Types and enums used by filament's driver.
@@ -1140,7 +1142,9 @@ struct ExternalSamplerDatum {
static_assert(sizeof(ExternalSamplerDatum) == 12);
struct DescriptorSetLayout {
std::variant<utils::StaticString, utils::CString, std::monostate> label;
#if !defined(NDEBUG)
std::string label;
#endif
utils::FixedCapacityVector<DescriptorSetLayoutBinding> bindings;
// TODO: uncomment when needed

View File

@@ -198,6 +198,8 @@ WGPUProgram::WGPUProgram(wgpu::Device& device, Program& program)
ShaderStage::FRAGMENT)),
computeShaderModule(createShaderModule(device, name.c_str_safe(), program.getShadersSource(),
ShaderStage::COMPUTE)),
constants(convertConstants(program.getSpecializationConstants())) {}
constants(convertConstants(program.getSpecializationConstants())) {
auto test = program.getShadersSource();
}
}// namespace filament::backend

View File

@@ -34,6 +34,8 @@
// order of calls).
#define FWGPU_DEBUG_FORCE_LOG_TO_I 0x00000004
#define FWGPU_DEBUG_DESCRIPTOR_SETS 0x00000008
// Useful default combinations
#define FWGPU_DEBUG_EVERYTHING 0xFFFFFFFF

View File

@@ -470,9 +470,8 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
assert_invariant(mSwapChain);
WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(mDevice,
mSwapChain->getColorFormat());
FWGPU_LOGW << "WebGPU support is still essentially a no-op at this point in development (only "
"background components have been instantiated/selected, such as surface/screen, "
"graphics device/GPU, etc.), thus nothing is being drawn to the screen."
FWGPU_LOGW << "WebGPU support is highly limited, only supporting the hello-triangle sample in "
"a brittle/hacked way and untested, likely, breaking in other samples."
<< utils::io::endl;
#if !FWGPU_ENABLED(FWGPU_PRINT_SYSTEM) && !defined(NDEBUG)
FWGPU_LOGI << "If the FILAMENT_BACKEND_DEBUG_FLAG variable were set with the " << utils::io::hex
@@ -591,7 +590,14 @@ void WebGPUDriver::createDescriptorSetLayoutR(Handle<HwDescriptorSetLayout> dslh
void WebGPUDriver::createDescriptorSetR(Handle<HwDescriptorSet> dsh,
Handle<HwDescriptorSetLayout> dslh) {
auto layout = handleCast<WebGPUDescriptorSetLayout>(dslh);
constructHandle<WebGPUDescriptorSet>(dsh, layout->getLayout(), layout->getBindGroupEntries());
constructHandle<WebGPUDescriptorSet>(
dsh,
#ifndef NDEBUG
wgpu::StringView(layout->getLabel()),
#endif
layout->getLayout(),
layout->getBindGroupEntries()
);
}
Handle<HwStream> WebGPUDriver::createStreamNative(void* nativeStream) {
@@ -974,12 +980,12 @@ void WebGPUDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
void WebGPUDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t instanceCount) {
// Calling DrawIndexed with "firstInstance = 0" results in a NON spinning triangle
// mRenderPassEncoder.DrawIndexed(indexCount, instanceCount, indexOffset, 0, 0);
// mRenderPassEncoder.DrawIndexed(indexCount, instanceCount, indexOffset, 0, 0);
// Calling DrawIndexed with "firstInstance = 1" results in a spinning triangle
mRenderPassEncoder.DrawIndexed(indexCount, instanceCount, indexOffset, 0, 1);
// Calling Draw with "firstInstance = 0" results in a NON spinning triangle
// Calling Draw with "firstInstance = 1" results in a spinning triangle
// mRenderPassEncoder.Draw(indexCount, instanceCount, 0, 1);
// mRenderPassEncoder.Draw(indexCount, instanceCount, 0, 1);
}
void WebGPUDriver::draw(PipelineState, Handle<HwRenderPrimitive>, uint32_t indexOffset,

View File

@@ -16,14 +16,28 @@
#include "WebGPUHandles.h"
#include "WebGPUConstants.h"
#include <backend/DriverEnums.h>
#include <utils/BitmaskEnum.h>
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
#include <utils/ostream.h>
#endif
#include <webgpu/webgpu_cpp.h>
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
#include <webgpu/webgpu_cpp_print.h>
#endif
#include <algorithm>
#include <cstdint>
#ifndef NDEBUG
#include <string>
#endif
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
#include <string_view>
#endif
#include <utility>
#include <vector>
@@ -157,6 +171,226 @@ wgpu::StringView getUserTextureViewLabel(filament::backend::SamplerType target)
}
}
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
std::string_view toString(filament::backend::DescriptorType type) {
using filament::backend::DescriptorType;
switch (type) {
case DescriptorType::UNIFORM_BUFFER:
return "UNIFORM_BUFFER";
case DescriptorType::SHADER_STORAGE_BUFFER:
return "SHADER_STORAGE_BUFFER";
case DescriptorType::SAMPLER:
return "SAMPLER";
case DescriptorType::INPUT_ATTACHMENT:
return "INPUT_ATTACHMENT";
case DescriptorType::SAMPLER_EXTERNAL:
return "SAMPLER_EXTERNAL";
}
}
#endif
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
std::string_view toString(filament::backend::ShaderStageFlags flags) {
using filament::backend::ShaderStageFlags;
switch (flags) {
case ShaderStageFlags::NONE:
return "NONE";
case ShaderStageFlags::VERTEX:
return "VERTEX";
case ShaderStageFlags::FRAGMENT:
return "FRAGMENT";
case ShaderStageFlags::COMPUTE:
return "COMPUTE";
case ShaderStageFlags::ALL_SHADER_STAGE_FLAGS:
return "ALL_SHADER_STAGE_FLAGS";
}
if (any(flags & ShaderStageFlags::VERTEX)) {
if (any(flags & ShaderStageFlags::FRAGMENT)) {
return "VERTEX | FRAGMENT";
}
if (any(flags & ShaderStageFlags::COMPUTE)) {
return "VERTEX | COMPUTE";
}
}
if (any(flags & ShaderStageFlags::FRAGMENT)) {
if (any(flags & ShaderStageFlags::COMPUTE)) {
return "FRAGMENT | COMPUTE";
}
}
PANIC_POSTCONDITION("IMPOSSIBLE ShaderStageFlags combination. flags: %d", flags);
}
#endif
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
std::string_view toString(wgpu::ShaderStage stages) {
switch (stages) {
case wgpu::ShaderStage::None:
return "None";
case wgpu::ShaderStage::Vertex:
return "Vertex";
case wgpu::ShaderStage::Fragment:
return "Fragment";
case wgpu::ShaderStage::Compute:
return "Compute";
}
wgpu::ShaderStage allStages =
wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment | wgpu::ShaderStage::Compute;
if ((stages & allStages) == allStages) {
return "Vertex | Fragment | Compute";
}
if ((stages & wgpu::ShaderStage::Vertex) != 0) {
if ((stages & wgpu::ShaderStage::Fragment) != 0) {
return "Vertex | Fragment";
}
if ((stages & wgpu::ShaderStage::Compute) != 0) {
return "Vertex | Compute";
}
}
if ((stages & wgpu::ShaderStage::Fragment) != 0) {
if ((stages & wgpu::ShaderStage::Compute) != 0) {
return "Fragment | Compute";
}
}
}
#endif
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
std::string_view toString(filament::backend::DescriptorFlags flags) {
using filament::backend::DescriptorFlags;
switch (flags) {
case DescriptorFlags::NONE:
return "NONE";
case DescriptorFlags::DYNAMIC_OFFSET:
return "DYNAMIC_OFFSET";
}
}
#endif
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
void printFilamentDescriptorSetLayout(filament::backend::DescriptorSetLayout const& layout) {
using filament::backend::DescriptorSetLayoutBinding;
FWGPU_LOGD << "filament::backend::DescriptorSetLayout \"" << layout.label
<< "\":" << utils::io::endl;
FWGPU_LOGD << " bindings (" << layout.bindings.size() << "):" << utils::io::endl;
for (DescriptorSetLayoutBinding const& binding: layout.bindings) {
FWGPU_LOGD << " binding " << static_cast<uint32_t>(binding.binding) << ":"
<< " type " << toString(binding.type) << " stageFlags "
<< toString(binding.stageFlags) << " flags " << toString(binding.flags)
<< " count " << binding.count << utils::io::endl;
}
}
#endif
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
void printBindGroupLayout(wgpu::BindGroupLayoutDescriptor const& layout) {
FWGPU_LOGD << "wgpu::BindGroupLayoutDescriptor label \"" << layout.label
<< "\":" << utils::io::endl;
FWGPU_LOGD << " entries (" << layout.entryCount << "):" << utils::io::endl;
for (size_t entryIndex = 0; entryIndex < layout.entryCount; entryIndex++) {
wgpu::BindGroupLayoutEntry const& entry = layout.entries[entryIndex];
FWGPU_LOGD << " binding " << entry.binding << " visibility "
<< toString(entry.visibility);
if (entry.buffer.type != wgpu::BufferBindingType::BindingNotUsed &&
entry.buffer.type != wgpu::BufferBindingType::Undefined) {
// buffer entry...
assert_invariant(
entry.sampler.type == wgpu::SamplerBindingType::BindingNotUsed &&
entry.texture.sampleType == wgpu::TextureSampleType::BindingNotUsed &&
entry.storageTexture.access == wgpu::StorageTextureAccess::BindingNotUsed &&
"entry is for a buffer but one of the other layout types (sampler, texture, "
"storage) are somehow also being used?");
std::stringstream typeStream;
typeStream << entry.buffer.type;
FWGPU_LOGD << " " << typeStream.str() << " hasDynamicOffset "
<< bool(entry.buffer.hasDynamicOffset) << " minBindingSize "
<< entry.buffer.minBindingSize;
}
if (entry.sampler.type != wgpu::SamplerBindingType::BindingNotUsed &&
entry.sampler.type != wgpu::SamplerBindingType::Undefined) {
// sampler entry...
assert_invariant(
entry.buffer.type == wgpu::BufferBindingType::BindingNotUsed &&
entry.texture.sampleType == wgpu::TextureSampleType::BindingNotUsed &&
entry.storageTexture.access == wgpu::StorageTextureAccess::BindingNotUsed &&
"entry is for a sampler but one of the other layout types (buffer, texture, "
"storage) are somehow also being used?");
std::stringstream typeStream;
typeStream << entry.sampler.type;
FWGPU_LOGD << " " << typeStream.str();
}
if (entry.texture.sampleType != wgpu::TextureSampleType::BindingNotUsed &&
entry.texture.sampleType != wgpu::TextureSampleType::Undefined) {
// texture entry...
assert_invariant(
entry.buffer.type == wgpu::BufferBindingType::BindingNotUsed &&
entry.sampler.type == wgpu::SamplerBindingType::BindingNotUsed &&
entry.storageTexture.access == wgpu::StorageTextureAccess::BindingNotUsed &&
"entry is for a texture but one of the other layout types (buffer, sampler, "
"storage) are somehow also being used?");
std::stringstream typeStream;
typeStream << entry.texture.sampleType;
std::stringstream dimensionStream;
dimensionStream << entry.texture.viewDimension;
FWGPU_LOGD << " " << typeStream.str() << " " << dimensionStream.str()
<< " multisampled " << bool(entry.texture.multisampled);
}
if (entry.storageTexture.access != wgpu::StorageTextureAccess::BindingNotUsed &&
entry.storageTexture.access != wgpu::StorageTextureAccess::Undefined) {
// storageTexture entry...
assert_invariant(
entry.buffer.type == wgpu::BufferBindingType::BindingNotUsed &&
entry.sampler.type == wgpu::SamplerBindingType::BindingNotUsed &&
entry.texture.sampleType == wgpu::TextureSampleType::BindingNotUsed &&
"entry is for a storage texture but one of the other layout types (buffer, "
"sampler, texture) are somehow also being used?");
std::stringstream accessStream;
accessStream << entry.storageTexture.access;
std::stringstream formatStream;
formatStream << entry.storageTexture.format;
std::stringstream dimensionStream;
dimensionStream << entry.storageTexture.viewDimension;
FWGPU_LOGD << " " << accessStream.str() << " " << formatStream.str() << " "
<< dimensionStream.str();
}
FWGPU_LOGD << utils::io::endl;
}
}
#endif
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
template <size_t ENTRY_SIZE>
void printBindGroup(wgpu::BindGroupDescriptor const& bindGroup,
std::bitset<ENTRY_SIZE> const& entriesByBindingWithDynamicOffsets,
std::bitset<ENTRY_SIZE> const& entriesByBindingAdded) {
assert_invariant(bindGroup.layout);
FWGPU_LOGD << "wgpu::BindGroupDescriptor label \"" << bindGroup.label
<< "\":" << utils::io::endl;
FWGPU_LOGD << " entries (" << bindGroup.entryCount << "):" << utils::io::endl;
for (size_t entryIndex = 0; entryIndex < bindGroup.entryCount; entryIndex++) {
wgpu::BindGroupEntry const& entry = bindGroup.entries[entryIndex];
FWGPU_LOGD << " binding " << entry.binding;
if (entry.buffer) {
assert_invariant(entry.sampler == nullptr && entry.textureView == nullptr &&
"buffer set but also sampler and/or textureView?");
FWGPU_LOGD << " buffer";
}
if (entry.sampler) {
assert_invariant(entry.buffer == nullptr && entry.textureView == nullptr &&
"sampler set but also buffer and/or textureView?");
FWGPU_LOGD << " sampler";
}
if (entry.textureView) {
assert_invariant(entry.buffer == nullptr && entry.sampler == nullptr &&
"textureView set but also buffer and/or sampler?");
FWGPU_LOGD << " textureView";
}
FWGPU_LOGD << " offset " << entry.offset << " size " << entry.size << " hasDynamicOffset "
<< bool(entriesByBindingWithDynamicOffsets[entry.binding]) << " added "
<< bool(entriesByBindingAdded[entry.binding]) << utils::io::endl;
}
}
#endif
}// namespace
namespace filament::backend {
@@ -236,20 +470,16 @@ wgpu::ShaderStage WebGPUDescriptorSetLayout::filamentStageToWGPUStage(ShaderStag
}
WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const& layout,
wgpu::Device const& device) {
wgpu::Device const& device)
#ifndef NDEBUG
: mLabel(layout.label)
#endif
{
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
printFilamentDescriptorSetLayout(layout);
#endif
assert_invariant(device);
std::string baseLabel;
if (std::holds_alternative<utils::StaticString>(layout.label)) {
const auto& temp = std::get_if<utils::StaticString>(&layout.label);
baseLabel = temp->c_str();
} else if (std::holds_alternative<utils::CString>(layout.label)) {
const auto& temp = std::get_if<utils::CString>(&layout.label);
baseLabel = temp->c_str();
}
// TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
// debugging. For now, hack an incrementing value.
static int layoutNum = 0;
unsigned int samplerCount =
@@ -283,13 +513,18 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
samplerEntry.sampler.type = wgpu::SamplerBindingType::NonFiltering; // Example default
wEntry.texture.sampleType = wgpu::TextureSampleType::Float; // Example default
// TODO: FIX! THIS IS HACK FOR HELLO-TRIANGLE!
if (baseLabel.find("Skybox") != std::string::npos ||
(baseLabel == "Filament Default Material_perView" && wEntry.binding == 22)) {
#ifndef NDEBUG
if (layout.label.find("Skybox") != std::string::npos ||
(layout.label == "Filament Default Material1" && wEntry.binding == 22)) {
wEntry.texture.viewDimension = wgpu::TextureViewDimension::Cube;
} else {
wEntry.texture.viewDimension =
wgpu::TextureViewDimension::e2D;// Example default
}
#else
// TODO: AGAIN, fix the above because hello-triangle will break on release builds
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e2D;// Example default
#endif
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW;
break;
}
@@ -313,12 +548,17 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
}
// fEntry.count is unused currently
}
std::string label = "layout_" + baseLabel + std::to_string(++layoutNum) ;
wgpu::BindGroupLayoutDescriptor layoutDescriptor{
.label{label.c_str()}, // Use .c_str() if label needs to be const char*
.entryCount = wEntries.size(),
.entries = wEntries.data()
};
#ifndef NDEBUG
std::string label = "layout_" + layout.label + std::to_string(++layoutNum);
layoutDescriptor.label = label.c_str();// Use .c_str() if label needs to be const char*
#endif
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
printBindGroupLayout(layoutDescriptor);
#endif
mLayout = device.CreateBindGroupLayout(&layoutDescriptor);
}
@@ -411,9 +651,17 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
return entries;
}
WebGPUDescriptorSet::WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
WebGPUDescriptorSet::WebGPUDescriptorSet(
#ifndef NDEBUG
wgpu::StringView const& label,
#endif
wgpu::BindGroupLayout const& layout,
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries)
: mLayout(layout),
:
#ifndef NDEBUG
mLabel(label),
#endif
mLayout(layout),
mEntriesSortedByBinding(createDummyEntriesSortedByBinding(bindGroupEntries)) {
// Establish the size of entries based on the layout. This should be reliable and efficient.
assert_invariant(INVALID_INDEX > mEntryIndexByBinding.size());
@@ -436,23 +684,26 @@ WebGPUDescriptorSet::WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
WebGPUDescriptorSet::~WebGPUDescriptorSet() {
mBindGroup = nullptr;
mLayout = nullptr;
}
wgpu::BindGroup WebGPUDescriptorSet::lockAndReturn(const wgpu::Device& device) {
if (mBindGroup) {
return mBindGroup;
}
// TODO label? Should we just copy layout label?
wgpu::BindGroupDescriptor desc{
#ifndef NDEBUG
.label = mLabel,
#endif
.layout = mLayout,
.entryCount = mEntriesSortedByBinding.size(),
.entries = mEntriesSortedByBinding.data()
};
#if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
printBindGroup(desc, mEntriesByBindingWithDynamicOffsets, mEntriesByBindingAdded);
#endif
mBindGroup = device.CreateBindGroup(&desc);
FILAMENT_CHECK_POSTCONDITION(mBindGroup) << "Failed to create bind group?";
// once we have created the bind group itself we should no longer need any other state
mLayout = nullptr;
mEntriesSortedByBinding.clear();
mEntriesSortedByBinding.shrink_to_fit();
return mBindGroup;

View File

@@ -14,7 +14,6 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_WEBGPUHANDLES_H
#define TNT_FILAMENT_BACKEND_WEBGPUHANDLES_H
@@ -30,6 +29,10 @@
#include <array>
#include <bitset>
#include <cstdint>
#ifndef NDEBUG
#include <string>
#include <string_view>
#endif
#include <vector>
namespace filament::backend {
@@ -118,6 +121,9 @@ public:
WebGPUDescriptorSetLayout(DescriptorSetLayout const& layout, wgpu::Device const& device);
~WebGPUDescriptorSetLayout();
#ifndef NDEBUG
[[nodiscard]] std::string const& getLabel() const { return mLabel; }
#endif
[[nodiscard]] const wgpu::BindGroupLayout& getLayout() const { return mLayout; }
[[nodiscard]] std::vector<BindGroupEntryInfo> const& getBindGroupEntries() const {
return mBindGroupEntries;
@@ -127,6 +133,9 @@ private:
// TODO: If this is useful elsewhere, remove it from this class
// Convert Filament Shader Stage Flags bitmask to webgpu equivilant
static wgpu::ShaderStage filamentStageToWGPUStage(ShaderStageFlags fFlags);
#ifndef NDEBUG
std::string const mLabel;
#endif
std::vector<BindGroupEntryInfo> mBindGroupEntries;
wgpu::BindGroupLayout mLayout;
};
@@ -136,7 +145,11 @@ public:
static void initializeDummyResourcesIfNotAlready(wgpu::Device const&,
wgpu::TextureFormat aColorFormat);
WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
WebGPUDescriptorSet(
#ifndef NDEBUG
wgpu::StringView const& label,
#endif
wgpu::BindGroupLayout const& layout,
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries);
~WebGPUDescriptorSet();
@@ -154,12 +167,14 @@ private:
static std::vector<wgpu::BindGroupEntry> createDummyEntriesSortedByBinding(
std::vector<filament::backend::WebGPUDescriptorSetLayout::BindGroupEntryInfo> const&);
#ifndef NDEBUG
const wgpu::StringView mLabel;
#endif
// TODO: Consider storing what we used to make the layout. However we need to essentially
// Recreate some of the info (Sampler in slot X with the actual sampler) so letting Dawn confirm
// there isn't a mismatch may be easiest.
// Also storing the wgpu ObjectBase takes care of ownership challenges in theory
wgpu::BindGroupLayout mLayout = nullptr;
wgpu::BindGroupLayout const& mLayout;
static constexpr uint8_t INVALID_INDEX = MAX_DESCRIPTOR_COUNT + 1;
std::array<uint8_t, MAX_DESCRIPTOR_COUNT> mEntryIndexByBinding {};
std::vector<wgpu::BindGroupEntry> mEntriesSortedByBinding;

View File

@@ -99,45 +99,21 @@ wgpu::Adapter WebGPUPlatform::requestAdapter(wgpu::Surface const& surface) {
wgpu::Device WebGPUPlatform::requestDevice(wgpu::Adapter const& adapter) {
// TODO consider passing limits
constexpr std::array optionalFeatures = { wgpu::FeatureName::DepthClipControl,
wgpu::FeatureName::Depth32FloatStencil8, wgpu::FeatureName::CoreFeaturesAndLimits };
constexpr std::array requiredFeatures = { wgpu::FeatureName::TransientAttachments };
constexpr std::array desiredFeatures = { wgpu::FeatureName::DepthClipControl,
wgpu::FeatureName::Depth32FloatStencil8, wgpu::FeatureName::CoreFeaturesAndLimits,
wgpu::FeatureName::TransientAttachments };
std::vector<wgpu::FeatureName> requiredFeatures;
requiredFeatures.reserve(desiredFeatures.size());
wgpu::SupportedFeatures supportedFeatures;
adapter.GetFeatures(&supportedFeatures);
std::vector<wgpu::FeatureName> enabledFeatures;
enabledFeatures.reserve(requiredFeatures.size() + optionalFeatures.size());
std::set_intersection(supportedFeatures.features,
supportedFeatures.features + supportedFeatures.featureCount, requiredFeatures.begin(),
requiredFeatures.end(), std::back_inserter(enabledFeatures));
if (enabledFeatures.size() != requiredFeatures.size()) {
std::vector<wgpu::FeatureName> missingFeatures;
std::set_difference(requiredFeatures.begin(), requiredFeatures.end(),
supportedFeatures.features,
supportedFeatures.features + supportedFeatures.featureCount,
std::back_inserter(missingFeatures));
std::stringstream missingFeaturesStream{};
for (const auto& entry: missingFeatures) {
missingFeaturesStream << std::to_string(static_cast<uint32_t>(entry)) << " ";
}
PANIC_POSTCONDITION("Some required features are not available %s/n",
missingFeaturesStream.str().c_str());
}
std::set_intersection(supportedFeatures.features,
supportedFeatures.features + supportedFeatures.featureCount, optionalFeatures.begin(),
optionalFeatures.end(), std::back_inserter(enabledFeatures));
supportedFeatures.features + supportedFeatures.featureCount, desiredFeatures.begin(),
desiredFeatures.end(), std::back_inserter(requiredFeatures));
wgpu::DeviceDescriptor deviceDescriptor{};
deviceDescriptor.label = "graphics_device";
deviceDescriptor.defaultQueue.label = "default_queue";
deviceDescriptor.requiredFeatureCount = enabledFeatures.size();
deviceDescriptor.requiredFeatures = enabledFeatures.data();
deviceDescriptor.requiredFeatureCount = requiredFeatures.size();
deviceDescriptor.requiredFeatures = requiredFeatures.data();
deviceDescriptor.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
[](wgpu::Device const&, wgpu::DeviceLostReason const& reason,
wgpu::StringView message) {

View File

@@ -1139,7 +1139,8 @@ void FMaterial::precacheDepthVariants(FEngine& engine) {
void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* const parser) {
UTILS_UNUSED_IN_RELEASE bool success;
utils::CString namestr;
parser->getName(&namestr);
success = parser->getDescriptorBindings(&mProgramDescriptorBindings);
assert_invariant(success);
@@ -1148,21 +1149,10 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con
success = parser->getDescriptorSetLayout(&descriptorSetLayout);
assert_invariant(success);
// Setup Labels for debugging
utils::CString namestr;
utils::StaticString perViewStr = "_perView";
utils::StaticString singleStr = "_single";
parser->getName(&namestr);
utils::CString singleLabel(namestr.c_str(), namestr.length() + singleStr.length());
memccpy(singleLabel.c_str() + namestr.length(), singleStr.c_str(), '\0', singleStr.length());
utils::CString perViewLabel(namestr.c_str(), namestr.length() + perViewStr.length());
memccpy(perViewLabel.c_str() + namestr.length(), perViewStr.c_str(), '\0', perViewStr.length());
descriptorSetLayout[0].label = namestr;
descriptorSetLayout[1].label = perViewLabel;
descriptorSetLayout[0].label = namestr.c_str();
descriptorSetLayout[1].label = namestr.c_str();
descriptorSetLayout[0].label+="0\0";
descriptorSetLayout[1].label+="1\0";
mDescriptorSetLayout = {
engine.getDescriptorSetLayoutFactory(),
@@ -1171,6 +1161,7 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con
mPerViewDescriptorSetLayout = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(), std::move(descriptorSetLayout[1]) };
}
descriptor_binding_t FMaterial::getSamplerBinding(

View File

@@ -33,13 +33,11 @@ namespace filament::descriptor_sets {
using namespace backend;
static DescriptorSetLayout const postProcessDescriptorSetLayout{
utils::StaticString("postProcess"),{
static DescriptorSetLayout const postProcessDescriptorSetLayout{"postProcess", {
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
}};
static DescriptorSetLayout const depthVariantDescriptorSetLayout{
utils::StaticString("depthVariant"),{
static DescriptorSetLayout const depthVariantDescriptorSetLayout{"depthVariant",{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
}};
@@ -48,16 +46,14 @@ static DescriptorSetLayout const depthVariantDescriptorSetLayout{
// dedicated SSR vertex shader), which uses perViewDescriptorSetLayout.
// This means that PerViewBindingPoints::SHADOWS must be in the layout even though it's not used
// by the SSR variant.
static DescriptorSetLayout const ssrVariantDescriptorSetLayout{
utils::StaticString("ssrVariant"),{
static DescriptorSetLayout const ssrVariantDescriptorSetLayout{"ssrVariant", {
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
}};
static DescriptorSetLayout perViewDescriptorSetLayout = {
utils::StaticString("perView"),{
static DescriptorSetLayout perViewDescriptorSetLayout = {"perView", {
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::LIGHTS },
@@ -72,8 +68,7 @@ static DescriptorSetLayout perViewDescriptorSetLayout = {
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG },
}};
static DescriptorSetLayout perRenderableDescriptorSetLayout = {
utils::StaticString("perRenderable"),{
static DescriptorSetLayout perRenderableDescriptorSetLayout = {"preRenderable",{
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::OBJECT_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::BONES_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::MORPHING_UNIFORMS },