Compare commits
10 Commits
pf/testing
...
ebridgewat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
815629f14e | ||
|
|
c05a446e10 | ||
|
|
9d49205844 | ||
|
|
7099b6dd6f | ||
|
|
18becfc656 | ||
|
|
cd2d499e25 | ||
|
|
3bb72cefe9 | ||
|
|
1a67f9233b | ||
|
|
f7e20562a8 | ||
|
|
08af16239c |
@@ -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**]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}}
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ?
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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{};
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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{};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user