@@ -633,7 +633,7 @@ endif()
|
||||
# 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
|
||||
if (FILAMENT_SUPPORTS_WEBGPU)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a webgpu --variant-filter=skinning,stereo)
|
||||
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a webgpu --variant-filter=stereo)
|
||||
endif()
|
||||
|
||||
# Disable ESSL 1.0 code generation.
|
||||
|
||||
@@ -146,7 +146,7 @@ abstract class MaterialCompiler extends TaskWithBinary {
|
||||
.gradleProperty("com.google.android.filament.include-webgpu")
|
||||
.forUseAtConfigurationTime().present
|
||||
if (include_webgpu) {
|
||||
matcArgs += ['-a', 'webgpu', '--variant-filter=skinning,stereo']
|
||||
matcArgs += ['-a', 'webgpu', '--variant-filter=stereo']
|
||||
}
|
||||
|
||||
def mat_no_opt = providers
|
||||
|
||||
@@ -629,6 +629,18 @@ enum class PrimitiveType : uint8_t {
|
||||
TRIANGLE_STRIP = 5 //!< triangle strip
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr bool isStripPrimitiveType(const PrimitiveType type) {
|
||||
switch (type) {
|
||||
case PrimitiveType::POINTS:
|
||||
case PrimitiveType::LINES:
|
||||
case PrimitiveType::TRIANGLES:
|
||||
return false;
|
||||
case PrimitiveType::LINE_STRIP:
|
||||
case PrimitiveType::TRIANGLE_STRIP:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported uniform types
|
||||
*/
|
||||
|
||||
@@ -293,10 +293,11 @@ wgpu::RenderPipeline WebGPUPipelineCache::createRenderPipeline(
|
||||
},
|
||||
.primitive = {
|
||||
.topology = toWebGPU(request.primitiveType),
|
||||
// TODO should we assume some constant format here or is there a way to get
|
||||
// this from PipelineState somehow or elsewhere?
|
||||
// Perhaps, cache/assert format from index buffers as they are requested?
|
||||
.stripIndexFormat = wgpu::IndexFormat::Undefined,
|
||||
// TODO This won't always be the case for the primitives bound. But this particular field
|
||||
// in the pipeline struct is only meant for restarting the strip, which we don't need so far.
|
||||
.stripIndexFormat =
|
||||
isStripPrimitiveType(request.primitiveType)? wgpu::IndexFormat::Uint16 :
|
||||
wgpu::IndexFormat::Undefined,
|
||||
.frontFace = request.rasterState.inverseFrontFaces ? wgpu::FrontFace::CW : wgpu::FrontFace::CCW,
|
||||
.cullMode = toWebGPU(request.rasterState.culling),
|
||||
// TODO no depth clamp in WebGPU supported directly. unclippedDepth is close, so we are
|
||||
@@ -312,12 +313,10 @@ wgpu::RenderPipeline WebGPUPipelineCache::createRenderPipeline(
|
||||
},
|
||||
.fragment = nullptr // will add below if fragment module is included
|
||||
};
|
||||
// TODO:
|
||||
if (pipelineDescriptor.primitive.topology == wgpu::PrimitiveTopology::LineStrip ||
|
||||
pipelineDescriptor.primitive.topology == wgpu::PrimitiveTopology::TriangleStrip) {
|
||||
PANIC_POSTCONDITION("stripIndexFormat must be set for strip topologies. "
|
||||
"This needs to be plumbed through from the RenderPrimitive.");
|
||||
}
|
||||
FILAMENT_CHECK_POSTCONDITION(!isStripPrimitiveType(request.primitiveType) ||
|
||||
pipelineDescriptor.primitive.stripIndexFormat != wgpu::IndexFormat::Undefined)
|
||||
<< "If the topology is a strip format, e.g. TriangleStrip, the stripIndexFormat cannot "
|
||||
"be Undefined.";
|
||||
|
||||
wgpu::FragmentState fragmentState = {};
|
||||
const wgpu::BlendState blendState {
|
||||
|
||||
@@ -161,7 +161,7 @@ private:
|
||||
// render targets... //
|
||||
uint8_t multisampleCount{ 0 }; // 1 : 313
|
||||
uint8_t colorFormatCount{ 0 }; // 1 : 314
|
||||
uint8_t padding[5]{ 0 }; // 5 : 319
|
||||
uint8_t padding[5]{ 0 }; // 5 : 315
|
||||
TargetBufferFlags targetRenderFlags{ TargetBufferFlags::NONE }; // 4 : 320
|
||||
wgpu::TextureFormat depthStencilFormat { wgpu::TextureFormat::Undefined }; // 4 : 324
|
||||
wgpu::TextureFormat colorFormats[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]{ //
|
||||
|
||||
@@ -173,9 +173,7 @@ utils::io::sstream& CodeGenerator::generateCommonProlog(utils::io::sstream& out,
|
||||
case TargetApi::METAL:
|
||||
out << "#define TARGET_METAL_ENVIRONMENT\n";
|
||||
break;
|
||||
// TODO: Handle webgpu here
|
||||
case TargetApi::WEBGPU:
|
||||
//For now, no differences so inherit the same changes.
|
||||
out << "#define TARGET_WEBGPU_ENVIRONMENT\n";
|
||||
break;
|
||||
case TargetApi::ALL:
|
||||
@@ -732,7 +730,6 @@ io::sstream& CodeGenerator::generateBufferInterfaceBlock(io::sstream& out, Shade
|
||||
// in the GLSL 4.5 / ESSL 3.1 case, the set is not used and binding is unique
|
||||
out << "binding = " << +binding << ", ";
|
||||
break;
|
||||
// TODO: Handle webgpu here
|
||||
case TargetApi::WEBGPU:
|
||||
out << "set = " << +set << ", binding = " << +binding << ", ";
|
||||
break;
|
||||
@@ -822,7 +819,6 @@ io::sstream& CodeGenerator::generateCommonSamplers(utils::io::sstream& out,
|
||||
// GLSL 4.5 / ESSL 3.1 require the 'binding' layout qualifier
|
||||
out << "layout(binding = " << getUniqueSamplerBindingPoint() << ") ";
|
||||
break;
|
||||
// TODO: Handle webgpu here
|
||||
case TargetApi::WEBGPU:
|
||||
out << "layout(binding = " << +info.binding << ", set = " << +set << ") ";
|
||||
break;
|
||||
@@ -942,7 +938,7 @@ utils::io::sstream& CodeGenerator::generateSpecializationConstant(utils::io::sst
|
||||
static const char* types[] = { "int", "float", "bool" };
|
||||
|
||||
// Spec constants aren't fully supported in Tint,
|
||||
// workaround until https://issues.chromium.org/issues/42250586 is resolved
|
||||
// workaround until https://issues.chromium.org/issues/42250586 is resolved
|
||||
if (mTargetApi == TargetApi::WEBGPU) {
|
||||
std::string const variableName = "FILAMENT_SPEC_CONST_" + std::to_string(id) + "_" + name;
|
||||
out << " const " << types[value.index()] << " " << variableName << " = " << constantString << ";\n";
|
||||
@@ -964,10 +960,11 @@ utils::io::sstream& CodeGenerator::generateSpecializationConstant(utils::io::sst
|
||||
|
||||
utils::io::sstream& CodeGenerator::generatePushConstants(utils::io::sstream& out,
|
||||
MaterialBuilder::PushConstantList const& pushConstants, size_t const layoutLocation) const {
|
||||
if (UTILS_UNLIKELY(pushConstants.empty())) {
|
||||
return out;
|
||||
}
|
||||
static constexpr char const* STRUCT_NAME = "Constants";
|
||||
|
||||
bool const outputSpirv =
|
||||
mTargetLanguage == TargetLanguage::SPIRV && mTargetApi != TargetApi::OPENGL;
|
||||
auto const getType = [](ConstantType const& type) {
|
||||
switch (type) {
|
||||
case ConstantType::BOOL:
|
||||
@@ -978,6 +975,30 @@ 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) {
|
||||
out << "layout(push_constant) uniform " << STRUCT_NAME << " {\n ";
|
||||
} else {
|
||||
|
||||
@@ -174,6 +174,7 @@ int main(int argc, char** argv) {
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT2, 0, 12)
|
||||
.attribute(VertexAttribute::COLOR, 0, VertexBuffer::AttributeType::UBYTE4, 8, 12)
|
||||
.normalized(VertexAttribute::COLOR)
|
||||
.advancedSkinning(true)
|
||||
.build(*engine);
|
||||
app.vb2->setBufferAt(*engine, 0,
|
||||
VertexBuffer::BufferDescriptor(TRIANGLE_VERTICES, 36, nullptr));
|
||||
|
||||
Reference in New Issue
Block a user