Compare commits
30 Commits
ebridgewat
...
idris/rend
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ef77cf003 | ||
|
|
fcc2819293 | ||
|
|
75d6076326 | ||
|
|
b1c6fd5d16 | ||
|
|
a1170924f9 | ||
|
|
1b53a2b680 | ||
|
|
6cb7762751 | ||
|
|
f87abf32ba | ||
|
|
f874778a11 | ||
|
|
c6c6cae21b | ||
|
|
4cd3d1917b | ||
|
|
c436fc5260 | ||
|
|
a5b5359449 | ||
|
|
cd4c02252c | ||
|
|
836b2a5669 | ||
|
|
1686e560b3 | ||
|
|
e18e452770 | ||
|
|
50e78636b7 | ||
|
|
6777f9f619 | ||
|
|
4a938ec198 | ||
|
|
3273023db7 | ||
|
|
4afca93c7c | ||
|
|
860a36256c | ||
|
|
afd1fef657 | ||
|
|
0250d68b4b | ||
|
|
418a8d75ad | ||
|
|
8d1caadd7e | ||
|
|
3d3aaff83e | ||
|
|
cd4aa0e01e | ||
|
|
3c10c20ea1 |
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user