diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt index b36532c30f..1f724ad030 100644 --- a/filament/CMakeLists.txt +++ b/filament/CMakeLists.txt @@ -163,6 +163,7 @@ set(MATERIAL_SRCS src/materials/dof/dofDownsample.mat src/materials/dof/dofCombine.mat src/materials/dof/dofTiles.mat + src/materials/dof/dofTilesSwizzle.mat src/materials/dof/dofDilate.mat src/materials/dof/dofMipmap.mat src/materials/dof/dofMedian.mat diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index 0515965844..cfd6bafc18 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -551,6 +551,7 @@ bool MetalDriver::isTextureFormatSupported(TextureFormat format) { } bool MetalDriver::isTextureSwizzleSupported() { + return false; // FIXME: reenable once textures used as attachments are supported if (@available(macOS 10.15, iOS 13, *)) { return true; } else { diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 64a1dacd16..4cc34a17a8 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -212,6 +212,7 @@ static const MaterialInfo sMaterialList[] = { { "dofCoc", MATERIAL(DOFCOC) }, { "dofMipmap", MATERIAL(DOFMIPMAP) }, { "dofTiles", MATERIAL(DOFTILES) }, + { "dofTilesSwizzle", MATERIAL(DOFTILESSWIZZLE) }, { "dofDilate", MATERIAL(DOFDILATE) }, { "dof", MATERIAL(DOF) }, { "dofMedian", MATERIAL(DOFMEDIAN) }, @@ -1064,6 +1065,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, FrameGraphId outTilesCocMinMax; }; + const bool textureSwizzleSupported = Texture::isTextureSwizzleSupported(mEngine); for (size_t i = 0; i < tileReductionCount; i++) { auto& ppDoFTiling = fg.addPass("DoF Tiling", [&](FrameGraph::Builder& builder, auto& data) { @@ -1083,7 +1085,9 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, auto const& outputDesc = resources.getDescriptor(data.outTilesCocMinMax); auto const& out = resources.getRenderPassInfo(); auto inCocMinMax = resources.getTexture(data.inCocMinMax); - auto const& material = getPostProcessMaterial("dofTiles"); + auto const& material = (!textureSwizzleSupported && (i == 0)) ? + getPostProcessMaterial("dofTilesSwizzle") : + getPostProcessMaterial("dofTiles"); FMaterialInstance* const mi = material.getMaterialInstance(); mi->setParameter("cocMinMax", inCocMinMax, { .filterMin = SamplerMinFilter::NEAREST }); mi->setParameter("uvscale", float4{ diff --git a/filament/src/materials/dof/dofTiles.mat b/filament/src/materials/dof/dofTiles.mat index b84a030eac..b3c4c3f342 100644 --- a/filament/src/materials/dof/dofTiles.mat +++ b/filament/src/materials/dof/dofTiles.mat @@ -47,6 +47,7 @@ void postProcess(inout PostProcessInputs postProcess) { ivec2 i = ivec2(uv * size - 0.5); // note: the first time, the source texture is swizzled -- so .r and .g are the same channel + // if swizzling is not supported, we use dofTilesSwizzle instead. #if defined(TARGET_VULKAN_ENVIRONMENT) || !defined(TARGET_MOBILE) vec4 mi = textureGather(materialParams_cocMinMax, uv, 0); // 01, 11, 10, 00 vec4 ma = textureGather(materialParams_cocMinMax, uv, 1); // 01, 11, 10, 00 diff --git a/filament/src/materials/dof/dofTilesSwizzle.mat b/filament/src/materials/dof/dofTilesSwizzle.mat new file mode 100644 index 0000000000..e852b57e8c --- /dev/null +++ b/filament/src/materials/dof/dofTilesSwizzle.mat @@ -0,0 +1,66 @@ +material { + name : dofTilesSwizzle, + parameters : [ + { + type : sampler2d, + name : cocMinMax, + precision: medium + }, + { + type : float4, + name : uvscale, + precision: high + } + ], + variables : [ + vertex + ], + domain : postprocess, + depthWrite : false, + depthCulling : false +} + +vertex { + void postProcessVertex(inout PostProcessVertexInputs postProcess) { + postProcess.vertex.xy = (postProcess.normalizedUV * materialParams.uvscale.xy * 2.0 - 0.5) * materialParams.uvscale.zw; + } +} + +fragment { + +void dummy(){} + +float max4(const vec4 f) { + vec2 t = max(f.xy, f.zw); + return max(t.x, t.y); +} + +float min4(const vec4 f) { + vec2 t = min(f.xy, f.zw); + return min(t.x, t.y); +} + +void postProcess(inout PostProcessInputs postProcess) { + highp vec2 uv = variable_vertex.xy; + highp vec2 size = vec2(textureSize(materialParams_cocMinMax, 0)); + + ivec2 i = ivec2(uv * size - 0.5); + +#if defined(TARGET_VULKAN_ENVIRONMENT) || !defined(TARGET_MOBILE) + vec4 mi = textureGather(materialParams_cocMinMax, uv, 0); // 01, 11, 10, 00 +#else + vec4 mi; + mi[0] = texelFetchOffset(materialParams_cocMinMax, i, 0, ivec2(0, 1)).r; + mi[1] = texelFetchOffset(materialParams_cocMinMax, i, 0, ivec2(1, 1)).r; + mi[2] = texelFetchOffset(materialParams_cocMinMax, i, 0, ivec2(1, 0)).r; + mi[3] = texelFetchOffset(materialParams_cocMinMax, i, 0, ivec2(0, 0)).r; +#endif + + // compute tile's min CoC + postProcess.color.r = min4(mi); + + // compute tile's max CoC + postProcess.color.g = max4(mi); +} + +}