Compare commits

...

10 Commits

Author SHA1 Message Date
bridgewaterrobbie
815629f14e Quick fix for descriptor set types. 2025-05-15 15:33:47 -04:00
bridgewaterrobbie
c05a446e10 Minor fixes to branch hacks. Use unfilterable float instead of float (Might need to vary this depending on eventual filtering bit) 2025-05-15 15:33:36 -04:00
bridgewaterrobbie
9d49205844 Filament's compareMode function should be checked before using any of the comparison related enums it provides. This also lets us use the descriptor now. 2025-05-15 15:32:19 -04:00
bridgewaterrobbie
7099b6dd6f Quick and dirty hack to log where dummies are needed to work still 2025-05-14 20:13:42 -04:00
Mathias Agopian
18becfc656 Make sure that all descriptors are always initialized 2025-05-14 20:13:42 -04:00
bridgewaterrobbie
cd2d499e25 Tinkering with new descriptortype info 2025-05-14 15:39:16 -04:00
Mathias Agopian
3bb72cefe9 fix fog sampler descriptor type 2025-05-14 15:39:16 -04:00
Mathias Agopian
1a67f9233b DescriptorType now includes the "dimension" of the texture
DescriptorType now also encodes wether the descriptor expects a 2D, 3D,
Cubemap and/or Array.

This is needed by both Metal and WebGPU.

[**New Material Version**]
2025-05-12 14:10:20 -04:00
Mathias Agopian
f7e20562a8 select the proper descriptor set layout in the rendering loop
Now that the per-view layout can be different based on the type of
shadow, we need to make sure we set the proper layout in the pipeline
and use the corresponding descriptor set.

There are now 16 "per-view" layouts and their corresponding descriptor
set. There are two sets of 8, the current set is determined by the
shadow type on the view.

Then during rendering, when we set the pipeline we need to select the
corresponding layout; each material now offers both versions of the
layout and we just pick the right one.

DescriptorSet::setBuffer and setSampler now need the layout in order
to do some validation that the correct type of descriptor is used.
This will help catch problems earlier.
2025-05-12 14:10:19 -04:00
Mathias Agopian
08af16239c add sampler type in DescriptorSetLayout
[**New Material Version**]
2025-05-12 14:10:19 -04:00
45 changed files with 1468 additions and 557 deletions

View File

@@ -7,3 +7,5 @@ for next branch cut* header.
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut
- materials: sampler now export their type in the material binary [⚠️ **New Material Version**]

View File

@@ -37,6 +37,7 @@
#include <array>
#include <type_traits>
#include <variant>
#include <string_view>
#include <stddef.h>
#include <stdint.h>
@@ -159,7 +160,7 @@ enum class TimerQueryResult : int8_t {
AVAILABLE = 1, // result is available
};
static constexpr const char* backendToString(Backend backend) {
constexpr std::string_view to_string(Backend const backend) noexcept {
switch (backend) {
case Backend::NOOP:
return "Noop";
@@ -171,9 +172,11 @@ static constexpr const char* backendToString(Backend backend) {
return "Metal";
case Backend::WEBGPU:
return "WebGPU";
default:
return "Unknown";
case Backend::DEFAULT:
return "Default";
break;
}
return "Unknown";
}
/**
@@ -190,7 +193,7 @@ enum class ShaderLanguage {
WGSL = 5,
};
static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) {
constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) noexcept {
switch (shaderLanguage) {
case ShaderLanguage::ESSL1:
return "ESSL 1.0";
@@ -205,6 +208,7 @@ static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguag
case ShaderLanguage::WGSL:
return "WGSL";
}
return "UNKNOWN";
}
enum class ShaderStage : uint8_t {
@@ -222,7 +226,7 @@ enum class ShaderStageFlags : uint8_t {
ALL_SHADER_STAGE_FLAGS = VERTEX | FRAGMENT | COMPUTE
};
static inline constexpr bool hasShaderType(ShaderStageFlags flags, ShaderStage type) noexcept {
constexpr bool hasShaderType(ShaderStageFlags flags, ShaderStage type) noexcept {
switch (type) {
case ShaderStage::VERTEX:
return bool(uint8_t(flags) & uint8_t(ShaderStageFlags::VERTEX));
@@ -233,14 +237,114 @@ static inline constexpr bool hasShaderType(ShaderStageFlags flags, ShaderStage t
}
}
enum class DescriptorType : uint8_t {
UNIFORM_BUFFER,
SHADER_STORAGE_BUFFER,
SAMPLER,
INPUT_ATTACHMENT,
SAMPLER_EXTERNAL
enum class TextureType : uint8_t {
FLOAT,
INT,
UINT,
DEPTH,
STENCIL,
DEPTH_STENCIL
};
constexpr std::string_view to_string(TextureType type) noexcept {
switch (type) {
case TextureType::FLOAT: return "FLOAT";
case TextureType::INT: return "INT";
case TextureType::UINT: return "UINT";
case TextureType::DEPTH: return "DEPTH";
case TextureType::STENCIL: return "STENCIL";
case TextureType::DEPTH_STENCIL: return "DEPTH_STENCIL";
}
return "UNKNOWN";
}
enum class DescriptorType : uint8_t {
SAMPLER_2D_FLOAT,
SAMPLER_2D_INT,
SAMPLER_2D_UINT,
SAMPLER_2D_DEPTH,
SAMPLER_2D_ARRAY_FLOAT,
SAMPLER_2D_ARRAY_INT,
SAMPLER_2D_ARRAY_UINT,
SAMPLER_2D_ARRAY_DEPTH,
SAMPLER_CUBE_FLOAT,
SAMPLER_CUBE_INT,
SAMPLER_CUBE_UINT,
SAMPLER_CUBE_DEPTH,
SAMPLER_CUBE_ARRAY_FLOAT,
SAMPLER_CUBE_ARRAY_INT,
SAMPLER_CUBE_ARRAY_UINT,
SAMPLER_CUBE_ARRAY_DEPTH,
SAMPLER_3D_FLOAT,
SAMPLER_3D_INT,
SAMPLER_3D_UINT,
SAMPLER_EXTERNAL,
UNIFORM_BUFFER,
SHADER_STORAGE_BUFFER,
INPUT_ATTACHMENT,
};
constexpr bool isDepthDescriptor(DescriptorType const type) noexcept {
switch (type) {
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
return true;
default: ;
}
return false;
}
constexpr bool isFloatDescriptor(DescriptorType const type) noexcept {
switch (type) {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_3D_FLOAT:
return true;
default: ;
}
return false;
}
constexpr std::string_view to_string(DescriptorType type) noexcept {
#define DESCRIPTOR_TYPE_CASE(TYPE) case DescriptorType::TYPE: return #TYPE;
switch (type) {
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_DEPTH)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_2D_ARRAY_DEPTH)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_DEPTH)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_CUBE_ARRAY_DEPTH)
DESCRIPTOR_TYPE_CASE(SAMPLER_3D_FLOAT)
DESCRIPTOR_TYPE_CASE(SAMPLER_3D_INT)
DESCRIPTOR_TYPE_CASE(SAMPLER_3D_UINT)
DESCRIPTOR_TYPE_CASE(SAMPLER_EXTERNAL)
DESCRIPTOR_TYPE_CASE(UNIFORM_BUFFER)
DESCRIPTOR_TYPE_CASE(SHADER_STORAGE_BUFFER)
DESCRIPTOR_TYPE_CASE(INPUT_ATTACHMENT)
}
return "UNKNOWN";
#undef DESCRIPTOR_TYPE_CASE
}
enum class DescriptorFlags : uint8_t {
NONE = 0x00,
DYNAMIC_OFFSET = 0x01
@@ -251,6 +355,13 @@ using descriptor_set_t = uint8_t;
using descriptor_binding_t = uint8_t;
struct DescriptorSetLayoutBinding {
static bool isSampler(DescriptorType type) noexcept {
return int(type) <= int(DescriptorType::SAMPLER_EXTERNAL);
}
static bool isBuffer(DescriptorType type) noexcept {
return type == DescriptorType::UNIFORM_BUFFER ||
type == DescriptorType::SHADER_STORAGE_BUFFER;
}
DescriptorType type;
ShaderStageFlags stageFlags;
descriptor_binding_t binding;
@@ -261,7 +372,7 @@ struct DescriptorSetLayoutBinding {
// no uninitialized padding bytes.
// uint8_t externalSamplerDataIndex = EXTERNAL_SAMPLER_DATA_INDEX_UNUSED;
friend inline bool operator==(DescriptorSetLayoutBinding const& lhs,
friend bool operator==(DescriptorSetLayoutBinding const& lhs,
DescriptorSetLayoutBinding const& rhs) noexcept {
return lhs.type == rhs.type &&
lhs.flags == rhs.flags &&
@@ -294,7 +405,7 @@ enum class TargetBufferFlags : uint32_t {
ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected.
};
inline constexpr TargetBufferFlags getTargetBufferFlagsAt(size_t index) noexcept {
constexpr TargetBufferFlags getTargetBufferFlagsAt(size_t index) noexcept {
if (index == 0u) return TargetBufferFlags::COLOR0;
if (index == 1u) return TargetBufferFlags::COLOR1;
if (index == 2u) return TargetBufferFlags::COLOR2;
@@ -451,6 +562,24 @@ enum class SamplerType : uint8_t {
SAMPLER_CUBEMAP_ARRAY, //!< Cube map array texture (feature level 2)
};
constexpr std::string_view to_string(SamplerType const type) noexcept {
switch (type) {
case SamplerType::SAMPLER_2D:
return "SAMPLER_2D";
case SamplerType::SAMPLER_2D_ARRAY:
return "SAMPLER_2D_ARRAY";
case SamplerType::SAMPLER_CUBEMAP:
return "SAMPLER_CUBEMAP";
case SamplerType::SAMPLER_EXTERNAL:
return "SAMPLER_EXTERNAL";
case SamplerType::SAMPLER_3D:
return "SAMPLER_3D";
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
return "SAMPLER_CUBEMAP_ARRAY";
}
return "Unknown";
}
//! Subpass type
enum class SubpassType : uint8_t {
SUBPASS_INPUT
@@ -464,6 +593,20 @@ enum class SamplerFormat : uint8_t {
SHADOW = 3 //!< shadow sampler (PCF)
};
constexpr std::string_view to_string(SamplerFormat const format) noexcept {
switch (format) {
case SamplerFormat::INT:
return "INT";
case SamplerFormat::UINT:
return "UINT";
case SamplerFormat::FLOAT:
return "FLOAT";
case SamplerFormat::SHADOW:
return "SHADOW";
}
return "Unknown";
}
/**
* Supported element types
*/
@@ -764,6 +907,8 @@ enum class TextureFormat : uint16_t {
SRGB_ALPHA_BPTC_UNORM, // BC7 sRGB
};
TextureType getTextureType(TextureFormat format) noexcept;
//! Bitmask describing the intended Texture Usage
enum class TextureUsage : uint16_t {
NONE = 0x0000,
@@ -791,7 +936,7 @@ enum class TextureSwizzle : uint8_t {
};
//! returns whether this format a depth format
static constexpr bool isDepthFormat(TextureFormat format) noexcept {
constexpr bool isDepthFormat(TextureFormat format) noexcept {
switch (format) {
case TextureFormat::DEPTH32F:
case TextureFormat::DEPTH24:
@@ -804,7 +949,7 @@ static constexpr bool isDepthFormat(TextureFormat format) noexcept {
}
}
static constexpr bool isStencilFormat(TextureFormat format) noexcept {
constexpr bool isStencilFormat(TextureFormat format) noexcept {
switch (format) {
case TextureFormat::STENCIL8:
case TextureFormat::DEPTH24_STENCIL8:
@@ -815,7 +960,7 @@ static constexpr bool isStencilFormat(TextureFormat format) noexcept {
}
}
inline constexpr bool isColorFormat(TextureFormat format) noexcept {
constexpr bool isColorFormat(TextureFormat format) noexcept {
switch (format) {
// Standard color formats
case TextureFormat::R8:
@@ -842,7 +987,7 @@ inline constexpr bool isColorFormat(TextureFormat format) noexcept {
return false;
}
static constexpr bool isUnsignedIntFormat(TextureFormat format) {
constexpr bool isUnsignedIntFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8UI:
case TextureFormat::R16UI:
@@ -863,7 +1008,7 @@ static constexpr bool isUnsignedIntFormat(TextureFormat format) {
}
}
static constexpr bool isSignedIntFormat(TextureFormat format) {
constexpr bool isSignedIntFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8I:
case TextureFormat::R16I:
@@ -885,35 +1030,35 @@ static constexpr bool isSignedIntFormat(TextureFormat format) {
}
//! returns whether this format is a compressed format
static constexpr bool isCompressedFormat(TextureFormat format) noexcept {
constexpr bool isCompressedFormat(TextureFormat format) noexcept {
return format >= TextureFormat::EAC_R11;
}
//! returns whether this format is an ETC2 compressed format
static constexpr bool isETC2Compression(TextureFormat format) noexcept {
constexpr bool isETC2Compression(TextureFormat format) noexcept {
return format >= TextureFormat::EAC_R11 && format <= TextureFormat::ETC2_EAC_SRGBA8;
}
//! returns whether this format is an S3TC compressed format
static constexpr bool isS3TCCompression(TextureFormat format) noexcept {
constexpr bool isS3TCCompression(TextureFormat format) noexcept {
return format >= TextureFormat::DXT1_RGB && format <= TextureFormat::DXT5_SRGBA;
}
static constexpr bool isS3TCSRGBCompression(TextureFormat format) noexcept {
constexpr bool isS3TCSRGBCompression(TextureFormat format) noexcept {
return format >= TextureFormat::DXT1_SRGB && format <= TextureFormat::DXT5_SRGBA;
}
//! returns whether this format is an RGTC compressed format
static constexpr bool isRGTCCompression(TextureFormat format) noexcept {
constexpr bool isRGTCCompression(TextureFormat format) noexcept {
return format >= TextureFormat::RED_RGTC1 && format <= TextureFormat::SIGNED_RED_GREEN_RGTC2;
}
//! returns whether this format is an BPTC compressed format
static constexpr bool isBPTCCompression(TextureFormat format) noexcept {
constexpr bool isBPTCCompression(TextureFormat format) noexcept {
return format >= TextureFormat::RGB_BPTC_SIGNED_FLOAT && format <= TextureFormat::SRGB_ALPHA_BPTC_UNORM;
}
static constexpr bool isASTCCompression(TextureFormat format) noexcept {
constexpr bool isASTCCompression(TextureFormat format) noexcept {
return format >= TextureFormat::RGBA_ASTC_4x4 && format <= TextureFormat::SRGB8_ALPHA8_ASTC_12x12;
}
@@ -1038,15 +1183,19 @@ struct SamplerParams { // NOLINT
}
};
bool isFiltered() const noexcept {
return filterMag != SamplerMagFilter::NEAREST || filterMin != SamplerMinFilter::NEAREST;
}
private:
friend inline bool operator == (SamplerParams lhs, SamplerParams rhs) noexcept {
return SamplerParams::EqualTo{}(lhs, rhs);
friend bool operator == (SamplerParams lhs, SamplerParams rhs) noexcept {
return EqualTo{}(lhs, rhs);
}
friend inline bool operator != (SamplerParams lhs, SamplerParams rhs) noexcept {
return !SamplerParams::EqualTo{}(lhs, rhs);
friend bool operator != (SamplerParams lhs, SamplerParams rhs) noexcept {
return !EqualTo{}(lhs, rhs);
}
friend inline bool operator < (SamplerParams lhs, SamplerParams rhs) noexcept {
return SamplerParams::LessThan{}(lhs, rhs);
friend bool operator < (SamplerParams lhs, SamplerParams rhs) noexcept {
return LessThan{}(lhs, rhs);
}
};
@@ -1096,15 +1245,15 @@ struct SamplerYcbcrConversion {// NOLINT
};
private:
friend inline bool operator == (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
friend bool operator == (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
noexcept {
return SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
}
friend inline bool operator != (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
friend bool operator != (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
noexcept {
return !SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
}
friend inline bool operator < (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
friend bool operator < (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
noexcept {
return SamplerYcbcrConversion::LessThan{}(lhs, rhs);
}

View File

@@ -18,6 +18,8 @@
#include "DataReshaper.h"
#include <backend/DriverEnums.h>
#include <utils/CString.h>
#include <string_view>
@@ -223,6 +225,143 @@ size_t getFormatSize(TextureFormat format) noexcept {
}
}
TextureType getTextureType(TextureFormat const format) noexcept {
switch (format) {
case TextureFormat::UNUSED:
// should not happen
return TextureType::FLOAT;
case TextureFormat::R8:
case TextureFormat::R16F:
case TextureFormat::RG8:
case TextureFormat::RGB565:
case TextureFormat::RGB5_A1:
case TextureFormat::RGBA4:
case TextureFormat::R32F:
case TextureFormat::RGB8:
case TextureFormat::SRGB8:
case TextureFormat::RG16F:
case TextureFormat::R11F_G11F_B10F:
case TextureFormat::RGB9_E5:
case TextureFormat::RGBA8:
case TextureFormat::SRGB8_A8:
case TextureFormat::RGB10_A2:
case TextureFormat::RGB16F:
case TextureFormat::RG32F:
case TextureFormat::RGBA16F:
case TextureFormat::RGB32F:
case TextureFormat::RGBA32F:
return TextureType::FLOAT;
case TextureFormat::R8_SNORM:
case TextureFormat::RG8_SNORM:
case TextureFormat::RGB8_SNORM:
case TextureFormat::RGBA8_SNORM:
// SNORM are treated as float
return TextureType::FLOAT;
case TextureFormat::R8UI:
case TextureFormat::R16UI:
case TextureFormat::RG8UI:
case TextureFormat::RGB8UI:
case TextureFormat::R32UI:
case TextureFormat::RG16UI:
case TextureFormat::RGBA8UI:
case TextureFormat::RGB16UI:
case TextureFormat::RG32UI:
case TextureFormat::RGBA16UI:
case TextureFormat::RGB32UI:
case TextureFormat::RGBA32UI:
return TextureType::UINT;
case TextureFormat::R8I:
case TextureFormat::R16I:
case TextureFormat::RG8I:
case TextureFormat::RGB8I:
case TextureFormat::R32I:
case TextureFormat::RG16I:
case TextureFormat::RGBA8I:
case TextureFormat::RGB16I:
case TextureFormat::RG32I:
case TextureFormat::RGBA16I:
case TextureFormat::RGB32I:
case TextureFormat::RGBA32I:
return TextureType::INT;
case TextureFormat::DEPTH16:
case TextureFormat::DEPTH24:
case TextureFormat::DEPTH32F:
return TextureType::DEPTH;
case TextureFormat::STENCIL8:
return TextureType::STENCIL;
case TextureFormat::DEPTH24_STENCIL8:
case TextureFormat::DEPTH32F_STENCIL8:
return TextureType::DEPTH_STENCIL;
// Compressed formats ---------------------------------------------------------------------
case TextureFormat::EAC_RG11:
case TextureFormat::EAC_RG11_SIGNED:
case TextureFormat::ETC2_EAC_RGBA8:
case TextureFormat::ETC2_EAC_SRGBA8:
case TextureFormat::EAC_R11:
case TextureFormat::EAC_R11_SIGNED:
case TextureFormat::ETC2_RGB8:
case TextureFormat::ETC2_SRGB8:
case TextureFormat::ETC2_RGB8_A1:
case TextureFormat::ETC2_SRGB8_A1:
case TextureFormat::DXT1_RGB:
case TextureFormat::DXT1_RGBA:
case TextureFormat::DXT1_SRGB:
case TextureFormat::DXT1_SRGBA:
case TextureFormat::DXT3_RGBA:
case TextureFormat::DXT3_SRGBA:
case TextureFormat::DXT5_RGBA:
case TextureFormat::DXT5_SRGBA:
case TextureFormat::RED_RGTC1:
case TextureFormat::SIGNED_RED_RGTC1:
case TextureFormat::RED_GREEN_RGTC2:
case TextureFormat::SIGNED_RED_GREEN_RGTC2:
case TextureFormat::RGB_BPTC_SIGNED_FLOAT:
case TextureFormat::RGB_BPTC_UNSIGNED_FLOAT:
case TextureFormat::RGBA_BPTC_UNORM:
case TextureFormat::SRGB_ALPHA_BPTC_UNORM:
case TextureFormat::RGBA_ASTC_4x4:
case TextureFormat::RGBA_ASTC_5x4:
case TextureFormat::RGBA_ASTC_5x5:
case TextureFormat::RGBA_ASTC_6x5:
case TextureFormat::RGBA_ASTC_6x6:
case TextureFormat::RGBA_ASTC_8x5:
case TextureFormat::RGBA_ASTC_8x6:
case TextureFormat::RGBA_ASTC_8x8:
case TextureFormat::RGBA_ASTC_10x5:
case TextureFormat::RGBA_ASTC_10x6:
case TextureFormat::RGBA_ASTC_10x8:
case TextureFormat::RGBA_ASTC_10x10:
case TextureFormat::RGBA_ASTC_12x10:
case TextureFormat::RGBA_ASTC_12x12:
case TextureFormat::SRGB8_ALPHA8_ASTC_4x4:
case TextureFormat::SRGB8_ALPHA8_ASTC_5x4:
case TextureFormat::SRGB8_ALPHA8_ASTC_5x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_6x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_6x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x8:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x8:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x10:
case TextureFormat::SRGB8_ALPHA8_ASTC_12x10:
case TextureFormat::SRGB8_ALPHA8_ASTC_12x12:
return TextureType::FLOAT;
}
return TextureType::FLOAT;
}
size_t getFormatComponentCount(TextureFormat format) noexcept {
switch (format) {
case TextureFormat::R8:

View File

@@ -672,22 +672,8 @@ void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
// nothing to do, timer query was constructed in createTimerQueryS
}
const char* toString(DescriptorType type) {
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";
}
}
const char* toString(ShaderStageFlags flags) {
UTILS_UNUSED
static const char* toString(ShaderStageFlags flags) {
std::vector<const char*> stages;
if (any(flags & ShaderStageFlags::VERTEX)) {
stages.push_back("VERTEX");

View File

@@ -1356,7 +1356,25 @@ id<MTLArgumentEncoder> MetalDescriptorSetLayout::getArgumentEncoderSlow(id<MTLDe
[arguments addObject:bufferArgument];
break;
}
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER_EXTERNAL: {
MTLArgumentDescriptor* textureArgument = [MTLArgumentDescriptor argumentDescriptor];
textureArgument.index = binding.binding * 2;
@@ -1472,7 +1490,25 @@ id<MTLBuffer> MetalDescriptorSet::finalizeAndGetBuffer(MetalDriver* driver, Shad
atIndex:binding.binding * 2];
break;
}
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER_EXTERNAL: {
auto found = textures.find(binding.binding);
if (found == textures.end()) {

View File

@@ -69,9 +69,8 @@ public:
assert_invariant(set < MAX_DESCRIPTOR_SET_COUNT);
assert_invariant(binding < MAX_DESCRIPTOR_COUNT);
assert_invariant(entry.binding < 128); // we reserve 1 bit for the type right now
mStorage[set][binding] = { (uint8_t)entry.binding,
entry.type == DescriptorType::SAMPLER ||
entry.type == DescriptorType::SAMPLER_EXTERNAL };
mStorage[set][binding] = { uint8_t(entry.binding),
DescriptorSetLayoutBinding::isSampler(entry.type) };
mActiveDescriptors[set].set(binding);
}

View File

@@ -95,7 +95,26 @@ GLDescriptorSet::GLDescriptorSet(OpenGLContext& gl, DescriptorSetLayoutHandle ds
}
break;
}
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER_EXTERNAL:
if (UTILS_UNLIKELY(gl.isES2())) {
desc.emplace<SamplerGLES2>();

View File

@@ -175,7 +175,25 @@ void OpenGLProgram::initializeProgramState(OpenGLContext& context, GLuint progra
}
break;
}
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER_EXTERNAL: {
if (!entry.name.empty()) {
GLint const loc = glGetUniformLocation(program, entry.name.c_str());

View File

@@ -93,7 +93,26 @@ BitmaskGroup fromBackendLayout(DescriptorSetLayout const& layout) {
case DescriptorType::SAMPLER_EXTERNAL:
fromStageFlags(binding.stageFlags, binding.binding, mask.externalSampler);
UTILS_FALLTHROUGH;
case DescriptorType::SAMPLER: {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT: {
fromStageFlags(binding.stageFlags, binding.binding, mask.sampler);
break;
}

View File

@@ -469,7 +469,7 @@ void WebGPUDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
mDevice, flags);
assert_invariant(mSwapChain);
WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(mDevice,
mSwapChain->getColorFormat());
mSwapChain->getColorFormat(), mSwapChain->getDepthFormat());
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."
@@ -591,7 +591,7 @@ 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, layout->getLayout(), layout->getBindGroupEntries(), layout->label);
}
Handle<HwStream> WebGPUDriver::createStreamNative(void* nativeStream) {
@@ -1069,97 +1069,98 @@ wgpu::Sampler WebGPUDriver::makeSampler(SamplerParams const& params) {
desc.addressModeU = fWrapModeToWAddressMode(params.wrapS);
desc.addressModeV = fWrapModeToWAddressMode(params.wrapR);
desc.addressModeW = fWrapModeToWAddressMode(params.wrapT);
switch (params.filterMag) {
case SamplerMagFilter::NEAREST: {
desc.magFilter = wgpu::FilterMode::Nearest;
break;
if (params.compareMode == SamplerCompareMode::COMPARE_TO_TEXTURE) {
switch (params.filterMag) {
case SamplerMagFilter::NEAREST: {
desc.magFilter = wgpu::FilterMode::Nearest;
break;
}
case SamplerMagFilter::LINEAR: {
desc.magFilter = wgpu::FilterMode::Linear;
break;
}
}
case SamplerMagFilter::LINEAR: {
desc.magFilter = wgpu::FilterMode::Linear;
break;
}
}
switch (params.filterMin) {
case SamplerMinFilter::NEAREST: {
desc.minFilter = wgpu::FilterMode::Nearest;
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
// suffice
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::LINEAR: {
desc.minFilter = wgpu::FilterMode::Linear;
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
// suffice
switch (params.filterMin) {
case SamplerMinFilter::NEAREST: {
desc.minFilter = wgpu::FilterMode::Nearest;
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
// suffice
desc.mipmapFilter = wgpu::MipmapFilterMode::Undefined;
break;
}
case SamplerMinFilter::LINEAR: {
desc.minFilter = wgpu::FilterMode::Linear;
// Metal Driver uses an explicit not-mipmapped value webgpu lacks. Nearest should
// suffice
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST: {
desc.minFilter = wgpu::FilterMode::Nearest;
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST: {
desc.minFilter = wgpu::FilterMode::Linear;
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
desc.mipmapFilter = wgpu::MipmapFilterMode::Undefined;
break;
}
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST: {
desc.minFilter = wgpu::FilterMode::Nearest;
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST: {
desc.minFilter = wgpu::FilterMode::Linear;
desc.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
break;
}
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR: {
desc.minFilter = wgpu::FilterMode::Nearest;
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
break;
}
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR: {
desc.minFilter = wgpu::FilterMode::Nearest;
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
break;
break;
}
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR: {
desc.minFilter = wgpu::FilterMode::Linear;
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
break;
}
}
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR: {
desc.minFilter = wgpu::FilterMode::Linear;
desc.mipmapFilter = wgpu::MipmapFilterMode::Linear;
break;
}
}
switch (params.compareFunc) {
case SamplerCompareFunc::LE: {
desc.compare = wgpu::CompareFunction::LessEqual;
break;
}
case SamplerCompareFunc::GE: {
desc.compare = wgpu::CompareFunction::GreaterEqual;
break;
}
case SamplerCompareFunc::L: {
desc.compare = wgpu::CompareFunction::Less;
break;
}
case SamplerCompareFunc::G: {
desc.compare = wgpu::CompareFunction::Greater;
break;
}
case SamplerCompareFunc::E: {
desc.compare = wgpu::CompareFunction::Equal;
break;
}
case SamplerCompareFunc::NE: {
desc.compare = wgpu::CompareFunction::NotEqual;
break;
}
case SamplerCompareFunc::A: {
desc.compare = wgpu::CompareFunction::Always;
break;
}
case SamplerCompareFunc::N: {
desc.compare = wgpu::CompareFunction::Never;
break;
switch (params.compareFunc) {
case SamplerCompareFunc::LE: {
desc.compare = wgpu::CompareFunction::LessEqual;
break;
}
case SamplerCompareFunc::GE: {
desc.compare = wgpu::CompareFunction::GreaterEqual;
break;
}
case SamplerCompareFunc::L: {
desc.compare = wgpu::CompareFunction::Less;
break;
}
case SamplerCompareFunc::G: {
desc.compare = wgpu::CompareFunction::Greater;
break;
}
case SamplerCompareFunc::E: {
desc.compare = wgpu::CompareFunction::Equal;
break;
}
case SamplerCompareFunc::NE: {
desc.compare = wgpu::CompareFunction::NotEqual;
break;
}
case SamplerCompareFunc::A: {
desc.compare = wgpu::CompareFunction::Always;
break;
}
case SamplerCompareFunc::N: {
desc.compare = wgpu::CompareFunction::Never;
break;
}
}
}
desc.maxAnisotropy = 1u << params.anisotropyLog2;
// Unused: Filament's compareMode, WGPU lodMinClamp/lodMaxClamp
// Unused: WGPU lodMinClamp/lodMaxClamp
//TODO Once we can properly map to descriptorsetlayout use the sampler.
return mDevice.CreateSampler(/*&desc*/);
return mDevice.CreateSampler(&desc);
}
wgpu::AddressMode WebGPUDriver::fWrapModeToWAddressMode(const SamplerWrapMode& fWrapMode) {
switch (fWrapMode) {

View File

@@ -247,6 +247,7 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
const auto& temp = std::get_if<utils::CString>(&layout.label);
baseLabel = temp->c_str();
}
label = baseLabel;
// TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
// debugging. For now, hack an incrementing value.
@@ -254,8 +255,7 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
unsigned int samplerCount =
std::count_if(layout.bindings.begin(), layout.bindings.end(), [](auto& fEntry) {
return fEntry.type == DescriptorType::SAMPLER ||
fEntry.type == DescriptorType::SAMPLER_EXTERNAL;
return DescriptorSetLayoutBinding::isSampler(fEntry.type);
});
@@ -269,12 +269,31 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
wEntry.visibility = filamentStageToWGPUStage(fEntry.stageFlags);
wEntry.binding = fEntry.binding * 2;
entryInfo.binding = wEntry.binding;
wgpu::BindGroupLayoutEntry* sEntry;
switch (fEntry.type) {
case DescriptorType::SAMPLER_EXTERNAL:
case DescriptorType::SAMPLER: {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT: {
auto& samplerEntry = wEntries.emplace_back();
auto& samplerEntryInfo = mBindGroupEntries.emplace_back();
sEntry = &samplerEntry;
samplerEntry.binding = fEntry.binding * 2 + 1;
samplerEntryInfo.binding = samplerEntry.binding;
samplerEntryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::SAMPLER;
@@ -282,15 +301,6 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
// We are simply hoping that undefined and defaults suffices here.
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)) {
wEntry.texture.viewDimension = wgpu::TextureViewDimension::Cube;
} else {
wEntry.texture.viewDimension =
wgpu::TextureViewDimension::e2D;// Example default
}
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW;
break;
}
case DescriptorType::UNIFORM_BUFFER: {
@@ -310,6 +320,81 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
PANIC_POSTCONDITION("Shader storage is not supported");
break;
}
case DescriptorType::SAMPLER_EXTERNAL: {
PANIC_POSTCONDITION("External Sampler is not supported");
break;
}
}
switch (fEntry.type) {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e2D;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2D;
break;
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e2DArray;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2DA;
break;
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::Cube;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBE;
break;
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::CubeArray;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBEA;
break;
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
wEntry.texture.viewDimension = wgpu::TextureViewDimension::e3D;
entryInfo.type = WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_3D;
break;
default:
break;
}
switch (fEntry.type) {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_3D_FLOAT:
wEntry.texture.sampleType = wgpu::TextureSampleType::UnfilterableFloat;
break;
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_3D_INT:
wEntry.texture.sampleType = wgpu::TextureSampleType::Sint;
break;
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_3D_UINT:
wEntry.texture.sampleType = wgpu::TextureSampleType::Uint;
break;
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
//Dummies complain if you set this correctly without having an associated dummy
wEntry.texture.sampleType = wgpu::TextureSampleType::Depth;
sEntry->sampler.type = wgpu::SamplerBindingType::Comparison;
break;
default:
break;
}
// fEntry.count is unused currently
}
@@ -325,12 +410,12 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
WebGPUDescriptorSetLayout::~WebGPUDescriptorSetLayout() {}
wgpu::Buffer WebGPUDescriptorSet::sDummyUniformBuffer = nullptr;
wgpu::Texture WebGPUDescriptorSet::sDummyTexture = nullptr;
wgpu::TextureView WebGPUDescriptorSet::sDummyTextureView = nullptr;
std::unordered_map<wgpu::TextureDimension, wgpu::Texture> WebGPUDescriptorSet::sDummyTextureMap;
std::unordered_map<wgpu::TextureViewDimension, wgpu::TextureView> WebGPUDescriptorSet::sDummyTextureViewMap;
wgpu::Sampler WebGPUDescriptorSet::sDummySampler = nullptr;
void WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(wgpu::Device const& device,
wgpu::TextureFormat aColorFormat) {
wgpu::TextureFormat aColorFormat, wgpu::TextureFormat aDepthFormat) {
if (!sDummyUniformBuffer) {
wgpu::BufferDescriptor bufferDescriptor{
.label = "dummy_uniform_not_to_be_used",
@@ -341,31 +426,75 @@ void WebGPUDescriptorSet::initializeDummyResourcesIfNotAlready(wgpu::Device cons
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer)
<< "Failed to create dummy uniform buffer?";
}
if (!sDummyTexture || !sDummyTextureView) {
if (sDummyTextureMap.empty() || sDummyTextureViewMap.empty()) {
wgpu::TextureDescriptor textureDescriptor{
.label = "dummy_texture_not_to_be_used",
.usage = wgpu::TextureUsage::TextureBinding,
.dimension = wgpu::TextureDimension::e2D,
.size = wgpu::Extent3D{ .width = 4, .height = 4, .depthOrArrayLayers = 1 },
.format = aColorFormat,
// .viewFormatCount = 1,
// .viewFormats = &aDepthFormat
};
if (!sDummyTexture) {
sDummyTexture = device.CreateTexture(&textureDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer) << "Failed to create dummy texture?";
}
if (!sDummyTextureView) {
wgpu::TextureViewDescriptor textureViewDescriptor{
.label = "dummy_texture_view_not_to_be_used"
};
sDummyTextureView = sDummyTexture.CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer)
<< "Failed to create dummy texture view?";
}
sDummyTextureMap[wgpu::TextureDimension::e2D] = device.CreateTexture(&textureDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureMap[wgpu::TextureDimension::e2D])
<< "Failed to create dummy texture 2D?";
textureDescriptor.dimension = wgpu::TextureDimension::e3D;
sDummyTextureMap[wgpu::TextureDimension::e3D] = device.CreateTexture(&textureDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureMap[wgpu::TextureDimension::e3D])
<< "Failed to create dummy texture 3D?";
//Hacking as an experiment, treating 1D as cube arbitrarilly since my map key was bad idea
textureDescriptor.dimension = wgpu::TextureDimension::e2D;
textureDescriptor.size.depthOrArrayLayers = 6;
sDummyTextureMap[wgpu::TextureDimension::e1D] = device.CreateTexture(&textureDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureMap[wgpu::TextureDimension::e1D])
<< "Failed to create dummy texture 3D?";
wgpu::TextureViewDescriptor textureViewDescriptor{
.label = "dummy_texture_view_not_to_be_used",
};
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
sDummyTextureViewMap[wgpu::TextureViewDimension::e2D] =
sDummyTextureMap[wgpu::TextureDimension::e2D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e2D])
<< "Failed to create dummy texture view?";
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2DArray;
sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray] =
sDummyTextureMap[wgpu::TextureDimension::e2D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e2D])
<< "Failed to create dummy texture view?";
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e2DArray;
sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray] =
sDummyTextureMap[wgpu::TextureDimension::e2D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray])
<< "Failed to create dummy texture view?";
textureViewDescriptor.dimension = wgpu::TextureViewDimension::e3D;
sDummyTextureViewMap[wgpu::TextureViewDimension::e3D] =
sDummyTextureMap[wgpu::TextureDimension::e3D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::e3D])
<< "Failed to create dummy texture view?";
textureViewDescriptor.arrayLayerCount = 6;
textureViewDescriptor.dimension = wgpu::TextureViewDimension::Cube;
sDummyTextureViewMap[wgpu::TextureViewDimension::Cube] =
sDummyTextureMap[wgpu::TextureDimension::e1D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::Cube])
<< "Failed to create dummy texture view?";
textureViewDescriptor.dimension = wgpu::TextureViewDimension::CubeArray;
sDummyTextureViewMap[wgpu::TextureViewDimension::CubeArray] =
sDummyTextureMap[wgpu::TextureDimension::e1D].CreateView(&textureViewDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyTextureViewMap[wgpu::TextureViewDimension::CubeArray])
<< "Failed to create dummy texture view?";
}
if (!sDummySampler) {
wgpu::SamplerDescriptor samplerDescriptor{
.label = "dummy_sampler_not_to_be_used"
};
wgpu::SamplerDescriptor samplerDescriptor{ .label = "dummy_sampler_not_to_be_used" , .addressModeU = wgpu::AddressMode::MirrorRepeat};
sDummySampler = device.CreateSampler(&samplerDescriptor);
FILAMENT_CHECK_POSTCONDITION(sDummyUniformBuffer) << "Failed to create dummy sampler?";
}
@@ -377,12 +506,12 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
assert_invariant(WebGPUDescriptorSet::sDummyUniformBuffer &&
"Dummy uniform buffer must have been created before "
"creating dummy bind group entries.");
assert_invariant(
/* assert_invariant(
WebGPUDescriptorSet::sDummyTexture &&
"Dummy texture must have been created before creating dummy bind group entries.");
assert_invariant(
WebGPUDescriptorSet::sDummyTextureView &&
"Dummy texture view must have been created before creating dummy bind group entries.");
"Dummy texture view must have been created before creating dummy bind group entries.");*/
assert_invariant(
WebGPUDescriptorSet::sDummySampler &&
"Dummy sampler must have been created before creating dummy bind group entries.");
@@ -394,14 +523,31 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
entry.binding = entryInfo.binding;
switch (entryInfo.type) {
case WebGPUDescriptorSetLayout::BindGroupEntryType::UNIFORM_BUFFER:
entry.buffer = WebGPUDescriptorSet::sDummyUniformBuffer;
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW:
entry.textureView = WebGPUDescriptorSet::sDummyTextureView;
//entry.buffer = WebGPUDescriptorSet::sDummyUniformBuffer;
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::SAMPLER:
entry.sampler = WebGPUDescriptorSet::sDummySampler;
// entry.sampler = WebGPUDescriptorSet::sDummySampler;
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2D:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::e2D];
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_2DA:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::e2DArray];
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBE:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::Cube];
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_CUBEA:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::CubeArray];
break;
case WebGPUDescriptorSetLayout::BindGroupEntryType::TEXTURE_VIEW_3D:
// entry.textureView = WebGPUDescriptorSet::sDummyTextureViewMap[wgpu::TextureViewDimension::e3D];
break;
default: break;
}
}
std::sort(entries.begin(), entries.end(),
@@ -412,9 +558,10 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
}
WebGPUDescriptorSet::WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries)
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries, std::string label)
: mLayout(layout),
mEntriesSortedByBinding(createDummyEntriesSortedByBinding(bindGroupEntries)) {
bglLabel = label;
// Establish the size of entries based on the layout. This should be reliable and efficient.
assert_invariant(INVALID_INDEX > mEntryIndexByBinding.size());
for (size_t i = 0; i < mEntryIndexByBinding.size(); i++) {
@@ -449,6 +596,20 @@ wgpu::BindGroup WebGPUDescriptorSet::lockAndReturn(const wgpu::Device& device) {
.entryCount = mEntriesSortedByBinding.size(),
.entries = mEntriesSortedByBinding.data()
};
for(auto e : mEntriesSortedByBinding){
if(e.sampler.Get() == sDummySampler.Get()){
printf("===R Dummy %s UBO %i\n", bglLabel.c_str(), e.binding/2);
}
for(auto dt : sDummyTextureViewMap){
if(e.textureView.Get() == dt.second.Get())
{
printf("===R Dummy %s Tex %i\n", bglLabel.c_str(), e.binding/2);
}
}
if(e.buffer.Get() == sDummyUniformBuffer.Get()){
printf("===R Dummy %s Sam %i\n", bglLabel.c_str(),(e.binding-1)/2);
}
}
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

View File

@@ -103,10 +103,15 @@ struct WGPUBufferObject : HwBufferObject {
class WebGPUDescriptorSetLayout final : public HwDescriptorSetLayout {
public:
std::string label;
enum class BindGroupEntryType : uint8_t {
UNIFORM_BUFFER,
TEXTURE_VIEW,
TEXTURE_VIEW_2D,
TEXTURE_VIEW_2DA,
TEXTURE_VIEW_CUBE,
TEXTURE_VIEW_CUBEA,
TEXTURE_VIEW_3D,
SAMPLER
};
@@ -133,11 +138,13 @@ private:
class WebGPUDescriptorSet final : public HwDescriptorSet {
public:
std::string bglLabel;
static void initializeDummyResourcesIfNotAlready(wgpu::Device const&,
wgpu::TextureFormat aColorFormat);
wgpu::TextureFormat aColorFormat,
wgpu::TextureFormat aDepthFormat);
WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries);
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const& bindGroupEntries, std::string label);
~WebGPUDescriptorSet();
wgpu::BindGroup lockAndReturn(wgpu::Device const&);
@@ -148,8 +155,8 @@ public:
private:
static wgpu::Buffer sDummyUniformBuffer;
static wgpu::Texture sDummyTexture;
static wgpu::TextureView sDummyTextureView;
static std::unordered_map<wgpu::TextureDimension, wgpu::Texture> sDummyTextureMap;
static std::unordered_map<wgpu::TextureViewDimension, wgpu::TextureView> sDummyTextureViewMap;
static wgpu::Sampler sDummySampler;
static std::vector<wgpu::BindGroupEntry> createDummyEntriesSortedByBinding(

View File

@@ -184,7 +184,7 @@ std::vector<UniformConfig> GetUniformConfig(ShaderUniformType type) {
"backend_test", "test_tex", 0,
SamplerType::SAMPLER_2D, SamplerFormat::FLOAT, Precision::HIGH, false };
return {{
"test_tex", DescriptorType::SAMPLER, samplerInfo
"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
}};
}
default:

View File

@@ -118,7 +118,7 @@ TEST_F(BackendTest, FeedbackLoops) {
Shader shader = Shader(api, cleanup, ShaderConfig {
.vertexShader = fullscreenVs,
.fragmentShader = fullscreenFs,
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}, {"Params"}}
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}, {"Params"}}
});
TrianglePrimitive const triangle(getDriverApi());

View File

@@ -308,7 +308,7 @@ TEST_F(LoadImageTest, UpdateImage2D) {
Shader shader(api, cleanup, ShaderConfig{
.vertexShader = mVertexShader,
.fragmentShader= fragment,
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}}
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}}
});
// Create a Texture.
@@ -372,7 +372,7 @@ TEST_F(LoadImageTest, UpdateImageSRGB) {
getSamplerTypeName(textureFormat), fragmentTemplate);
Shader shader(api, cleanup, ShaderConfig{
.vertexShader = mVertexShader, .fragmentShader = fragment, .uniforms = {{
"test_tex", DescriptorType::SAMPLER, samplerInfo
"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
}}});
// Create a texture.
@@ -447,7 +447,7 @@ TEST_F(LoadImageTest, UpdateImageMipLevel) {
Shader shader(api, cleanup, ShaderConfig {
.vertexShader = mVertexShader,
.fragmentShader = fragment,
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}}
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo}}
});
// Create a texture with 3 mip levels.
@@ -508,7 +508,7 @@ TEST_F(LoadImageTest, UpdateImage3D) {
Shader shader(api, cleanup, ShaderConfig {
.vertexShader = mVertexShader,
.fragmentShader = fragment,
.uniforms = {{"test_tex", DescriptorType::SAMPLER, samplerInfo}}
.uniforms = {{"test_tex", DescriptorType::SAMPLER_2D_ARRAY_FLOAT, samplerInfo}}
});
// Create a texture.

View File

@@ -82,7 +82,7 @@ TEST_F(BackendTest, TextureViewLod) {
.vertexShader = vertexShader,
.fragmentShader = fragmentTexturedLod,
.uniforms = {{
"backend_test_sib_tex", DescriptorType::SAMPLER, samplerInfo
"backend_test_sib_tex", DescriptorType::SAMPLER_2D_FLOAT, samplerInfo
}}
});

View File

@@ -232,7 +232,7 @@ PostProcessManager::~PostProcessManager() noexcept = default;
void PostProcessManager::setFrameUniforms(DriverApi& driver,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
mPostProcessDescriptorSet.setFrameUniforms(driver, uniforms);
mSsrPassDescriptorSet.setFrameUniforms(uniforms);
mSsrPassDescriptorSet.setFrameUniforms(mEngine, uniforms);
}
void PostProcessManager::bindPostProcessDescriptorSet(DriverApi& driver) const noexcept {
@@ -504,6 +504,7 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph
FrameGraphTexture::Usage::DEPTH_ATTACHMENT);
if (config.picking) {
// FIXME: the DescriptorSetLayout must specify SAMPLER_FLOAT
data.picking = builder.createTexture("Picking Buffer", {
.width = width, .height = height,
.format = isES2 ? TextureFormat::RGBA8 : TextureFormat::RG32F });
@@ -653,7 +654,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::ssr(FrameGraph& fg,
options, passBuilder = passBuilder]
(FrameGraphResources const& resources, auto const& data, DriverApi& driver) mutable {
// set structure sampler
mSsrPassDescriptorSet.prepareStructure(data.structure ?
mSsrPassDescriptorSet.prepareStructure(mEngine, data.structure ?
resources.getTexture(data.structure) : getOneTexture());
// set screen-space reflections and screen-space refractions
@@ -664,7 +665,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::ssr(FrameGraph& fg,
// the history sampler is a regular texture2D
TextureHandle const history = data.history ?
resources.getTexture(data.history) : getZeroTexture();
mSsrPassDescriptorSet.prepareHistorySSR(history, reprojection, uvFromViewMatrix, options);
mSsrPassDescriptorSet.prepareHistorySSR(mEngine, history, reprojection, uvFromViewMatrix, options);
mSsrPassDescriptorSet.commit(mEngine);

View File

@@ -921,7 +921,6 @@ backend::Viewport RenderPass::Executor::applyScissorViewport(
UTILS_NOINLINE // no need to be inlined
void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
Command const* first, Command const* last) const noexcept {
SYSTRACE_CALL();
SYSTRACE_CONTEXT();
@@ -942,6 +941,13 @@ void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
driver.scissor(mScissor);
}
// If we have a mColorPassDescriptorSet, we need to use its idea of "VSM" to select
// the descriptor set layout. Materials always offer both.
// If we don't have a mColorPassDescriptorSet, it doesn't matter because the layout
// are chosen via the variant only.
bool const useVsmDescriptorSetLayout =
mColorPassDescriptorSet ? mColorPassDescriptorSet->isVSM() : false;
bool const polygonOffsetOverride = mPolygonOffsetOverride;
PipelineState pipeline{
// initialize with polygon offset override
@@ -1051,8 +1057,13 @@ void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver,
// Each material has its own version of the per-view descriptor-set layout,
// because it depends on the material features (e.g. lit/unlit)
// TODO: QUESTION: are
// Variant::isValidDepthVariant(info.materialVariant) and
// Variant::isSSRVariant(info.materialVariant)
// constant? If so we could precompute ma->getPerViewDescriptorSetLayout()
pipeline.pipelineLayout.setLayout[+DescriptorSetBindingPoints::PER_VIEW] =
ma->getPerViewDescriptorSetLayout(info.materialVariant).getHandle();
ma->getPerViewDescriptorSetLayout(info.materialVariant,
useVsmDescriptorSetLayout).getHandle();
// Each material has a per-material descriptor-set layout which encodes the
// material's parameters (ubo and samplers)

View File

@@ -205,11 +205,13 @@ RendererUtils::ColorPassOutput RendererUtils::colorPass(
view.prepareSSAO(data.ssao ?
resources.getTexture(data.ssao) : engine.getOneTextureArray());
view.prepareShadowMapping(view.getVsmShadowOptions().highPrecision);
view.prepareShadowMapping(engine, view.getVsmShadowOptions().highPrecision);
// set shadow sampler
view.prepareShadow(data.shadows ?
resources.getTexture(data.shadows) : engine.getOneTextureArray());
resources.getTexture(data.shadows) :
(view.getShadowType() != ShadowType::PCF ?
engine.getOneTextureArray() : engine.getOneTextureArrayDepth()));
// set structure sampler
view.prepareStructure(data.structure ?

View File

@@ -361,8 +361,6 @@ void FEngine::init() {
}
// initialize the dummy textures so that their contents are not undefined
static constexpr uint32_t zeroes[6] = {};
static constexpr uint32_t ones = 0xffffffff;
mDefaultIblTexture = downcast(Texture::Builder()
.width(1).height(1).levels(1)
@@ -371,7 +369,8 @@ void FEngine::init() {
.build(*this));
driverApi.update3DImage(mDefaultIblTexture->getHwHandle(), 0, 0, 0, 0, 1, 1, 6,
{ zeroes, sizeof(zeroes), Texture::Format::RGBA, Texture::Type::UBYTE });
{ std::array<uint8_t, 6>{}.data(), 6,
Texture::Format::RGBA, Texture::Type::UBYTE });
// 3 bands = 9 float3
constexpr float sh[9 * 3] = { 0.0f };
@@ -393,10 +392,12 @@ void FEngine::init() {
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
driverApi.update3DImage(mDummyOneTexture, 0, 0, 0, 0, 1, 1, 1,
{ &ones, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
{ std::array<uint8_t, 4>{0xff, 0xff, 0xff, 0xff}.data(), 4,
Texture::Format::RGBA, Texture::Type::UBYTE });
driverApi.update3DImage(mDummyZeroTexture, 0, 0, 0, 0, 1, 1, 1,
{ zeroes, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
{ std::array<uint8_t, 4>{}.data(), 4,
Texture::Format::RGBA, Texture::Type::UBYTE });
mPerViewDescriptorSetLayoutSsrVariant = {
@@ -423,25 +424,28 @@ void FEngine::init() {
} else
#endif
{
mDefaultColorGrading = downcast(ColorGrading::Builder().build(*this));
FMaterial::DefaultMaterialBuilder defaultMaterialBuilder;
switch (mConfig.stereoscopicType) {
case StereoscopicType::NONE:
case StereoscopicType::INSTANCED:
defaultMaterialBuilder.package(
MATERIALS_DEFAULTMATERIAL_DATA, MATERIALS_DEFAULTMATERIAL_SIZE);
MATERIALS_DEFAULTMATERIAL_DATA, MATERIALS_DEFAULTMATERIAL_SIZE);
break;
case StereoscopicType::MULTIVIEW:
#ifdef FILAMENT_ENABLE_MULTIVIEW
defaultMaterialBuilder.package(
MATERIALS_DEFAULTMATERIAL_MULTIVIEW_DATA, MATERIALS_DEFAULTMATERIAL_MULTIVIEW_SIZE);
MATERIALS_DEFAULTMATERIAL_MULTIVIEW_DATA,
MATERIALS_DEFAULTMATERIAL_MULTIVIEW_SIZE);
#else
assert_invariant(false);
#endif
break;
}
mDefaultMaterial = downcast(defaultMaterialBuilder.build(*this));
}
if (UTILS_UNLIKELY(getSupportedFeatureLevel() >= FeatureLevel::FEATURE_LEVEL_1)) {
mDefaultColorGrading = downcast(ColorGrading::Builder().build(*this));
constexpr float3 dummyPositions[1] = {};
constexpr short4 dummyTangents[1] = {};
@@ -451,14 +455,26 @@ void FEngine::init() {
mDummyOneTextureArray = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
mDummyOneTextureArrayDepth = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
TextureFormat::DEPTH32F, 1, 1, 1, 1, TextureUsage::DEFAULT);
mDummyZeroTextureArray = driverApi.createTexture(SamplerType::SAMPLER_2D_ARRAY, 1,
TextureFormat::RGBA8, 1, 1, 1, 1, TextureUsage::DEFAULT);
driverApi.update3DImage(mDummyOneTextureArray, 0, 0, 0, 0, 1, 1, 1,
{ &ones, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
{ std::array<uint8_t, 4>{0xff, 0xff, 0xff, 0xff}.data(), 4,
Texture::Format::RGBA, Texture::Type::UBYTE });
driverApi.update3DImage(mDummyOneTextureArrayDepth, 0, 0, 0, 0, 1, 1, 1,
{ std::array<float, 1>{1.0f}.data(), 4,
Texture::Format::DEPTH_COMPONENT, Texture::Type::FLOAT });
driverApi.update3DImage(mDummyZeroTextureArray, 0, 0, 0, 0, 1, 1, 1,
{ zeroes, 4, Texture::Format::RGBA, Texture::Type::UBYTE });
{ std::array<uint8_t, 4>{}.data(), 4,
Texture::Format::RGBA, Texture::Type::UBYTE });
mDummyUniformBuffer = driverApi.createBufferObject(CONFIG_MINSPEC_UBO_SIZE,
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
mLightManager.init(*this);
mDFG.init(*this);
@@ -608,6 +624,8 @@ void FEngine::shutdown() {
driver.destroyTexture(std::move(mDummyZeroTexture));
driver.destroyTexture(std::move(mDummyZeroTextureArray));
driver.destroyBufferObject(std::move(mDummyUniformBuffer));
driver.destroyRenderTarget(std::move(mDefaultRenderTarget));
/*
@@ -712,8 +730,7 @@ int FEngine::loop() {
if (mPlatform == nullptr) {
mPlatform = PlatformFactory::create(&mBackend);
mOwnPlatform = true;
const char* const backend = backendToString(mBackend);
slog.i << "FEngine resolved backend: " << backend << io::endl;
slog.i << "FEngine resolved backend: " << to_string(mBackend) << io::endl;
if (mPlatform == nullptr) {
slog.e << "Selected backend not supported in this build." << io::endl;
mDriverBarrier.latch();

View File

@@ -486,10 +486,29 @@ public:
return mPerRenderableDescriptorSetLayout;
}
backend::Handle<backend::HwTexture> getOneTexture() const { return mDummyOneTexture; }
backend::Handle<backend::HwTexture> getZeroTexture() const { return mDummyZeroTexture; }
backend::Handle<backend::HwTexture> getOneTextureArray() const { return mDummyOneTextureArray; }
backend::Handle<backend::HwTexture> getZeroTextureArray() const { return mDummyZeroTextureArray; }
backend::Handle<backend::HwTexture> getOneTexture() const {
return mDummyOneTexture;
}
backend::Handle<backend::HwTexture> getOneTextureArray() const {
return mDummyOneTextureArray;
}
backend::Handle<backend::HwTexture> getOneTextureArrayDepth() const {
return mDummyOneTextureArrayDepth;
}
backend::Handle<backend::HwTexture> getZeroTexture() const {
return mDummyZeroTexture;
}
backend::Handle<backend::HwTexture> getZeroTextureArray() const {
return mDummyZeroTextureArray;
}
backend::Handle<backend::HwBufferObject> getDummyUniformBuffer() const {
return mDummyUniformBuffer;
}
static constexpr size_t MiB = 1024u * 1024u;
size_t getMinCommandBufferSize() const noexcept { return mConfig.minCommandBufferSizeMB * MiB; }
@@ -628,8 +647,10 @@ private:
backend::Handle<backend::HwTexture> mDummyOneTexture;
backend::Handle<backend::HwTexture> mDummyOneTextureArray;
backend::Handle<backend::HwTexture> mDummyOneTextureArrayDepth;
backend::Handle<backend::HwTexture> mDummyZeroTextureArray;
backend::Handle<backend::HwTexture> mDummyZeroTexture;
backend::Handle<backend::HwBufferObject> mDummyUniformBuffer;
std::thread::id mMainThreadId{};

View File

@@ -96,7 +96,7 @@ static std::unique_ptr<MaterialParser> createParser(Backend const backend,
FILAMENT_CHECK_PRECONDITION(
materialResult != MaterialParser::ParseResult::ERROR_MISSING_BACKEND)
<< "the material was not built for any of the " << backendToString(backend)
<< "the material was not built for any of the " << to_string(backend)
<< " backend's supported shader languages (" << languageNames.c_str() << ")\n";
}
@@ -329,11 +329,12 @@ FMaterial::FMaterial(FEngine& engine, const Builder& builder,
parser->hasCustomDepthShader(&mHasCustomDepthShader);
mPerViewLayoutIndex = ColorPassDescriptorSet::getIndex(
mIsVariantLit,
mReflectionMode == ReflectionMode::SCREEN_SPACE ||
mRefractionMode == RefractionMode::SCREEN_SPACE,
!(mVariantFilterMask & +UserVariantFilterBit::FOG));
bool const isLit = mIsVariantLit || mHasShadowMultiplier;
bool const isSSR = mReflectionMode == ReflectionMode::SCREEN_SPACE ||
mRefractionMode == RefractionMode::SCREEN_SPACE;
bool const hasFog = !(mVariantFilterMask & UserVariantFilterMask(UserVariantFilterBit::FOG));
mPerViewLayoutIndex = ColorPassDescriptorSet::getIndex(isLit, isSSR, hasFog);
processBlendingMode(parser);
processSpecializationConstants(engine, builder, parser);
@@ -407,6 +408,7 @@ void FMaterial::terminate(FEngine& engine) {
DriverApi& driver = engine.getDriverApi();
mPerViewDescriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver);
mPerViewDescriptorSetLayoutVsm.terminate(engine.getDescriptorSetLayoutFactory(), driver);
mDescriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver);
}
@@ -1149,17 +1151,23 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con
backend::DescriptorSetLayout descriptorSetLayout;
success = parser->getDescriptorSetLayout(&descriptorSetLayout);
assert_invariant(success);
auto perMatLabel = mName;
perMatLabel.append("_perMat");
descriptorSetLayout.label = std::move(perMatLabel);
// get the PER_VIEW descriptor binding info
auto perViewDescriptorSetLayout =
descriptor_sets::getPerViewDescriptorSetLayout(mMaterialDomain, mVariantFilterMask,
mIsVariantLit || mHasShadowMultiplier, mReflectionMode, mRefractionMode);
auto perViewLabel = mName;
perViewLabel.append("_perView");
perViewDescriptorSetLayout.label = std::move(perViewLabel);
bool const isLit = mIsVariantLit || mHasShadowMultiplier;
bool const isSSR = mReflectionMode == ReflectionMode::SCREEN_SPACE ||
mRefractionMode == RefractionMode::SCREEN_SPACE;
bool const hasFog = !(mVariantFilterMask & UserVariantFilterMask(UserVariantFilterBit::FOG));
auto perViewDescriptorSetLayout = descriptor_sets::getPerViewDescriptorSetLayout(
mMaterialDomain, isLit, isSSR, hasFog, false);
auto perViewDescriptorSetLayoutVsm = descriptor_sets::getPerViewDescriptorSetLayout(
mMaterialDomain, isLit, isSSR, hasFog, true);
// set the labels
descriptorSetLayout.label = CString{ mName }.append("_perMat");
perViewDescriptorSetLayout.label = CString{ mName }.append("_perView");
perViewDescriptorSetLayoutVsm.label = CString{ mName }.append("_perViewVsm");
// get the PER_RENDERABLE and PER_VIEW descriptor binding info
for (auto&& [bindingPoint, descriptorSetLayout] : {
@@ -1181,7 +1189,11 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con
mPerViewDescriptorSetLayout = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(), perViewDescriptorSetLayout };
engine.getDriverApi(), std::move(perViewDescriptorSetLayout) };
mPerViewDescriptorSetLayoutVsm = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(), std::move(perViewDescriptorSetLayoutVsm) };
}
descriptor_binding_t FMaterial::getSamplerBinding(

View File

@@ -93,7 +93,8 @@ public:
return mPerViewDescriptorSetLayout;
}
DescriptorSetLayout const& getPerViewDescriptorSetLayout(Variant const variant) const noexcept {
DescriptorSetLayout const& getPerViewDescriptorSetLayout(
Variant const variant, bool const useVsmDescriptorSetLayout) const noexcept {
if (Variant::isValidDepthVariant(variant)) {
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
return mEngine.getPerViewDescriptorSetLayoutDepthVariant();
@@ -102,6 +103,10 @@ public:
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
return mEngine.getPerViewDescriptorSetLayoutSsrVariant();
}
if (useVsmDescriptorSetLayout) {
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
return mPerViewDescriptorSetLayoutVsm;
}
return mPerViewDescriptorSetLayout;
}
@@ -312,6 +317,7 @@ private:
// try to order by frequency of use
mutable std::array<backend::Handle<backend::HwProgram>, VARIANT_COUNT> mCachedPrograms;
DescriptorSetLayout mPerViewDescriptorSetLayout;
DescriptorSetLayout mPerViewDescriptorSetLayoutVsm;
DescriptorSetLayout mDescriptorSetLayout;
backend::Program::DescriptorSetInfo mProgramDescriptorBindings;

View File

@@ -50,6 +50,8 @@
#include <string_view>
#include <utility>
#include <stddef.h>
using namespace filament::math;
using namespace utils;
@@ -74,15 +76,17 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material,
FEngine::DriverApi& driver = engine.getDriverApi();
if (!material->getUniformInterfaceBlock().isEmpty()) {
mUniforms = UniformBuffer(material->getUniformInterfaceBlock().getSize());
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
driver.setDebugTag(mUbHandle.getId(), material->getName());
}
// even if the material doesn't have any parameters, we allocate a small UBO because it's
// expected by the per-material descriptor-set layout
size_t const uboSize = std::max(size_t(16), material->getUniformInterfaceBlock().getSize());
mUniforms = UniformBuffer(uboSize);
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
BufferObjectBinding::UNIFORM, BufferUsage::STATIC);
driver.setDebugTag(mUbHandle.getId(), material->getName());
// set the UBO, always descriptor 0
mDescriptorSet.setBuffer(0, mUbHandle, 0, mUniforms.getSize());
mDescriptorSet.setBuffer(material->getDescriptorSetLayout(),
0, mUbHandle, 0, mUniforms.getSize());
const RasterState& rasterState = material->getRasterState();
// At the moment, only MaterialInstances have a stencil state, but in the future it should be
@@ -142,15 +146,15 @@ FMaterialInstance::FMaterialInstance(FEngine& engine,
FEngine::DriverApi& driver = engine.getDriverApi();
FMaterial const* const material = other->getMaterial();
if (!material->getUniformInterfaceBlock().isEmpty()) {
mUniforms.setUniforms(other->getUniformBuffer());
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
driver.setDebugTag(mUbHandle.getId(), material->getName());
}
size_t const uboSize = std::max(size_t(16), material->getUniformInterfaceBlock().getSize());
mUniforms = UniformBuffer(uboSize);
mUbHandle = driver.createBufferObject(mUniforms.getSize(),
BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC);
driver.setDebugTag(mUbHandle.getId(), material->getName());
// set the UBO, always descriptor 0
mDescriptorSet.setBuffer(0, mUbHandle, 0, mUniforms.getSize());
mDescriptorSet.setBuffer(mMaterial->getDescriptorSetLayout(),
0, mUbHandle, 0, mUniforms.getSize());
if (material->hasDoubleSidedCapability()) {
setDoubleSided(mIsDoubleSided);
@@ -223,7 +227,8 @@ void FMaterialInstance::commit(DriverApi& driver) const {
<< "Invalid texture still bound to MaterialInstance: '" << getName() << "'\n";
Handle<HwTexture> const handle = p.texture->getHwHandleForSampling();
assert_invariant(handle);
mDescriptorSet.setSampler(binding, handle, p.params);
mDescriptorSet.setSampler(mMaterial->getDescriptorSetLayout(),
binding, handle, p.params);
}
}
@@ -239,7 +244,9 @@ void FMaterialInstance::commit(DriverApi& driver) const {
void FMaterialInstance::setParameter(std::string_view const name,
Handle<HwTexture> texture, SamplerParams const params) {
auto const binding = mMaterial->getSamplerBinding(name);
mDescriptorSet.setSampler(binding, texture, params);
mDescriptorSet.setSampler(mMaterial->getDescriptorSetLayout(),
binding, texture, params);
}
void FMaterialInstance::setParameterImpl(std::string_view const name,
@@ -266,6 +273,21 @@ void FMaterialInstance::setParameterImpl(std::string_view const name,
#endif
auto const binding = mMaterial->getSamplerBinding(name);
if (texture) {
auto const& descriptorSetLayout = mMaterial->getDescriptorSetLayout();
DescriptorType const descriptorType = descriptorSetLayout.getDescriptorType(binding);
TextureType const textureType = texture->getTextureType();
FILAMENT_CHECK_PRECONDITION(
DescriptorSet::isTextureCompatibleWithDescriptor(textureType, descriptorType))
<< "Texture format " << int(texture->getFormat())
<< " of type " << to_string(textureType)
<< " is not compatible with material \"" << getMaterial()->getName().c_str() << "\""
<< " parameter \"" << name << "\""
<< " of type " << to_string(descriptorType);
}
if (texture && texture->textureHandleCanMutate()) {
mTextureParameters[binding] = { texture, sampler.getSamplerParams() };
} else {
@@ -278,7 +300,8 @@ void FMaterialInstance::setParameterImpl(std::string_view const name,
handle = texture->getHwHandleForSampling();
assert_invariant(handle == texture->getHwHandle());
}
mDescriptorSet.setSampler(binding, handle, sampler.getSamplerParams());
mDescriptorSet.setSampler(mMaterial->getDescriptorSetLayout(),
binding, handle, sampler.getSamplerParams());
}
}
@@ -395,29 +418,30 @@ void FMaterialInstance::fixMissingSamplers() const {
auto const pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) {
return item.binding == binding;
});
FEngine const& engine = mMaterial->getEngine();
// just safety-check, should never fail
if (UTILS_LIKELY(pos != list.end())) {
switch (pos->type) {
case SamplerType::SAMPLER_2D:
mDescriptorSet.setSampler(binding,
engine.getZeroTexture(), {});
break;
case SamplerType::SAMPLER_2D_ARRAY:
mDescriptorSet.setSampler(binding,
engine.getZeroTextureArray(), {});
break;
case SamplerType::SAMPLER_CUBEMAP:
mDescriptorSet.setSampler(binding,
engine.getDummyCubemap()->getHwHandle(), {});
break;
case SamplerType::SAMPLER_EXTERNAL:
case SamplerType::SAMPLER_3D:
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
// we're currently not able to fix-up those
break;
FEngine const& engine = mMaterial->getEngine();
filament::DescriptorSetLayout const& layout = mMaterial->getDescriptorSetLayout();
if (pos->format != SamplerFormat::FLOAT) {
// TODO: we only handle missing samplers that are FLOAT
switch (pos->type) {
case SamplerType::SAMPLER_2D:
mDescriptorSet.setSampler(layout,
binding, engine.getZeroTexture(), {});
break;
case SamplerType::SAMPLER_2D_ARRAY:
mDescriptorSet.setSampler(layout,
binding, engine.getZeroTextureArray(), {});
break;
case SamplerType::SAMPLER_CUBEMAP:
mDescriptorSet.setSampler(layout,
binding, engine.getDummyCubemap()->getHwHandle(), {});
break;
default:
// we're currently not able to fix-up other sampler types
break;
}
}
}
});

View File

@@ -114,7 +114,8 @@ FMorphTargetBuffer::FMorphTargetBuffer(FEngine& engine, const Builder& builder)
: mVertexCount(builder->mVertexCount),
mCount(builder->mCount) {
if (UTILS_UNLIKELY(engine.getActiveFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0)) {
if (UTILS_UNLIKELY(engine.getSupportedFeatureLevel() <= FeatureLevel::FEATURE_LEVEL_0)) {
// feature level 0 doesn't support morph target buffers
return;
}

View File

@@ -977,7 +977,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
// this descriptor-set is also used for ssr/picking/structure and these could be stale
// it would be better to use a separate desriptor-set for those two cases so that we don't
// have to do this
view.unbindSamplers(driver);
view.unbindSamplers(engine);
view.commitUniformsAndSamplers(driver);
});

View File

@@ -64,7 +64,7 @@ using namespace math;
// this is a hack to be able to create a std::function<> with a non-copyable closure
template<class F>
auto make_copyable_function(F&& f) {
static auto make_copyable_function(F&& f) {
using dF = std::decay_t<F>;
auto spf = std::make_shared<dF>(std::forward<F>(f));
return [spf](auto&& ... args) -> decltype(auto) {
@@ -274,7 +274,9 @@ Texture* Texture::Builder::build(Engine& engine) {
// ------------------------------------------------------------------------------------------------
FTexture::FTexture(FEngine& engine, const Builder& builder) {
FTexture::FTexture(FEngine& engine, const Builder& builder)
: mHasBlitSrc(false),
mExternal(false) {
FEngine::DriverApi& driver = engine.getDriverApi();
mDriver = &driver; // this is unfortunately needed for getHwHandleForSampling()
mWidth = static_cast<uint32_t>(builder->mWidth);
@@ -288,6 +290,7 @@ FTexture::FTexture(FEngine& engine, const Builder& builder) {
mTextureIsSwizzled = builder->mTextureIsSwizzled;
mHasBlitSrc = builder->mHasBlitSrc;
mExternal = builder->mExternal;
mTextureType = backend::getTextureType(mFormat);
bool const isImported = builder->mImportedId != 0;
if (mExternal && !isImported) {
@@ -716,6 +719,10 @@ size_t FTexture::getFormatSize(InternalFormat const format) noexcept {
return backend::getFormatSize(format);
}
TextureType FTexture::getTextureType() const noexcept {
return mTextureType;
}
void FTexture::generatePrefilterMipmap(FEngine& engine,
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,

View File

@@ -27,6 +27,9 @@
#include <utils/compiler.h>
#include <array>
#include <cmath>
#include <stddef.h>
#include <stdint.h>
@@ -105,18 +108,20 @@ public:
// Size a of a pixel in bytes for the given format
static size_t getFormatSize(InternalFormat format) noexcept;
backend::TextureType getTextureType() const noexcept;
// Returns the with or height for a given mipmap level from the base value.
static inline size_t valueForLevel(uint8_t const level, size_t const baseLevelValue) {
static size_t valueForLevel(uint8_t const level, size_t const baseLevelValue) {
return std::max(size_t(1), baseLevelValue >> level);
}
// Returns the max number of levels for a texture of given max dimensions
static inline uint8_t maxLevelCount(uint32_t const maxDimension) noexcept {
static uint8_t maxLevelCount(uint32_t const maxDimension) noexcept {
return std::max(1, std::ilogbf(float(maxDimension)) + 1);
}
// Returns the max number of levels for a texture of given dimensions
static inline uint8_t maxLevelCount(uint32_t const width, uint32_t const height) noexcept {
static uint8_t maxLevelCount(uint32_t const width, uint32_t const height) noexcept {
uint32_t const maxDimension = std::max(width, height);
return maxLevelCount(maxDimension);
}
@@ -132,7 +137,7 @@ public:
void updateLodRange(uint8_t level) noexcept;
// TODO: remove in a future filament release. See below for description.
inline bool hasBlitSrcUsage() const noexcept {
bool hasBlitSrcUsage() const noexcept {
return mHasBlitSrc;
}
@@ -166,23 +171,25 @@ private:
uint32_t mWidth = 1;
uint32_t mHeight = 1;
uint32_t mDepth = 1;
InternalFormat mFormat = InternalFormat::RGBA8;
Sampler mTarget = Sampler::SAMPLER_2D;
uint8_t mLevelCount = 1;
uint8_t mSampleCount = 1;
std::array<Swizzle, 4> mSwizzle = {
Swizzle::CHANNEL_0, Swizzle::CHANNEL_1,
Swizzle::CHANNEL_2, Swizzle::CHANNEL_3 };
bool mTextureIsSwizzled;
Usage mUsage = Usage::DEFAULT;
backend::TextureType mTextureType;
// TODO: remove in a future filament release.
// Indicates whether the user has set the TextureUsage::BLIT_SRC usage. This will be used to
// temporarily validate whether this texture can be used for readPixels.
bool mHasBlitSrc = false;
bool mExternal = false;
// there is 4 bytes of padding here
bool mHasBlitSrc : 1;
bool mExternal : 1;
bool mTextureIsSwizzled : 1;
FStream* mStream = nullptr; // only needed for streaming textures
};

View File

@@ -68,10 +68,36 @@ FView::FView(FEngine& engine)
mFogEntity(engine.getEntityManager().create()),
mIsStereoSupported(engine.getDriverApi().isStereoSupported()),
mUniforms(engine.getDriverApi()),
mColorPassDescriptorSet(engine, mUniforms) {
mColorPassDescriptorSet{
{ engine, false, mUniforms },
{ engine, true, mUniforms } }
{
DriverApi& driver = engine.getDriverApi();
auto const& layout = engine.getPerRenderableDescriptorSetLayout();
// initialize the common descriptor set with dummy descriptors
mCommonRenderableDescriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::BONES_UNIFORMS,
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableBoneUib));
mCommonRenderableDescriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableMorphingUib));
mCommonRenderableDescriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
engine.getDummyMorphTargetBuffer()->getPositionsHandle(), {});
mCommonRenderableDescriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
engine.getDummyMorphTargetBuffer()->getTangentsHandle(), {});
mCommonRenderableDescriptorSet.setSampler(layout,
+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
engine.getZeroTextureArray(), {});
FDebugRegistry& debugRegistry = engine.getDebugRegistry();
debugRegistry.registerProperty("d.view.camera_at_origin",
@@ -125,11 +151,13 @@ FView::FView(FEngine& engine)
mDefaultColorGrading = mColorGrading = engine.getDefaultColorGrading();
mColorPassDescriptorSet.init(
engine,
mLightUbh,
mFroxelizer.getRecordBuffer(),
mFroxelizer.getFroxelBuffer());
for (auto&& colorPassDescriptorSet : mColorPassDescriptorSet) {
colorPassDescriptorSet.init(
engine,
mLightUbh,
mFroxelizer.getRecordBuffer(),
mFroxelizer.getFroxelBuffer());
}
}
FView::~FView() noexcept = default;
@@ -146,7 +174,9 @@ void FView::terminate(FEngine& engine) {
ShadowMapManager::terminate(engine, mShadowMapManager);
mUniforms.terminate(driver);
mColorPassDescriptorSet.terminate(engine.getDescriptorSetLayoutFactory(), driver);
for (auto&& colorPassDescriptorSet : mColorPassDescriptorSet) {
colorPassDescriptorSet.terminate(engine.getDescriptorSetLayoutFactory(), driver);
}
mFroxelizer.terminate(driver);
mCommonRenderableDescriptorSet.terminate(driver);
@@ -429,7 +459,7 @@ void FView::prepareLighting(FEngine& engine, CameraInfo const& cameraInfo) noexc
*/
const float exposure = Exposure::exposure(cameraInfo.ev100);
mColorPassDescriptorSet.prepareExposure(cameraInfo.ev100);
getColorPassDescriptorSet().prepareExposure(cameraInfo.ev100);
/*
* Indirect light (IBL)
@@ -446,7 +476,7 @@ void FView::prepareLighting(FEngine& engine, CameraInfo const& cameraInfo) noexc
FSkybox const* const skybox = scene->getSkybox();
intensity = skybox ? skybox->getIntensity() : FIndirectLight::DEFAULT_INTENSITY;
}
mColorPassDescriptorSet.prepareAmbientLight(engine, *ibl, intensity, exposure);
getColorPassDescriptorSet().prepareAmbientLight(engine, *ibl, intensity, exposure);
/*
* Directional light (always at index 0)
@@ -454,7 +484,7 @@ void FView::prepareLighting(FEngine& engine, CameraInfo const& cameraInfo) noexc
FLightManager::Instance const directionalLight = lightData.elementAt<FScene::LIGHT_INSTANCE>(0);
const float3 sceneSpaceDirection = lightData.elementAt<FScene::DIRECTION>(0); // guaranteed normalized
mColorPassDescriptorSet.prepareDirectionalLight(engine, exposure, sceneSpaceDirection, directionalLight);
getColorPassDescriptorSet().prepareDirectionalLight(engine, exposure, sceneSpaceDirection, directionalLight);
}
CameraInfo FView::computeCameraInfo(FEngine& engine) const noexcept {
@@ -606,7 +636,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
cameraInfo.projection, cameraInfo.zn, cameraInfo.zf)) {
// TODO: might be more consistent to do this in prepareLighting(), but it's not
// strictly necessary
mColorPassDescriptorSet.prepareDynamicLights(mFroxelizer);
getColorPassDescriptorSet().prepareDynamicLights(mFroxelizer);
}
// We need to pass viewMatrix by value here because it extends the scope of this
// function.
@@ -711,6 +741,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
scene->updateUBOs(merged, mRenderableUbh);
mCommonRenderableDescriptorSet.setBuffer(
engine.getPerRenderableDescriptorSetLayout(),
+PerRenderableBindingPoints::OBJECT_UNIFORMS, mRenderableUbh,
0, sizeof(PerRenderableUib));
@@ -734,37 +765,65 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
FRenderableManager& rcm = engine.getRenderableManager();
auto& descriptorSet = rcm.getDescriptorSet(ci);
auto const& layout = engine.getPerRenderableDescriptorSetLayout();
// initialize the descriptor set the first time it's needed
if (UTILS_UNLIKELY(!descriptorSet.getHandle())) {
descriptorSet = DescriptorSet{ engine.getPerRenderableDescriptorSetLayout() };
descriptorSet = DescriptorSet{ layout };
}
descriptorSet.setBuffer(+PerRenderableBindingPoints::OBJECT_UNIFORMS,
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::OBJECT_UNIFORMS,
instance.handle ? instance.handle : mRenderableUbh,
0, sizeof(PerRenderableUib));
if (UTILS_UNLIKELY(skinning.handle || morphing.handle)) {
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::BONES_UNIFORMS,
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableBoneUib));
descriptorSet.setBuffer(+PerRenderableBindingPoints::BONES_UNIFORMS,
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
engine.getDummyUniformBuffer(), 0, sizeof(PerRenderableMorphingUib));
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
engine.getDummyMorphTargetBuffer()->getPositionsHandle(), {});
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
engine.getDummyMorphTargetBuffer()->getTangentsHandle(), {});
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
engine.getZeroTextureArray(), {});
if (UTILS_UNLIKELY(skinning.handle || morphing.handle)) {
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::BONES_UNIFORMS,
skinning.handle, 0, sizeof(PerRenderableBoneUib));
descriptorSet.setSampler(+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS,
skinning.boneIndicesAndWeightHandle, {});
descriptorSet.setBuffer(+PerRenderableBindingPoints::MORPHING_UNIFORMS,
descriptorSet.setBuffer(layout,
+PerRenderableBindingPoints::MORPHING_UNIFORMS,
morphing.handle, 0, sizeof(PerRenderableMorphingUib));
descriptorSet.setSampler(+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_POSITIONS,
morphing.morphTargetBuffer->getPositionsHandle(), {});
descriptorSet.setSampler(+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
descriptorSet.setSampler(layout,
+PerRenderableBindingPoints::MORPH_TARGET_TANGENTS,
morphing.morphTargetBuffer->getTangentsHandle(), {});
}
descriptorSet.commit(engine.getPerRenderableDescriptorSetLayout(), driver);
descriptorSet.commit(layout, driver);
// write the descriptor-set handle to the sceneData array for access later
sceneData.elementAt<FScene::DESCRIPTOR_SET_HANDLE>(i) = descriptorSet.getHandle();
sceneData.elementAt<FScene::DESCRIPTOR_SET_HANDLE>(i) =
descriptorSet.getHandle();
} else {
// use the shared descriptor-set
sceneData.elementAt<FScene::DESCRIPTOR_SET_HANDLE>(i) =
@@ -788,12 +847,13 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren
auto const& tcm = engine.getTransformManager();
auto const fogTransform = tcm.getWorldTransformAccurate(tcm.getInstance(mFogEntity));
mColorPassDescriptorSet.prepareTime(engine, userTime);
mColorPassDescriptorSet.prepareFog(engine, cameraInfo, fogTransform, mFogOptions,
auto& colorPassDescriptorSet = getColorPassDescriptorSet();
colorPassDescriptorSet.prepareTime(engine, userTime);
colorPassDescriptorSet.prepareFog(engine, cameraInfo, fogTransform, mFogOptions,
scene->getIndirectLight());
mColorPassDescriptorSet.prepareTemporalNoise(engine, mTemporalAntiAliasingOptions);
mColorPassDescriptorSet.prepareBlending(needsAlphaChannel);
mColorPassDescriptorSet.prepareMaterialGlobals(mMaterialGlobals);
colorPassDescriptorSet.prepareTemporalNoise(engine, mTemporalAntiAliasingOptions);
colorPassDescriptorSet.prepareBlending(needsAlphaChannel);
colorPassDescriptorSet.prepareMaterialGlobals(mMaterialGlobals);
}
void FView::computeVisibilityMasks(
@@ -854,12 +914,12 @@ void FView::prepareUpscaler(float2 const scale,
derivativesScale = 0.5f;
}
}
mColorPassDescriptorSet.prepareLodBias(bias, derivativesScale);
getColorPassDescriptorSet().prepareLodBias(bias, derivativesScale);
}
void FView::prepareCamera(FEngine& engine, const CameraInfo& cameraInfo) const noexcept {
SYSTRACE_CALL();
mColorPassDescriptorSet.prepareCamera(engine, cameraInfo);
getColorPassDescriptorSet().prepareCamera(engine, cameraInfo);
}
void FView::prepareViewport(
@@ -868,23 +928,23 @@ void FView::prepareViewport(
SYSTRACE_CALL();
// TODO: we should pass viewport.{left|bottom} to the backend, so it can offset the
// scissor properly.
mColorPassDescriptorSet.prepareViewport(physicalViewport, logicalViewport);
getColorPassDescriptorSet().prepareViewport(physicalViewport, logicalViewport);
}
void FView::prepareSSAO(Handle<HwTexture> ssao) const noexcept {
mColorPassDescriptorSet.prepareSSAO(ssao, mAmbientOcclusionOptions);
getColorPassDescriptorSet().prepareSSAO(ssao, mAmbientOcclusionOptions);
}
void FView::prepareSSR(Handle<HwTexture> ssr,
bool const disableSSR,
float const refractionLodOffset,
ScreenSpaceReflectionsOptions const& ssrOptions) const noexcept {
mColorPassDescriptorSet.prepareSSR(ssr, disableSSR, refractionLodOffset, ssrOptions);
getColorPassDescriptorSet().prepareSSR(ssr, disableSSR, refractionLodOffset, ssrOptions);
}
void FView::prepareStructure(Handle<HwTexture> structure) const noexcept {
// sampler must be NEAREST
mColorPassDescriptorSet.prepareStructure(structure);
getColorPassDescriptorSet().prepareStructure(structure);
}
void FView::prepareShadow(Handle<HwTexture> texture) const noexcept {
@@ -896,37 +956,38 @@ void FView::prepareShadow(Handle<HwTexture> texture) const noexcept {
}
switch (mShadowType) {
case ShadowType::PCF:
mColorPassDescriptorSet.prepareShadowPCF(texture, uniforms);
getColorPassDescriptorSet().prepareShadowPCF(texture, uniforms);
break;
case ShadowType::VSM:
mColorPassDescriptorSet.prepareShadowVSM(texture, uniforms, mVsmShadowOptions);
getColorPassDescriptorSet().prepareShadowVSM(texture, uniforms, mVsmShadowOptions);
break;
case ShadowType::DPCF:
mColorPassDescriptorSet.prepareShadowDPCF(texture, uniforms, mSoftShadowOptions);
getColorPassDescriptorSet().prepareShadowDPCF(texture, uniforms, mSoftShadowOptions);
break;
case ShadowType::PCSS:
mColorPassDescriptorSet.prepareShadowPCSS(texture, uniforms, mSoftShadowOptions);
getColorPassDescriptorSet().prepareShadowPCSS(texture, uniforms, mSoftShadowOptions);
break;
case ShadowType::PCFd:
mColorPassDescriptorSet.prepareShadowPCFDebug(texture, uniforms);
getColorPassDescriptorSet().prepareShadowPCFDebug(texture, uniforms);
break;
}
}
void FView::prepareShadowMapping(bool const highPrecision) const noexcept {
void FView::prepareShadowMapping(FEngine const& engine, bool const highPrecision) const noexcept {
BufferObjectHandle ubo{ engine.getDummyUniformBuffer() };
if (mHasShadowing) {
assert_invariant(mShadowMapManager);
mColorPassDescriptorSet.prepareShadowMapping(
mShadowMapManager->getShadowUniformsHandle(), highPrecision);
ubo = mShadowMapManager->getShadowUniformsHandle();
}
getColorPassDescriptorSet().prepareShadowMapping(ubo, highPrecision);
}
void FView::commitUniformsAndSamplers(DriverApi& driver) const noexcept {
mColorPassDescriptorSet.commit(driver);
getColorPassDescriptorSet().commit(driver);
}
void FView::unbindSamplers(DriverApi& driver) noexcept {
mColorPassDescriptorSet.unbindSamplers(driver);
void FView::unbindSamplers(FEngine& engine) noexcept {
getColorPassDescriptorSet().unbindSamplers(engine);
}
void FView::commitFroxels(DriverApi& driverApi) const noexcept {

View File

@@ -178,11 +178,11 @@ public:
ScreenSpaceReflectionsOptions const& ssrOptions) const noexcept;
void prepareStructure(backend::Handle<backend::HwTexture> structure) const noexcept;
void prepareShadow(backend::Handle<backend::HwTexture> structure) const noexcept;
void prepareShadowMapping(bool highPrecision) const noexcept;
void prepareShadowMapping(FEngine const& engine, bool highPrecision) const noexcept;
void commitFroxels(backend::DriverApi& driverApi) const noexcept;
void commitUniformsAndSamplers(backend::DriverApi& driver) const noexcept;
void unbindSamplers(backend::DriverApi& driver) noexcept;
void unbindSamplers(FEngine& engine) noexcept;
utils::JobSystem::Job* getFroxelizerSync() const noexcept { return mFroxelizerSync; }
void setFroxelizerSync(utils::JobSystem::Job* sync) noexcept { mFroxelizerSync = sync; }
@@ -440,7 +440,9 @@ public:
static void cullRenderables(utils::JobSystem& js, FScene::RenderableSoa& renderableData,
Frustum const& frustum, size_t bit) noexcept;
ColorPassDescriptorSet& getColorPassDescriptorSet() noexcept { return mColorPassDescriptorSet; }
ColorPassDescriptorSet& getColorPassDescriptorSet() const noexcept {
return mColorPassDescriptorSet[mShadowType == ShadowType::PCF ? 0 : 1];
}
// Returns the frame history FIFO. This is typically used by the FrameGraph to access
// previous frame data.
@@ -587,7 +589,7 @@ private:
RenderQuality mRenderQuality;
mutable TypedUniformBuffer<PerViewUib> mUniforms;
mutable ColorPassDescriptorSet mColorPassDescriptorSet;
mutable ColorPassDescriptorSet mColorPassDescriptorSet[2];
mutable FrameHistory mFrameHistory{};

View File

@@ -79,7 +79,7 @@ uint8_t ColorPassDescriptorSet::getIndex(
index |= 0x2;
}
if (!fog) {
if (fog) {
// this will remove samplers needed for fog
index |= 0x4;
}
@@ -88,27 +88,18 @@ uint8_t ColorPassDescriptorSet::getIndex(
return index;
}
ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine,
ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine, bool const vsm,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept
: mUniforms(uniforms) {
constexpr UserVariantFilterMask filterFog = UserVariantFilterMask(UserVariantFilterBit::FOG);
constexpr UserVariantFilterMask keepFog = UserVariantFilterMask(0);
: mUniforms(uniforms), mIsVsm(vsm) {
for (bool const lit: { false, true }) {
for (bool const ssr: { false, true }) {
for (bool const fog: { false, true }) {
auto index = getIndex(lit, ssr, fog);
auto const index = getIndex(lit, ssr, fog);
mDescriptorSetLayout[index] = {
engine.getDescriptorSetLayoutFactory(),
engine.getDriverApi(),
descriptor_sets::getPerViewDescriptorSetLayout(
MaterialDomain::SURFACE,
fog ? keepFog : filterFog,
lit,
ssr ? ReflectionMode::SCREEN_SPACE : ReflectionMode::DEFAULT,
ssr ? RefractionMode::SCREEN_SPACE : RefractionMode::NONE)
MaterialDomain::SURFACE, lit, ssr, fog, vsm)
};
mDescriptorSet[index] = DescriptorSet{ mDescriptorSetLayout[index] };
}
@@ -118,11 +109,11 @@ ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine,
setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
uniforms.getUboHandle(), 0, uniforms.getSize());
if (engine.getDFG().isValid()) {
TextureSampler const sampler(TextureSampler::MagFilter::LINEAR);
setSampler(+PerViewBindingPoints::IBL_DFG_LUT,
engine.getDFG().getTexture(), sampler.getSamplerParams());
}
setSampler(+PerViewBindingPoints::IBL_DFG_LUT,
engine.getDFG().isValid() ?
engine.getDFG().getTexture() : engine.getZeroTexture(), {
.filterMag = SamplerMagFilter::LINEAR
});
}
void ColorPassDescriptorSet::init(
@@ -130,12 +121,14 @@ void ColorPassDescriptorSet::init(
BufferObjectHandle lights,
BufferObjectHandle recordBuffer,
BufferObjectHandle froxelBuffer) noexcept {
for (auto&& descriptorSet: mDescriptorSet) {
descriptorSet.setBuffer(+PerViewBindingPoints::LIGHTS,
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
auto& descriptorSet = mDescriptorSet[i];
auto const& layout = mDescriptorSetLayout[i];
descriptorSet.setBuffer(layout, +PerViewBindingPoints::LIGHTS,
lights, 0, CONFIG_MAX_LIGHT_COUNT * sizeof(LightsUib));
descriptorSet.setBuffer(+PerViewBindingPoints::RECORD_BUFFER,
descriptorSet.setBuffer(layout, +PerViewBindingPoints::RECORD_BUFFER,
recordBuffer, 0, sizeof(FroxelRecordUib));
descriptorSet.setBuffer(+PerViewBindingPoints::FROXEL_BUFFER,
descriptorSet.setBuffer(layout, +PerViewBindingPoints::FROXEL_BUFFER,
froxelBuffer, 0, Froxelizer::getFroxelBufferByteCount(engine.getDriverApi()));
}
}
@@ -305,6 +298,7 @@ void ColorPassDescriptorSet::prepareFog(FEngine& engine, const CameraInfo& camer
void ColorPassDescriptorSet::prepareSSAO(Handle<HwTexture> ssao,
AmbientOcclusionOptions const& options) noexcept {
// High quality sampling is enabled only if AO itself is enabled and upsampling quality is at
// least set to high and of course only if upsampling is needed.
const bool highQualitySampling = options.upsampling >= QualityLevel::HIGH
@@ -537,20 +531,28 @@ void ColorPassDescriptorSet::commit(DriverApi& driver) noexcept {
driver.updateBufferObject(mUniforms.getUboHandle(),
mUniforms.toBufferDescriptor(driver), 0);
}
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
mDescriptorSet[i].commit(mDescriptorSetLayout[i], driver);
}
}
void ColorPassDescriptorSet::unbindSamplers(DriverApi&) noexcept {
void ColorPassDescriptorSet::unbindSamplers(FEngine& engine) noexcept {
// this needs to reset the sampler that are only set in RendererUtils::colorPass(), because
// this descriptor-set is also used for ssr/picking/structure and these could be stale
// it would be better to use a separate descriptor-set for those two cases so that we don't
// have to do this
setSampler(+PerViewBindingPoints::STRUCTURE, {}, {});
setSampler(+PerViewBindingPoints::SHADOW_MAP, {}, {});
setSampler(+PerViewBindingPoints::SSAO, {}, {});
setSampler(+PerViewBindingPoints::SSR, {}, {});
setBuffer(+PerViewBindingPoints::SHADOWS,
engine.getDummyUniformBuffer(), 0, sizeof(ShadowUib));
setSampler(+PerViewBindingPoints::STRUCTURE,
engine.getZeroTexture(), {});
setSampler(+PerViewBindingPoints::SHADOW_MAP,
engine.getOneTextureArrayDepth(), {});
setSampler(+PerViewBindingPoints::SSAO,
engine.getZeroTextureArray(), {});
setSampler(+PerViewBindingPoints::SSR,
engine.getZeroTextureArray(), {});
}
void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding,
@@ -558,7 +560,7 @@ void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding,
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
auto samplers = mDescriptorSetLayout[i].getSamplerDescriptors();
if (samplers[binding]) {
mDescriptorSet[i].setSampler(binding, th, params);
mDescriptorSet[i].setSampler(mDescriptorSetLayout[i], binding, th, params);
}
}
}
@@ -566,9 +568,10 @@ void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding,
void ColorPassDescriptorSet::setBuffer(descriptor_binding_t const binding,
BufferObjectHandle boh, uint32_t const offset, uint32_t const size) noexcept {
for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) {
auto ubos = mDescriptorSetLayout[i].getUniformBufferDescriptors();
auto const& layout = mDescriptorSetLayout[i];
auto ubos = layout.getUniformBufferDescriptors();
if (ubos[binding]) {
mDescriptorSet[i].setBuffer(binding, boh, offset, size);
mDescriptorSet[i].setBuffer(layout, binding, boh, offset, size);
}
}
}

View File

@@ -66,16 +66,16 @@ class ColorPassDescriptorSet {
using LightManagerInstance = utils::EntityInstance<LightManager>;
using TextureHandle = backend::Handle<backend::HwTexture>;
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_PCF = 0u;
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_EVSM = 1u;
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_DPCF = 2u;
static constexpr uint32_t const SHADOW_SAMPLING_RUNTIME_PCSS = 3u;
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_PCF = 0u;
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_EVSM = 1u;
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_DPCF = 2u;
static constexpr uint32_t SHADOW_SAMPLING_RUNTIME_PCSS = 3u;
public:
static uint8_t getIndex(bool lit, bool ssr, bool fog) noexcept;
ColorPassDescriptorSet(FEngine& engine,
ColorPassDescriptorSet(FEngine& engine, bool vsm,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
void init(
@@ -153,13 +153,15 @@ public:
// update local data into GPU UBO
void commit(backend::DriverApi& driver) noexcept;
void unbindSamplers(backend::DriverApi& driver) noexcept;
void unbindSamplers(FEngine& engine) noexcept;
// bind this UBO
void bind(backend::DriverApi& driver, uint8_t const index) const noexcept {
mDescriptorSet[index].bind(driver, DescriptorSetBindingPoints::PER_VIEW);
}
bool isVSM() const noexcept { return mIsVsm; }
private:
static constexpr size_t DESCRIPTOR_LAYOUT_COUNT = 8;
@@ -169,11 +171,13 @@ private:
void setBuffer(backend::descriptor_binding_t binding,
backend::BufferObjectHandle boh, uint32_t offset, uint32_t size) noexcept;
static void prepareShadowSampling(PerViewUib& uniforms,
ShadowMappingUniforms const& shadowMappingUniforms) noexcept;
TypedUniformBuffer<PerViewUib>& mUniforms;
std::array<DescriptorSetLayout, DESCRIPTOR_LAYOUT_COUNT> mDescriptorSetLayout;
std::array<DescriptorSet, DESCRIPTOR_LAYOUT_COUNT> mDescriptorSet;
static void prepareShadowSampling(PerViewUib& uniforms,
ShadowMappingUniforms const& shadowMappingUniforms) noexcept;
bool const mIsVsm;
};
} // namespace filament

View File

@@ -28,6 +28,7 @@
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Log.h>
#include <utils/Panic.h>
#include <utility>
#include <limits>
@@ -86,6 +87,7 @@ void DescriptorSet::commitSlow(DescriptorSetLayout const& layout,
mValid.forEachSetBit([&layout, &driver,
dsh = mDescriptorSetHandle, descriptors = mDescriptors.data()]
(backend::descriptor_binding_t const binding) {
assert_invariant(layout.isValid(binding));
if (layout.isSampler(binding)) {
driver.updateDescriptorSetTexture(dsh, binding,
descriptors[binding].texture.th,
@@ -113,7 +115,7 @@ void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints
// within the renderpass. We have to comment the assert out since it crashed a client's debug
// build.
// assert_invariant(mDirty.none());
if (mDirty.any() && !mSetAfterCommitWarning) {
if (UTILS_VERY_UNLIKELY(mDirty.any() && !mSetAfterCommitWarning)) {
mDirty.forEachSetBit([&](uint8_t const binding) {
utils::slog.w << "Descriptor set (handle=" << mDescriptorSetHandle.getId()
<< ") binding=" << (int) binding
@@ -124,35 +126,109 @@ void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints
driver.bindDescriptorSet(mDescriptorSetHandle, +set, std::move(dynamicOffsets));
}
void DescriptorSet::setBuffer(
void DescriptorSet::setBuffer(DescriptorSetLayout const& layout,
backend::descriptor_binding_t const binding,
backend::Handle<backend::HwBufferObject> boh, uint32_t const offset, uint32_t const size) noexcept {
// TODO: validate it's the right kind of descriptor
backend::Handle<backend::HwBufferObject> boh, uint32_t const offset, uint32_t const size) {
// Validate it's the right kind of descriptor
using DSLB = backend::DescriptorSetLayoutBinding;
FILAMENT_CHECK_PRECONDITION(DSLB::isBuffer(layout.getDescriptorType(binding)))
<< "descriptor " << +binding << "is not a buffer";
if (mDescriptors[binding].buffer.boh != boh || mDescriptors[binding].buffer.size != size) {
// we don't set the dirty bit if only offset changes
mDirty.set(binding);
}
mDescriptors[binding].buffer = { boh, offset, size };
mValid.set(binding, (bool)boh);
mValid.set(binding, bool(boh));
}
void DescriptorSet::setSampler(
DescriptorSetLayout const& layout,
backend::descriptor_binding_t const binding,
backend::Handle<backend::HwTexture> th, backend::SamplerParams const params) noexcept {
// TODO: validate it's the right kind of descriptor
backend::Handle<backend::HwTexture> th, backend::SamplerParams const params) {
using namespace backend;
using DSLB = DescriptorSetLayoutBinding;
// Validate it's the right kind of descriptor
auto type = layout.getDescriptorType(binding);
FILAMENT_CHECK_PRECONDITION(DSLB::isSampler(type))
<< "descriptor " << +binding << " is not a sampler";
FILAMENT_CHECK_PRECONDITION(
!(params.compareMode == SamplerCompareMode::COMPARE_TO_TEXTURE && !isDepthDescriptor(type)))
<< "descriptor " << +binding
<< " is not of type DEPTH, but sampler is in COMPARE_TO_TEXTURE mode";
FILAMENT_CHECK_PRECONDITION(
!(params.isFiltered() &&
isDepthDescriptor(type) &&
params.compareMode != SamplerCompareMode::COMPARE_TO_TEXTURE))
<< "descriptor " << +binding
<< " is of type filtered DEPTH, but sampler not in COMPARE_TO_TEXTURE mode";
if (mDescriptors[binding].texture.th != th || mDescriptors[binding].texture.params != params) {
mDirty.set(binding);
}
mDescriptors[binding].texture = { th, params };
mValid.set(binding, (bool)th);
mValid.set(binding, bool(th));
}
DescriptorSet DescriptorSet::duplicate(DescriptorSetLayout const& layout) const noexcept {
DescriptorSet set{layout};
set.mDescriptors = mDescriptors; // Use the vector's assignment operator
set.mDirty = mDirty;
set.mDirty = mValid | mDirty; // Dirty all valid descriptors so they're updated during commit
set.mValid = mValid;
return set;
}
bool DescriptorSet::isTextureCompatibleWithDescriptor(
backend::TextureType t, backend::DescriptorType d) noexcept {
using namespace backend;
switch (d) {
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_3D_FLOAT:
// DEPTH_STENCIL is treated as accessing the depth component. OpenGL 4.3
// allows to specify which one, but not filament.
// Depth textures can be used as an unfiltered float sampler
return t == TextureType::FLOAT || t == TextureType::DEPTH || t == TextureType::DEPTH_STENCIL;
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_3D_INT:
return t == TextureType::INT;
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_3D_UINT:
return t == TextureType::UINT;
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
// DEPTH_STENCIL is treated as accessing the depth component. OpenGL 4.3
// allows to specify which one, but not filament.
return t == TextureType::DEPTH || t == TextureType::DEPTH_STENCIL;
case DescriptorType::SAMPLER_EXTERNAL:
case DescriptorType::UNIFORM_BUFFER:
case DescriptorType::SHADER_STORAGE_BUFFER:
case DescriptorType::INPUT_ATTACHMENT:
return false;
}
// should never happen
return false;
}
} // namespace filament

View File

@@ -62,14 +62,16 @@ public:
backend::DescriptorSetOffsetArray dynamicOffsets) const noexcept;
// sets a ubo/ssbo descriptor
void setBuffer(backend::descriptor_binding_t binding,
void setBuffer(DescriptorSetLayout const& layout,
backend::descriptor_binding_t binding,
backend::Handle<backend::HwBufferObject> boh,
uint32_t offset, uint32_t size) noexcept;
uint32_t offset, uint32_t size);
// sets a sampler descriptor
void setSampler(backend::descriptor_binding_t binding,
void setSampler(DescriptorSetLayout const& layout,
backend::descriptor_binding_t binding,
backend::Handle<backend::HwTexture> th,
backend::SamplerParams params) noexcept;
backend::SamplerParams params);
// Used for duplicating material
DescriptorSet duplicate(DescriptorSetLayout const& layout) const noexcept;
@@ -82,6 +84,9 @@ public:
return mValid;
}
static bool isTextureCompatibleWithDescriptor(
backend::TextureType t, backend::DescriptorType d) noexcept;
private:
struct Desc {
Desc() noexcept { }

View File

@@ -20,6 +20,9 @@
#include "details/Engine.h"
#include <utils/debug.h>
#include <utils/FixedCapacityVector.h>
#include <backend/DriverEnums.h>
#include <algorithm>
@@ -35,11 +38,15 @@ DescriptorSetLayout::DescriptorSetLayout(
backend::DescriptorSetLayout descriptorSetLayout) noexcept {
for (auto&& desc : descriptorSetLayout.bindings) {
mMaxDescriptorBinding = std::max(mMaxDescriptorBinding, desc.binding);
mSamplers.set(desc.binding,
desc.type == backend::DescriptorType::SAMPLER ||
desc.type == backend::DescriptorType::SAMPLER_EXTERNAL);
mUniformBuffers.set(desc.binding,
desc.type == backend::DescriptorType::UNIFORM_BUFFER);
mSamplers.set(desc.binding, backend::DescriptorSetLayoutBinding::isSampler(desc.type));
mUniformBuffers.set(desc.binding, desc.type == backend::DescriptorType::UNIFORM_BUFFER);
}
assert_invariant(mMaxDescriptorBinding < utils::bitset64::BIT_COUNT);
mDescriptorTypes = utils::FixedCapacityVector<backend::DescriptorType>(mMaxDescriptorBinding + 1);
for (auto&& desc : descriptorSetLayout.bindings) {
mDescriptorTypes[desc.binding] = desc.type;
}
mDescriptorSetLayoutHandle = factory.create(driver,

View File

@@ -23,6 +23,7 @@
#include <backend/Handle.h>
#include <utils/bitset.h>
#include <utils/FixedCapacityVector.h>
#include <stddef.h>
#include <stdint.h>
@@ -56,6 +57,10 @@ public:
return mMaxDescriptorBinding;
}
bool isValid(backend::descriptor_binding_t const binding) const noexcept {
return mSamplers[binding] || mUniformBuffers[binding];
}
bool isSampler(backend::descriptor_binding_t const binding) const noexcept {
return mSamplers[binding];
}
@@ -68,11 +73,17 @@ public:
return mUniformBuffers;
}
backend::DescriptorType getDescriptorType(
backend::descriptor_binding_t const binding) const noexcept {
return mDescriptorTypes[binding];
}
private:
backend::DescriptorSetLayoutHandle mDescriptorSetLayoutHandle;
utils::bitset64 mSamplers;
utils::bitset64 mUniformBuffers;
uint8_t mMaxDescriptorBinding = 0;
utils::FixedCapacityVector<backend::DescriptorType> mDescriptorTypes;
};

View File

@@ -53,7 +53,8 @@ void PostProcessDescriptorSet::terminate(HwDescriptorSetLayoutFactory& factory,
void PostProcessDescriptorSet::setFrameUniforms(DriverApi& driver,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
// initialize the descriptor-set
mDescriptorSet.setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
mDescriptorSet.setBuffer(mDescriptorSetLayout,
+PerViewBindingPoints::FRAME_UNIFORMS,
uniforms.getUboHandle(), 0, uniforms.getSize());
mDescriptorSet.commit(mDescriptorSetLayout, driver);

View File

@@ -46,8 +46,8 @@ ShadowMapDescriptorSet::ShadowMapDescriptorSet(FEngine& engine) noexcept {
mDescriptorSet = DescriptorSet{ engine.getPerViewDescriptorSetLayoutDepthVariant() };
// initialize the descriptor-set
mDescriptorSet.setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
mUniformBufferHandle, 0, sizeof(PerViewUib));
mDescriptorSet.setBuffer(engine.getPerViewDescriptorSetLayoutDepthVariant(),
+PerViewBindingPoints::FRAME_UNIFORMS, mUniformBufferHandle, 0, sizeof(PerViewUib));
}
void ShadowMapDescriptorSet::terminate(DriverApi& driver) {

View File

@@ -53,28 +53,32 @@ void SsrPassDescriptorSet::terminate(DriverApi& driver) {
driver.destroyBufferObject(mShadowUbh);
}
void SsrPassDescriptorSet::setFrameUniforms(TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
void SsrPassDescriptorSet::setFrameUniforms(FEngine const& engine,
TypedUniformBuffer<PerViewUib>& uniforms) noexcept {
// initialize the descriptor-set
mDescriptorSet.setBuffer(+PerViewBindingPoints::FRAME_UNIFORMS,
mDescriptorSet.setBuffer(engine.getPerViewDescriptorSetLayoutSsrVariant(),
+PerViewBindingPoints::FRAME_UNIFORMS,
uniforms.getUboHandle(), 0, uniforms.getSize());
// This is actually not used for the SSR variants, but the descriptor-set layout needs
// to have this UBO because the fragment shader used is the "generic" one. Both Metal
// and GL would be okay without this, but Vulkan's validation layer would complain.
mDescriptorSet.setBuffer(+PerViewBindingPoints::SHADOWS, mShadowUbh, 0, sizeof(ShadowUib));
mDescriptorSet.setBuffer(engine.getPerViewDescriptorSetLayoutSsrVariant(),
+PerViewBindingPoints::SHADOWS, mShadowUbh, 0, sizeof(ShadowUib));
mUniforms = std::addressof(uniforms);
}
void SsrPassDescriptorSet::prepareHistorySSR(Handle<HwTexture> ssr,
void SsrPassDescriptorSet::prepareHistorySSR(FEngine const& engine, Handle<HwTexture> ssr,
mat4f const& historyProjection,
mat4f const& uvFromViewMatrix,
ScreenSpaceReflectionsOptions const& ssrOptions) noexcept {
mDescriptorSet.setSampler(+PerViewBindingPoints::SSR, ssr, {
.filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR
});
mDescriptorSet.setSampler(engine.getPerViewDescriptorSetLayoutSsrVariant(),
+PerViewBindingPoints::SSR, ssr, {
.filterMag = SamplerMagFilter::LINEAR,
.filterMin = SamplerMinFilter::LINEAR
});
assert_invariant(mUniforms);
auto& s = mUniforms->edit();
@@ -86,9 +90,11 @@ void SsrPassDescriptorSet::prepareHistorySSR(Handle<HwTexture> ssr,
s.ssrStride = ssrOptions.stride;
}
void SsrPassDescriptorSet::prepareStructure(Handle<HwTexture> structure) noexcept {
void SsrPassDescriptorSet::prepareStructure(FEngine const& engine,
Handle<HwTexture> structure) noexcept {
// sampler must be NEAREST
mDescriptorSet.setSampler(+PerViewBindingPoints::STRUCTURE, structure, {});
mDescriptorSet.setSampler(engine.getPerViewDescriptorSetLayoutSsrVariant(),
+PerViewBindingPoints::STRUCTURE, structure, {});
}
void SsrPassDescriptorSet::commit(FEngine& engine) noexcept {

View File

@@ -47,11 +47,11 @@ public:
void terminate(backend::DriverApi& driver);
void setFrameUniforms(TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
void setFrameUniforms(FEngine const& engine, TypedUniformBuffer<PerViewUib>& uniforms) noexcept;
void prepareStructure(TextureHandle structure) noexcept;
void prepareStructure(FEngine const& engine, TextureHandle structure) noexcept;
void prepareHistorySSR(TextureHandle ssr,
void prepareHistorySSR(FEngine const& engine, TextureHandle ssr,
math::mat4f const& historyProjection,
math::mat4f const& uvFromViewMatrix,
ScreenSpaceReflectionsOptions const& ssrOptions) noexcept;

View File

@@ -35,23 +35,20 @@ backend::DescriptorSetLayout const& getPerRenderableLayout() noexcept;
backend::DescriptorSetLayout getPerViewDescriptorSetLayout(
MaterialDomain domain,
UserVariantFilterMask variantFilter,
bool isLit,
ReflectionMode reflectionMode,
RefractionMode refractionMode) noexcept;
bool isLit, bool isSSR, bool hasFog,
bool isVSM) noexcept;
backend::DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
Variant variant,
MaterialDomain domain,
UserVariantFilterMask variantFilter,
bool isLit,
ReflectionMode reflectionMode,
RefractionMode refractionMode) noexcept;
bool isLit, bool isSSR, bool hasFog) noexcept;
utils::CString getDescriptorName(
DescriptorSetBindingPoints set,
backend::descriptor_binding_t binding) noexcept;
backend::DescriptorType getDescriptorType(backend::SamplerType type, backend::SamplerFormat format);
} // namespace filament::descriptor_sets

View File

@@ -24,21 +24,28 @@
#include <backend/DriverEnums.h>
#include <utils/CString.h>
#include <utils/Panic.h>
#include <utils/StaticString.h>
#include <utils/debug.h>
#include <algorithm>
#include <cstddef>
#include <initializer_list>
#include <string_view>
#include <type_traits>
#include <unordered_map>
#include <utility>
namespace filament::descriptor_sets {
using namespace backend;
// used for post-processing passes
static constexpr std::initializer_list<DescriptorSetLayoutBinding> postProcessDescriptorSetLayoutList = {
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
};
// used to generate shadow-maps
static constexpr std::initializer_list<DescriptorSetLayoutBinding> depthVariantDescriptorSetLayoutList = {
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
};
@@ -51,32 +58,88 @@ static constexpr std::initializer_list<DescriptorSetLayoutBinding> depthVariantD
static constexpr std::initializer_list<DescriptorSetLayoutBinding> ssrVariantDescriptorSetLayoutList = {
{ 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 },
{ DescriptorType::SAMPLER_2D_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
};
// Used for generating the color pass (i.e. the main pass). This is in fact a template that gets
// declined into 8 different layouts, based on variants.
//
// Note about the SHADOW_MAP binding points:
// This descriptor can either be a SAMPLER_FLOAT or a SAMPLER_DEPTH,
// and there are 3 cases to consider:
//
// | TextureType | CompareMode | Filtered | SamplerType | Variant |
// ---------+-------------+-------------+----------+-------------+---------+
// PCF | DEPTH | COMPARE | Yes | DEPTH | - |
// VSM | FLOAT | NONE | Yes | FLOAT | VSM |
// OTHER | DEPTH | NONE | No | FLOAT | VSM |
//
// The SamplerType to use depends on the Variant. Variant::VSM is set for all cases except PCM.
//
static constexpr std::initializer_list<DescriptorSetLayoutBinding> perViewDescriptorSetLayoutList = {
{ 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 },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::RECORD_BUFFER },
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FROXEL_BUFFER },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOW_MAP },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_DFG_LUT },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_SPECULAR },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSAO },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG },
{ DescriptorType::SAMPLER_2D_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
{ DescriptorType::SAMPLER_2D_ARRAY_DEPTH, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOW_MAP },
{ DescriptorType::SAMPLER_2D_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_DFG_LUT },
{ DescriptorType::SAMPLER_CUBE_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::IBL_SPECULAR },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSAO },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
{ DescriptorType::SAMPLER_CUBE_FLOAT, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG },
};
static constexpr std::initializer_list<DescriptorSetLayoutBinding> perRenderableDescriptorSetLayoutList = {
{ 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 },
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_POSITIONS },
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_TANGENTS },
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS },
{ 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 },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_POSITIONS },
{ DescriptorType::SAMPLER_2D_ARRAY_INT, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_TANGENTS },
{ DescriptorType::SAMPLER_2D_ARRAY_FLOAT, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS },
};
struct PairSamplerTypeFormatHasher {
std::size_t operator()(const std::pair<SamplerType, SamplerFormat>& p) const {
using UnderlyingSamplerType = std::underlying_type_t<SamplerType>;
using UnderlyingSamplerFormat = std::underlying_type_t<SamplerFormat>;
std::size_t seed = 0;
std::size_t const hash1 = std::hash<UnderlyingSamplerType>{}(
static_cast<UnderlyingSamplerType>(p.first)
);
std::size_t const hash2 = std::hash<UnderlyingSamplerFormat>{}(
static_cast<UnderlyingSamplerFormat>(p.second)
);
seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
return seed;
}
};
static const std::unordered_map<
std::pair<SamplerType, SamplerFormat>, DescriptorType, PairSamplerTypeFormatHasher> sDescriptorTypeMap{
{{ SamplerType::SAMPLER_2D, SamplerFormat::INT }, DescriptorType::SAMPLER_2D_INT },
{{ SamplerType::SAMPLER_2D, SamplerFormat::UINT }, DescriptorType::SAMPLER_2D_UINT },
{{ SamplerType::SAMPLER_2D, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_2D_FLOAT },
{{ SamplerType::SAMPLER_2D, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_2D_DEPTH },
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::INT }, DescriptorType::SAMPLER_2D_ARRAY_INT },
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::UINT }, DescriptorType::SAMPLER_2D_ARRAY_UINT },
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_2D_ARRAY_FLOAT },
{{ SamplerType::SAMPLER_2D_ARRAY, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_2D_ARRAY_DEPTH },
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::INT }, DescriptorType::SAMPLER_CUBE_INT },
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::UINT }, DescriptorType::SAMPLER_CUBE_UINT },
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_CUBE_FLOAT },
{{ SamplerType::SAMPLER_CUBEMAP, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_CUBE_DEPTH },
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::INT }, DescriptorType::SAMPLER_CUBE_ARRAY_INT },
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::UINT }, DescriptorType::SAMPLER_CUBE_ARRAY_UINT },
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT },
{{ SamplerType::SAMPLER_CUBEMAP_ARRAY, SamplerFormat::SHADOW }, DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH },
{{ SamplerType::SAMPLER_3D, SamplerFormat::INT }, DescriptorType::SAMPLER_3D_INT },
{{ SamplerType::SAMPLER_3D, SamplerFormat::UINT }, DescriptorType::SAMPLER_3D_UINT },
{{ SamplerType::SAMPLER_3D, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_3D_FLOAT },
{{ SamplerType::SAMPLER_EXTERNAL, SamplerFormat::FLOAT }, DescriptorType::SAMPLER_EXTERNAL }
};
// used for post-processing passes
@@ -146,12 +209,12 @@ utils::CString getDescriptorName(DescriptorSetBindingPoints const set,
switch (set) {
case DescriptorSetBindingPoints::PER_VIEW: {
auto pos = set0.find(binding);
auto const pos = set0.find(binding);
assert_invariant(pos != set0.end());
return { pos->second.data(), pos->second.size() };
}
case DescriptorSetBindingPoints::PER_RENDERABLE: {
auto pos = set1.find(binding);
auto const pos = set1.find(binding);
assert_invariant(pos != set1.end());
return { pos->second.data(), pos->second.size() };
}
@@ -160,17 +223,13 @@ utils::CString getDescriptorName(DescriptorSetBindingPoints const set,
return "MaterialParams";
}
}
return "Unknown";
}
DescriptorSetLayout getPerViewDescriptorSetLayout(
MaterialDomain const domain,
UserVariantFilterMask const variantFilter,
bool const isLit,
ReflectionMode const reflectionMode,
RefractionMode const refractionMode) noexcept {
bool const ssr = reflectionMode == ReflectionMode::SCREEN_SPACE ||
refractionMode == RefractionMode::SCREEN_SPACE;
bool const isLit, bool const isSSR, bool const hasFog,
bool const isVSM) noexcept {
switch (domain) {
case MaterialDomain::SURFACE: {
@@ -189,7 +248,7 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
layout.bindings.end());
}
// remove descriptors not needed for SSRs
if (!ssr) {
if (!isSSR) {
layout.bindings.erase(
std::remove_if(layout.bindings.begin(), layout.bindings.end(),
[](auto const& entry) {
@@ -199,7 +258,7 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
}
// remove fog descriptor if filtered out
if (variantFilter & (UserVariantFilterMask)UserVariantFilterBit::FOG) {
if (!hasFog) {
layout.bindings.erase(
std::remove_if(layout.bindings.begin(), layout.bindings.end(),
[](auto const& entry) {
@@ -207,6 +266,17 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
}),
layout.bindings.end());
}
// change the SHADOW_MAP descriptor type for VSM
if (isVSM) {
auto const pos = std::find_if(layout.bindings.begin(), layout.bindings.end(),
[](auto const& v) {
return v.binding == PerViewBindingPoints::SHADOW_MAP;
});
if (pos != layout.bindings.end()) {
pos->type = DescriptorType::SAMPLER_2D_ARRAY_FLOAT;
}
}
return layout;
}
case MaterialDomain::POST_PROCESS:
@@ -219,11 +289,8 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
Variant const variant,
MaterialDomain domain,
UserVariantFilterMask const variantFilter,
bool const isLit,
ReflectionMode const reflectionMode,
RefractionMode const refractionMode) noexcept {
MaterialDomain const domain,
bool const isLit, bool const isSSR, bool const hasFog) noexcept {
if (Variant::isValidDepthVariant(variant)) {
return depthVariantDescriptorSetLayout;
}
@@ -231,11 +298,17 @@ DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
return ssrVariantDescriptorSetLayout;
}
// We need to filter out all the descriptors not included in the "resolved" layout below
return getPerViewDescriptorSetLayout(domain, variantFilter,
isLit, reflectionMode, refractionMode);
return getPerViewDescriptorSetLayout(domain, isLit, isSSR, hasFog,
Variant::isVSMVariant(variant));
}
DescriptorType getDescriptorType(SamplerType const type, SamplerFormat const format) {
auto const pos = sDescriptorTypeMap.find({ type, format });
FILAMENT_CHECK_PRECONDITION(pos != sDescriptorTypeMap.end())
<< "Incompatible Sampler Format " << to_string(format)
<< " and Type " << to_string(type);
return pos->second;
}
template<class ITERATOR, class PREDICATE>
constexpr static ITERATOR find_if(ITERATOR first, ITERATOR last, PREDICATE pred) {

View File

@@ -23,7 +23,6 @@
#include <spirv_glsl.hpp>
#include <spirv_msl.hpp>
#include "backend/DriverEnums.h"
#include "private/filament/DescriptorSets.h"
#include "sca/builtinResource.h"
#include "sca/GLSLTools.h"
@@ -45,10 +44,15 @@
#include <algorithm>
#include <optional>
#include <sstream>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
#include <stddef.h>
#include <stdint.h>
#ifdef FILAMENT_SUPPORTS_WEBGPU
#include <tint/tint.h>
#endif
@@ -71,22 +75,7 @@ using BindingIndexMap = std::unordered_map<std::string, uint16_t>;
#define DEBUG_LOG_DESCRIPTOR_SETS 0
#endif
const char* toString(DescriptorType type) {
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";
}
}
const char* toString(ShaderStageFlags flags) {
static const char* toString(ShaderStageFlags const flags) {
std::vector<const char*> stages;
if (any(flags & ShaderStageFlags::VERTEX)) {
stages.push_back("VERTEX");
@@ -111,14 +100,14 @@ const char* toString(ShaderStageFlags flags) {
return buffer;
}
const char* prettyDescriptorFlags(DescriptorFlags flags) {
static const char* prettyDescriptorFlags(DescriptorFlags const flags) {
if (flags == DescriptorFlags::DYNAMIC_OFFSET) {
return "DYNAMIC_OFFSET";
}
return "NONE";
}
const char* prettyPrintSamplerType(SamplerType type) {
static const char* prettyPrintSamplerType(SamplerType const type) {
switch (type) {
case SamplerType::SAMPLER_2D:
return "SAMPLER_2D";
@@ -145,12 +134,18 @@ DescriptorSetLayout getPerMaterialDescriptorSet(SamplerInterfaceBlock const& sib
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT,
+PerMaterialBindingPoints::MATERIAL_PARAMS, DescriptorFlags::NONE, 0 });
for (auto const& sampler : samplers) {
layout.bindings.push_back(DescriptorSetLayoutBinding {
(sampler.type == SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) ?
DescriptorType::SAMPLER_EXTERNAL : DescriptorType::SAMPLER,
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, sampler.binding,
DescriptorFlags::NONE, 0 });
for (auto const& sampler: samplers) {
DescriptorSetLayoutBinding layoutBinding{
DescriptorType::SAMPLER_EXTERNAL,
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT,
sampler.binding,
DescriptorFlags::NONE,
0
};
if (sampler.type != SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) {
layoutBinding.type = descriptor_sets::getDescriptorType(sampler.type, sampler.format);
}
layout.bindings.push_back(layoutBinding);
}
return layout;
@@ -164,11 +159,12 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
DescriptorSetLayout const descriptorSetLayout = [&] {
switch (set) {
case DescriptorSetBindingPoints::PER_VIEW: {
bool const isLit = material.isLit || material.hasShadowMultiplier;
bool const isSSR = material.reflectionMode == ReflectionMode::SCREEN_SPACE ||
material.refractionMode == RefractionMode::SCREEN_SPACE;
bool const hasFog = !(config.variantFilter & UserVariantFilterMask(UserVariantFilterBit::FOG));
return descriptor_sets::getPerViewDescriptorSetLayoutWithVariant(
config.variant, config.domain, config.variantFilter,
material.isLit || material.hasShadowMultiplier,
material.reflectionMode,
material.refractionMode);
config.variant, config.domain, isLit, isSSR, hasFog);
}
case DescriptorSetBindingPoints::PER_RENDERABLE:
return descriptor_sets::getPerRenderableLayout();
@@ -210,17 +206,16 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
return descriptor_sets::getDescriptorName(set, binding);
};
for (auto descriptor : descriptorSetLayout.bindings) {
descriptor_binding_t binding = descriptor.binding;
for (auto const& layoutBinding : descriptorSetLayout.bindings) {
descriptor_binding_t binding = layoutBinding.binding;
auto name = getDescriptorName(binding);
if (descriptor.type == DescriptorType::SAMPLER ||
descriptor.type == DescriptorType::SAMPLER_EXTERNAL) {
auto pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
if (DescriptorSetLayoutBinding::isSampler(layoutBinding.type)) {
auto const pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
[&](const auto& entry) { return entry.binding == binding; });
assert_invariant(pos != descriptorSetSamplerList.end());
descriptors.emplace_back(name, descriptor, *pos);
descriptors.emplace_back(name, layoutBinding, *pos);
} else {
descriptors.emplace_back(name, descriptor, std::nullopt);
descriptors.emplace_back(name, layoutBinding, std::nullopt);
}
}
@@ -229,8 +224,8 @@ static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
});
}
void prettyPrintDescriptorSetInfoVector(DescriptorSets const& sets) {
auto getName = [](uint8_t set) {
static void prettyPrintDescriptorSetInfoVector(DescriptorSets const& sets) noexcept {
auto getName = [](uint8_t const set) {
switch (set) {
case +DescriptorSetBindingPoints::PER_VIEW:
return "perViewDescriptorSetLayout";
@@ -247,18 +242,23 @@ void prettyPrintDescriptorSetInfoVector(DescriptorSets const& sets) {
printf("[DS] info (%s) = [\n", getName(setIndex));
for (auto const& descriptor : descriptors) {
auto const& [name, info, sampler] = descriptor;
if (info.type == DescriptorType::SAMPLER ||
info.type == DescriptorType::SAMPLER_EXTERNAL) {
if (DescriptorSetLayoutBinding::isSampler(info.type)) {
assert_invariant(sampler.has_value());
printf(" {name = %s, binding = %d, type = %s, count = %d, stage = %s, flags = "
printf(" {name = %s, binding = %d, type = %.*s, count = %d, stage = %s, flags = "
"%s, samplerType = %s}",
name.c_str_safe(), info.binding, toString(info.type), info.count,
name.c_str_safe(), info.binding,
int(to_string(info.type).size()),
to_string(info.type).data(),
info.count,
toString(info.stageFlags), prettyDescriptorFlags(info.flags),
prettyPrintSamplerType(sampler->type));
} else {
printf(" {name = %s, binding = %d, type = %s, count = %d, stage = %s, flags = "
printf(" {name = %s, binding = %d, type = %.*s, count = %d, stage = %s, flags = "
"%s}",
name.c_str_safe(), info.binding, toString(info.type), info.count,
name.c_str_safe(), info.binding,
int(to_string(info.type).size()),
to_string(info.type).data(),
info.count,
toString(info.stageFlags), prettyDescriptorFlags(info.flags));
}
printf(",\n");
@@ -472,7 +472,25 @@ void GLSLPostProcessor::spirvToMsl(const SpirvBlob* spirv, std::string* outMsl,
break;
}
case DescriptorType::SAMPLER:
case DescriptorType::SAMPLER_2D_FLOAT:
case DescriptorType::SAMPLER_2D_INT:
case DescriptorType::SAMPLER_2D_UINT:
case DescriptorType::SAMPLER_2D_DEPTH:
case DescriptorType::SAMPLER_2D_ARRAY_FLOAT:
case DescriptorType::SAMPLER_2D_ARRAY_INT:
case DescriptorType::SAMPLER_2D_ARRAY_UINT:
case DescriptorType::SAMPLER_2D_ARRAY_DEPTH:
case DescriptorType::SAMPLER_CUBE_FLOAT:
case DescriptorType::SAMPLER_CUBE_INT:
case DescriptorType::SAMPLER_CUBE_UINT:
case DescriptorType::SAMPLER_CUBE_DEPTH:
case DescriptorType::SAMPLER_CUBE_ARRAY_FLOAT:
case DescriptorType::SAMPLER_CUBE_ARRAY_INT:
case DescriptorType::SAMPLER_CUBE_ARRAY_UINT:
case DescriptorType::SAMPLER_CUBE_ARRAY_DEPTH:
case DescriptorType::SAMPLER_3D_FLOAT:
case DescriptorType::SAMPLER_3D_INT:
case DescriptorType::SAMPLER_3D_UINT:
case DescriptorType::SAMPLER_EXTERNAL: {
assert_invariant(sampler.has_value());
const std::string samplerName = std::string(name.c_str()) + "Smplr";
@@ -568,7 +586,7 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
//After splitting the image samplers, we need to remap the bindings to separate them.
rebindImageSamplerForWGSL(*spirv);
//Allow non-uniform derivitives due to our nested shaders. See https://github.com/gpuweb/gpuweb/issues/3479
//Allow non-uniform derivatives due to our nested shaders. See https://github.com/gpuweb/gpuweb/issues/3479
const tint::spirv::reader::Options readerOpts{true};
tint::wgsl::writer::Options writerOpts{};
@@ -607,7 +625,9 @@ bool GLSLPostProcessor::spirvToWgsl(SpirvBlob *spirv, std::string *outWsl) {
*outWsl = wgslOut->wgsl;
return true;
#else
slog.i << "Trying to emit WGSL without including WebGPU dependencies, please set CMake arg FILAMENT_SUPPORTS_WEBGPU and FILAMENT_SUPPORTS_WEBGPU" << io::endl;
slog.i << "Trying to emit WGSL without including WebGPU dependencies,"
" please set CMake arg FILAMENT_SUPPORTS_WEBGPU and FILAMENT_SUPPORTS_WEBGPU"
<< io::endl;
return false;
#endif

View File

@@ -27,7 +27,10 @@
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/debug.h>
#include <utils/FixedCapacityVector.h>
#include <utility>
@@ -194,11 +197,7 @@ void MaterialDescriptorBindingsChuck::flatten(Flattener& f) {
// all the material's sampler descriptors
for (auto const& entry: mSamplerInterfaceBlock.getSamplerInfoList()) {
f.writeString({ entry.uniformName.data(), entry.uniformName.size() });
if (entry.type == SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) {
f.writeUint8(uint8_t(DescriptorType::SAMPLER_EXTERNAL));
} else {
f.writeUint8(uint8_t(DescriptorType::SAMPLER));
}
f.writeUint8(uint8_t(descriptor_sets::getDescriptorType(entry.type, entry.format)));
f.writeUint8(entry.binding);
}
}
@@ -228,11 +227,7 @@ void MaterialDescriptorSetLayoutChunk::flatten(Flattener& f) {
// all the material's sampler descriptors
for (auto const& entry: mSamplerInterfaceBlock.getSamplerInfoList()) {
if (entry.type == SamplerInterfaceBlock::Type::SAMPLER_EXTERNAL) {
f.writeUint8(uint8_t(DescriptorType::SAMPLER_EXTERNAL));
} else {
f.writeUint8(uint8_t(DescriptorType::SAMPLER));
}
f.writeUint8(uint8_t(descriptor_sets::getDescriptorType(entry.type, entry.format)));
f.writeUint8(uint8_t(ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT));
f.writeUint8(entry.binding);
f.writeUint8(uint8_t(DescriptorFlags::NONE));

View File

@@ -36,6 +36,7 @@
#include <algorithm>
#include <iterator>
#include <utility>
#include <stddef.h>
#include <stdint.h>
@@ -46,9 +47,9 @@ using namespace filament;
using namespace filament::backend;
using namespace utils;
void ShaderGenerator::generateSurfaceMaterialVariantDefines(utils::io::sstream& out,
ShaderStage stage, MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, filament::Variant variant) noexcept {
void ShaderGenerator::generateSurfaceMaterialVariantDefines(io::sstream& out,
ShaderStage const stage, MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, filament::Variant const variant) noexcept {
bool const litVariants = material.isLit || material.hasShadowMultiplier;
@@ -228,25 +229,25 @@ void ShaderGenerator::generateSurfaceMaterialVariantProperties(io::sstream& out,
}
}
void ShaderGenerator::generateVertexDomainDefines(io::sstream& vs, VertexDomain domain) noexcept {
void ShaderGenerator::generateVertexDomainDefines(io::sstream& out, VertexDomain const domain) noexcept {
switch (domain) {
case VertexDomain::OBJECT:
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_OBJECT", true);
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_OBJECT", true);
break;
case VertexDomain::WORLD:
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_WORLD", true);
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_WORLD", true);
break;
case VertexDomain::VIEW:
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_VIEW", true);
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_VIEW", true);
break;
case VertexDomain::DEVICE:
CodeGenerator::generateDefine(vs, "VERTEX_DOMAIN_DEVICE", true);
CodeGenerator::generateDefine(out, "VERTEX_DOMAIN_DEVICE", true);
break;
}
}
void ShaderGenerator::generatePostProcessMaterialVariantDefines(io::sstream& out,
PostProcessVariant variant) noexcept {
PostProcessVariant const variant) noexcept {
switch (variant) {
case PostProcessVariant::OPAQUE:
CodeGenerator::generateDefine(out, "POST_PROCESS_OPAQUE", 1u);
@@ -258,7 +259,7 @@ void ShaderGenerator::generatePostProcessMaterialVariantDefines(io::sstream& out
}
void ShaderGenerator::appendShader(io::sstream& ss,
const CString& shader, size_t lineOffset) noexcept {
const CString& shader, size_t const lineOffset) noexcept {
auto countLines = [](const char* s) -> size_t {
size_t lines = 0;
@@ -314,9 +315,9 @@ ShaderGenerator::ShaderGenerator(
MaterialBuilder::PreprocessorDefineList const& defines,
MaterialBuilder::ConstantList const& constants,
MaterialBuilder::PushConstantList const& pushConstants,
CString const& materialCode, size_t lineOffset,
CString const& materialVertexCode, size_t vertexLineOffset,
MaterialBuilder::MaterialDomain materialDomain) noexcept {
CString const& materialCode, size_t const lineOffset,
CString const& materialVertexCode, size_t const vertexLineOffset,
MaterialBuilder::MaterialDomain const materialDomain) noexcept {
if (materialDomain == MaterialBuilder::MaterialDomain::COMPUTE) {
// we shouldn't have a vertex shader in a compute material
@@ -360,8 +361,8 @@ ShaderGenerator::ShaderGenerator(
}
}
void ShaderGenerator::fixupExternalSamplers(ShaderModel sm, std::string& shader,
MaterialBuilder::FeatureLevel featureLevel,
void ShaderGenerator::fixupExternalSamplers(ShaderModel const sm, std::string& shader,
MaterialBuilder::FeatureLevel const featureLevel,
MaterialInfo const& material) noexcept {
// External samplers are only supported on GL ES at the moment, we must
// skip the fixup on desktop targets
@@ -370,11 +371,11 @@ void ShaderGenerator::fixupExternalSamplers(ShaderModel sm, std::string& shader,
}
}
std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
MaterialInfo const& material, const filament::Variant variant, Interpolation interpolation,
VertexDomain vertexDomain) const noexcept {
std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel const shaderModel,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
MaterialInfo const& material, const filament::Variant variant, Interpolation const interpolation,
VertexDomain const vertexDomain) const noexcept {
assert_invariant(filament::Variant::isValid(variant));
assert_invariant(mMaterialDomain != MaterialBuilder::MaterialDomain::COMPUTE);
@@ -416,23 +417,23 @@ std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel shaderModel,
AttributeBitset attributes = material.requiredAttributes;
if (hasSkinningOrMorphing(variant, featureLevel)) {
attributes.set(VertexAttribute::BONE_INDICES);
attributes.set(VertexAttribute::BONE_WEIGHTS);
attributes.set(BONE_INDICES);
attributes.set(BONE_WEIGHTS);
if (material.useLegacyMorphing) {
attributes.set(VertexAttribute::MORPH_POSITION_0);
attributes.set(VertexAttribute::MORPH_POSITION_1);
attributes.set(VertexAttribute::MORPH_POSITION_2);
attributes.set(VertexAttribute::MORPH_POSITION_3);
attributes.set(VertexAttribute::MORPH_TANGENTS_0);
attributes.set(VertexAttribute::MORPH_TANGENTS_1);
attributes.set(VertexAttribute::MORPH_TANGENTS_2);
attributes.set(VertexAttribute::MORPH_TANGENTS_3);
attributes.set(MORPH_POSITION_0);
attributes.set(MORPH_POSITION_1);
attributes.set(MORPH_POSITION_2);
attributes.set(MORPH_POSITION_3);
attributes.set(MORPH_TANGENTS_0);
attributes.set(MORPH_TANGENTS_1);
attributes.set(MORPH_TANGENTS_2);
attributes.set(MORPH_TANGENTS_3);
}
}
MaterialBuilder::PushConstantList vertexPushConstants;
std::copy_if(mPushConstants.begin(), mPushConstants.end(),
std::back_insert_iterator<MaterialBuilder::PushConstantList>(vertexPushConstants),
std::back_insert_iterator(vertexPushConstants),
[](MaterialBuilder::PushConstant const& constant) {
return constant.stage == ShaderStage::VERTEX;
});
@@ -505,11 +506,11 @@ std::string ShaderGenerator::createSurfaceVertexProgram(ShaderModel shaderModel,
return vs.c_str();
}
std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel const shaderModel,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
MaterialInfo const& material, const filament::Variant variant,
Interpolation interpolation, UserVariantFilterMask variantFilter) const noexcept {
Interpolation const interpolation, UserVariantFilterMask const variantFilter) const noexcept {
assert_invariant(filament::Variant::isValid(variant));
assert_invariant(mMaterialDomain != MaterialBuilder::MaterialDomain::COMPUTE);
@@ -529,8 +530,8 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode
generateSurfaceMaterialVariantDefines(
fs, ShaderStage::FRAGMENT, featureLevel, material, variant);
auto defaultSpecularAO = shaderModel == ShaderModel::MOBILE ?
SpecularAmbientOcclusion::NONE : SpecularAmbientOcclusion::SIMPLE;
auto const defaultSpecularAO = shaderModel == ShaderModel::MOBILE ?
SpecularAmbientOcclusion::NONE : SpecularAmbientOcclusion::SIMPLE;
auto specularAO = material.specularAOSet ? material.specularAO : defaultSpecularAO;
CodeGenerator::generateDefine(fs, "SPECULAR_AMBIENT_OCCLUSION", uint32_t(specularAO));
@@ -542,12 +543,12 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode
MaterialBuilder::PushConstantList fragmentPushConstants;
std::copy_if(mPushConstants.begin(), mPushConstants.end(),
std::back_insert_iterator<MaterialBuilder::PushConstantList>(fragmentPushConstants),
std::back_insert_iterator(fragmentPushConstants),
[](MaterialBuilder::PushConstant const& constant) {
return constant.stage == ShaderStage::FRAGMENT;
});
cg.generateSurfaceShaderInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes, interpolation,
fragmentPushConstants);
cg.generateSurfaceShaderInputs(fs, ShaderStage::FRAGMENT, material.requiredAttributes,
interpolation, fragmentPushConstants);
CodeGenerator::generateSurfaceTypes(fs, ShaderStage::FRAGMENT);
@@ -605,12 +606,16 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode
if (featureLevel >= FeatureLevel::FEATURE_LEVEL_1) {
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
// this is the list of samplers we need to filter
bool const isLit = material.isLit || material.hasShadowMultiplier;
bool const isSSR = material.reflectionMode == ReflectionMode::SCREEN_SPACE ||
material.refractionMode == RefractionMode::SCREEN_SPACE;
bool const hasFog = !(variantFilter & UserVariantFilterMask(UserVariantFilterBit::FOG));
auto const list = SamplerInterfaceBlock::filterSamplerList(
SibGenerator::getPerViewSib(variant).getSamplerInfoList(),
descriptor_sets::getPerViewDescriptorSetLayoutWithVariant(
variant, mMaterialDomain, variantFilter,
material.isLit || material.hasShadowMultiplier,
material.reflectionMode, material.refractionMode));
variant, mMaterialDomain, isLit, isSSR, hasFog));
cg.generateCommonSamplers(fs, DescriptorSetBindingPoints::PER_VIEW, list);
}
@@ -665,9 +670,9 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode
return fs.c_str();
}
std::string ShaderGenerator::createSurfaceComputeProgram(filament::backend::ShaderModel shaderModel,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
std::string ShaderGenerator::createSurfaceComputeProgram(ShaderModel const shaderModel,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
MaterialInfo const& material) const noexcept {
assert_invariant(mMaterialDomain == MaterialBuilder::MaterialDomain::COMPUTE);
assert_invariant(featureLevel >= FeatureLevel::FEATURE_LEVEL_2);
@@ -708,9 +713,9 @@ std::string ShaderGenerator::createSurfaceComputeProgram(filament::backend::Shad
return s.c_str();
}
std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel const sm,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
MaterialInfo const& material, const filament::Variant::type_t variantKey) const noexcept {
const CodeGenerator cg(sm, targetApi, targetLanguage, featureLevel);
io::sstream vs;
@@ -718,7 +723,7 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
generateUserSpecConstants(cg, vs, mConstants);
CodeGenerator::generateDefine(vs, "LOCATION_POSITION", uint32_t(VertexAttribute::POSITION));
CodeGenerator::generateDefine(vs, "LOCATION_POSITION", uint32_t(POSITION));
// custom material variables
size_t variableIndex = 0;
@@ -752,9 +757,9 @@ std::string ShaderGenerator::createPostProcessVertexProgram(ShaderModel sm,
return vs.c_str();
}
std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
MaterialBuilder::TargetApi targetApi, MaterialBuilder::TargetLanguage targetLanguage,
MaterialBuilder::FeatureLevel featureLevel,
std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel const sm,
MaterialBuilder::TargetApi const targetApi, MaterialBuilder::TargetLanguage const targetLanguage,
MaterialBuilder::FeatureLevel const featureLevel,
MaterialInfo const& material, uint8_t variant) const noexcept {
const CodeGenerator cg(sm, targetApi, targetLanguage, featureLevel);
io::sstream fs;
@@ -811,7 +816,7 @@ std::string ShaderGenerator::createPostProcessFragmentProgram(ShaderModel sm,
}
bool ShaderGenerator::hasSkinningOrMorphing(
filament::Variant variant, MaterialBuilder::FeatureLevel featureLevel) noexcept {
filament::Variant const variant, MaterialBuilder::FeatureLevel const featureLevel) noexcept {
return variant.hasSkinningOrMorphing()
// HACK(exv): Ignore skinning/morphing variant when targeting ESSL 1.0. We should
// either properly support skinning on FL0 or build a system in matc which allows
@@ -820,7 +825,7 @@ bool ShaderGenerator::hasSkinningOrMorphing(
}
bool ShaderGenerator::hasStereo(
filament::Variant variant, MaterialBuilder::FeatureLevel featureLevel) noexcept {
filament::Variant const variant, MaterialBuilder::FeatureLevel const featureLevel) noexcept {
return variant.hasStereo()
// HACK(exv): Ignore stereo variant when targeting ESSL 1.0. We should properly build a
// system in matc which allows the set of included variants to differ per-feature level.