diff --git a/CMakeLists.txt b/CMakeLists.txt
index e5475ef5..4eb8a68b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -247,57 +247,59 @@ if (WIN32)
     # __declspec(dllexport) in front of each functions).
     set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
 
-    # The CMAKE_CXX_FLAGS vars can be overriden by some Visual Studio generators, so we use an alternative
-    # global method here:
-    if (${USE_STATIC_CRT})
-        add_compile_options(
-            $<$<CONFIG:>:/MT>
-            $<$<CONFIG:Debug>:/MTd>
-            $<$<CONFIG:Release>:/MT>
-        )
-    else()
-        add_compile_options(
-            $<$<CONFIG:>:/MD>
-            $<$<CONFIG:Debug>:/MDd>
-            $<$<CONFIG:Release>:/MD>
-        )
-    endif()
-
-    # TODO: Figure out why pdb generation messes with incremental compilaton.
-    # IN RELEASE_WITH_DEBUG_INFO, generate debug info in .obj, no in pdb.
-    set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Z7")
-    set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /Z7")
-
-    # In RELEASE, also generate PDBs.
-    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
-    set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi")
-
-    # In DEBUG, avoid generating a PDB file which seems to mess with incremental compilation.
-    # Instead generate debug info directly inside obj files.
-    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Z7")
-    set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7")
-
-    # Special settings when building on CI.
-    if (${FILAMENT_WINDOWS_CI_BUILD})
-        set(LinkerFlags
-            CMAKE_SHARED_LINKER_FLAGS_DEBUG
-            CMAKE_EXE_LINKER_FLAGS_DEBUG
-            CMAKE_MODULE_LINKER_FLAGS_DEBUG
+    if (MSVC)
+        # The CMAKE_CXX_FLAGS vars can be overriden by some Visual Studio generators, so we use an alternative
+        # global method here:
+        if (${USE_STATIC_CRT})
+            add_compile_options(
+                $<$<CONFIG:>:/MT>
+                $<$<CONFIG:Debug>:/MTd>
+                $<$<CONFIG:Release>:/MT>
             )
-        foreach(LinkerFlag ${LinkerFlags})
-            # The /debug flag outputs .pdb files, which we don't need on CI.
-            string(REPLACE "/debug" "" ${LinkerFlag} ${${LinkerFlag}})
-
-            # The /INCREMENTAL flag outputs .ilk files for incremental linking. These are huge, and
-            # we don't need them on CI.
-            string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" ${LinkerFlag} ${${LinkerFlag}})
-        endforeach()
-
-        # We turn off compile-time optimizations for CI, as options that speed up the compile-time
-        # (e.g. /MP) might increase memory usage, leading to instabilities on limited CI machines.
-        option(FILAMENT_SHORTEN_MSVC_COMPILATION "Shorten compile-time in Visual Studio" OFF)
-    else()
-        option(FILAMENT_SHORTEN_MSVC_COMPILATION "Shorten compile-time in Visual Studio" ON)
+        else()
+            add_compile_options(
+                $<$<CONFIG:>:/MD>
+                $<$<CONFIG:Debug>:/MDd>
+                $<$<CONFIG:Release>:/MD>
+            )
+        endif()
+
+        # TODO: Figure out why pdb generation messes with incremental compilaton.
+        # IN RELEASE_WITH_DEBUG_INFO, generate debug info in .obj, no in pdb.
+        set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Z7")
+        set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /Z7")
+
+        # In RELEASE, also generate PDBs.
+        set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
+        set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi")
+
+        # In DEBUG, avoid generating a PDB file which seems to mess with incremental compilation.
+        # Instead generate debug info directly inside obj files.
+        set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Z7")
+        set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7")
+
+        # Special settings when building on CI.
+        if (${FILAMENT_WINDOWS_CI_BUILD})
+            set(LinkerFlags
+                CMAKE_SHARED_LINKER_FLAGS_DEBUG
+                CMAKE_EXE_LINKER_FLAGS_DEBUG
+                CMAKE_MODULE_LINKER_FLAGS_DEBUG
+                )
+            foreach(LinkerFlag ${LinkerFlags})
+                # The /debug flag outputs .pdb files, which we don't need on CI.
+                string(REPLACE "/debug" "" ${LinkerFlag} ${${LinkerFlag}})
+
+                # The /INCREMENTAL flag outputs .ilk files for incremental linking. These are huge, and
+                # we don't need them on CI.
+                string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" ${LinkerFlag} ${${LinkerFlag}})
+            endforeach()
+
+            # We turn off compile-time optimizations for CI, as options that speed up the compile-time
+            # (e.g. /MP) might increase memory usage, leading to instabilities on limited CI machines.
+            option(FILAMENT_SHORTEN_MSVC_COMPILATION "Shorten compile-time in Visual Studio" OFF)
+        else()
+            option(FILAMENT_SHORTEN_MSVC_COMPILATION "Shorten compile-time in Visual Studio" ON)
+        endif()
     endif()
 
     if (MSVC)
@@ -344,7 +346,7 @@ endif()
 # Detect use of the clang-cl.exe frontend, which does not support all of clangs normal options
 if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
     if ("${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC")
-        message(FATAL_ERROR "Building with Clang on Windows is no longer supported. Use MSVC 2019 instead.")
+        message(WARNING "Building with Clang on Windows is experimental (re-enabled by patch).")
     endif()
 endif()
 
@@ -376,7 +378,7 @@ if (APPLE AND NOT IOS)
 endif()
 
 set(CXX_STANDARD "-std=c++20")
-if (WIN32)
+if (MSVC)
     set(CXX_STANDARD "/std:c++20")
 endif()
 
@@ -770,9 +772,14 @@ function(combine_static_libs TARGET OUTPUT DEPS)
     endforeach()
 
     if (WIN32)
+        if (MSVC)
+            set(AR_COMMAND "${CMAKE_AR}" /nologo /out:temp.lib ${DEPS_FILES})
+        else()
+            set(AR_COMMAND "${CMAKE_AR}" rcs temp.lib ${DEPS_FILES})
+        endif()
         add_custom_command(
             TARGET ${TARGET} POST_BUILD
-            COMMAND lib.exe /nologo /out:temp.lib ${DEPS_FILES}
+            COMMAND ${AR_COMMAND}
             COMMAND "${CMAKE_COMMAND}" -E rename temp.lib ${OUTPUT}
             COMMENT "Combining ${target} dependencies into single shared library"
             VERBATIM
diff --git a/filament/backend/src/CommandStream.cpp b/filament/backend/src/CommandStream.cpp
index 7146800f..d7973ffd 100644
--- a/filament/backend/src/CommandStream.cpp
+++ b/filament/backend/src/CommandStream.cpp
@@ -57,7 +57,7 @@ static void printParameterPack(io::ostream& out, const FIRST& first, const REMAI
     printParameterPack(out, rest...);
 }
 
-static UTILS_NOINLINE UTILS_UNUSED std::string_view extractMethodName(std::string_view command) noexcept { // NOLINT(*-exception-escape)
+UTILS_UNUSED static UTILS_NOINLINE std::string_view extractMethodName(std::string_view command) noexcept { // NOLINT(*-exception-escape)
     constexpr char startPattern[] = "::Command<&filament::backend::Driver::";
     auto pos = command.rfind(startPattern);
     auto end = command.rfind('(');
diff --git a/filament/backend/src/opengl/platforms/PlatformWGL.cpp b/filament/backend/src/opengl/platforms/PlatformWGL.cpp
index 1cc84db0..aa3d24f8 100644
--- a/filament/backend/src/opengl/platforms/PlatformWGL.cpp
+++ b/filament/backend/src/opengl/platforms/PlatformWGL.cpp
@@ -241,7 +241,7 @@ Platform::SwapChain* PlatformWGL::createSwapChain(uint32_t width, uint32_t heigh
     // WS_POPUP was chosen for the window style here after some experimentation.
     // For some reason, using other window styles resulted in corrupted pixel buffers when using
     // readPixels.
-    RECT rect = {0, 0, width, height};
+    RECT rect = {0, 0, static_cast<LONG>(width), static_cast<LONG>(height)};
     AdjustWindowRect(&rect, WS_POPUP, FALSE);
     width = rect.right - rect.left;
     height = rect.bottom - rect.top;
diff --git a/libs/ibl/src/CubemapIBL.cpp b/libs/ibl/src/CubemapIBL.cpp
index 60f83174..1deb0185 100644
--- a/libs/ibl/src/CubemapIBL.cpp
+++ b/libs/ibl/src/CubemapIBL.cpp
@@ -56,7 +56,7 @@ static float3 hemisphereImportanceSampleDggx(float2 u, float a) { // pdf = D(a)
     return { sinTheta * std::cos(phi), sinTheta * std::sin(phi), cosTheta };
 }
 
-static float3 UTILS_UNUSED hemisphereCosSample(float2 u) {  // pdf = cosTheta / F_PI;
+UTILS_UNUSED static float3 hemisphereCosSample(float2 u) {  // pdf = cosTheta / F_PI;
     const float phi = 2.0f * (float) F_PI * u.x;
     const float cosTheta2 = 1 - u.y;
     const float cosTheta = std::sqrt(cosTheta2);
@@ -64,7 +64,7 @@ static float3 UTILS_UNUSED hemisphereCosSample(float2 u) {  // pdf = cosTheta /
     return { sinTheta * std::cos(phi), sinTheta * std::sin(phi), cosTheta };
 }
 
-static float3 UTILS_UNUSED hemisphereUniformSample(float2 u) { // pdf = 1.0 / (2.0 * F_PI);
+UTILS_UNUSED static float3 hemisphereUniformSample(float2 u) { // pdf = 1.0 / (2.0 * F_PI);
     const float phi = 2.0f * (float) F_PI * u.x;
     const float cosTheta = 1 - u.y;
     const float sinTheta = std::sqrt(1 - cosTheta * cosTheta);
@@ -128,7 +128,7 @@ static float3 UTILS_UNUSED hemisphereUniformSample(float2 u) { // pdf = 1.0 / (2
  *  |                                            |
  *  +--------------------------------------------+
  */
-static float3 UTILS_UNUSED hemisphereImportanceSampleDCharlie(float2 u, float a) { // pdf = DistributionCharlie() * cosTheta
+UTILS_UNUSED static float3 hemisphereImportanceSampleDCharlie(float2 u, float a) { // pdf = DistributionCharlie() * cosTheta
     const float phi = 2.0f * (float) F_PI * u.x;
 
     const float sinTheta = std::pow(u.y, a / (2 * a + 1));
@@ -144,7 +144,7 @@ static float DistributionGGX(float NoH, float linearRoughness) {
     return (a * a) / ((float) F_PI * f * f);
 }
 
-static float UTILS_UNUSED DistributionAshikhmin(float NoH, float linearRoughness) {
+UTILS_UNUSED static float DistributionAshikhmin(float NoH, float linearRoughness) {
     float a = linearRoughness;
     float a2 = a * a;
     float cos2h = NoH * NoH;
@@ -153,7 +153,7 @@ static float UTILS_UNUSED DistributionAshikhmin(float NoH, float linearRoughness
     return 1.0f / ((float) F_PI * (1 + 4 * a2)) * (sin4h + 4 * std::exp(-cos2h / (a2 * sin2h)));
 }
 
-static float UTILS_UNUSED DistributionCharlie(float NoH, float linearRoughness) {
+UTILS_UNUSED static float DistributionCharlie(float NoH, float linearRoughness) {
     // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF"
     float a = linearRoughness;
     float invAlpha = 1 / a;
@@ -176,7 +176,7 @@ static float Visibility(float NoV, float NoL, float a) {
     return 0.5f / (GGXV + GGXL);
 }
 
-static float UTILS_UNUSED VisibilityAshikhmin(float NoV, float NoL, float /*a*/) {
+UTILS_UNUSED static float VisibilityAshikhmin(float NoV, float NoL, float /*a*/) {
     // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"
     return 1 / (4 * (NoL + NoV - NoL * NoV));
 }
@@ -634,7 +634,7 @@ void CubemapIBL::diffuseIrradiance(JobSystem& js, Cubemap& dst, const std::vecto
 }
 
 // Not importance-sampled
-static float2 UTILS_UNUSED DFV_NoIS(float NoV, float roughness, size_t numSamples) {
+UTILS_UNUSED static float2 DFV_NoIS(float NoV, float roughness, size_t numSamples) {
     float2 r = 0;
     const float linearRoughness = roughness * roughness;
     const float3 V(std::sqrt(1 - NoV * NoV), 0, NoV);
@@ -832,7 +832,7 @@ static float2 DFV_Multiscatter(float NoV, float linearRoughness, size_t numSampl
     return r * (4.0f / numSamples);
 }
 
-static float UTILS_UNUSED DFV_LazanyiTerm(float NoV, float linearRoughness, size_t numSamples) {
+UTILS_UNUSED static float DFV_LazanyiTerm(float NoV, float linearRoughness, size_t numSamples) {
     float r = 0;
     const float cosThetaMax = (float) std::cos(81.7 * F_PI / 180.0);
     const float q = 1.0f / (cosThetaMax * pow6(1.0f - cosThetaMax));
@@ -958,7 +958,7 @@ static float DFV_Charlie_Uniform(float NoV, float linearRoughness, size_t numSam
  *  +---------------------------------------+
  *
  */
-static float UTILS_UNUSED DFV_Charlie_IS(float NoV, float linearRoughness, size_t numSamples) {
+UTILS_UNUSED static float DFV_Charlie_IS(float NoV, float linearRoughness, size_t numSamples) {
     float r = 0.0;
     const float3 V(std::sqrt(1 - NoV * NoV), 0, NoV);
     for (size_t i = 0; i < numSamples; i++) {
diff --git a/libs/ibl/src/CubemapSH.cpp b/libs/ibl/src/CubemapSH.cpp
index 5d22cb80..f8adccc7 100644
--- a/libs/ibl/src/CubemapSH.cpp
+++ b/libs/ibl/src/CubemapSH.cpp
@@ -685,7 +685,7 @@ void CubemapSH::renderPreScaledSH3Bands(JobSystem& js,
 // Only used for debugging
 // -----------------------------------------------------------------------------------------------
 
-float UTILS_UNUSED CubemapSH::Legendre(ssize_t l, ssize_t m, float x) {
+UTILS_UNUSED float CubemapSH::Legendre(ssize_t l, ssize_t m, float x) {
     // evaluate an Associated Legendre Polynomial P(l,m,x) at x
     float pmm = 1.0;
     if (m > 0) {
@@ -711,7 +711,7 @@ float UTILS_UNUSED CubemapSH::Legendre(ssize_t l, ssize_t m, float x) {
 }
 
 // Only used for debugging
-float UTILS_UNUSED CubemapSH::TSH(int l, int m, const float3& d) {
+UTILS_UNUSED float CubemapSH::TSH(int l, int m, const float3& d) {
     if (l==0 && m==0) {
         return 1 / (2*sqrt(F_PI));
     } else if (l==1 && m==-1) {
@@ -734,7 +734,7 @@ float UTILS_UNUSED CubemapSH::TSH(int l, int m, const float3& d) {
     return 0;
 }
 
-void UTILS_UNUSED CubemapSH::printShBase(std::ostream& out, int l, int m) {
+UTILS_UNUSED void CubemapSH::printShBase(std::ostream& out, int l, int m) {
     if (l<3 && std::abs(m) <= l) {
         const char* d = nullptr;
         float c = 0;
diff --git a/libs/imageio/src/ImageEncoder.cpp b/libs/imageio/src/ImageEncoder.cpp
index 9f83c6c6..6593581e 100644
--- a/libs/imageio/src/ImageEncoder.cpp
+++ b/libs/imageio/src/ImageEncoder.cpp
@@ -867,39 +867,39 @@ const uint32_t DDS_FOURCC_DX10 = 0x30315844; // "DX10"
 
 #pragma pack(push, 1)
 struct DDS_PIXELFORMAT {
-    uint32_t UTILS_UNUSED dwSize;
+    UTILS_UNUSED uint32_t dwSize;
     uint32_t              dwFlags;
-    uint32_t UTILS_UNUSED dwFourCC;
-    uint32_t UTILS_UNUSED dwRGBBitCount;
-    uint32_t UTILS_UNUSED dwRBitMask;
-    uint32_t UTILS_UNUSED dwGBitMask;
-    uint32_t UTILS_UNUSED dwBBitMask;
-    uint32_t UTILS_UNUSED dwABitMask;
+    UTILS_UNUSED uint32_t dwFourCC;
+    UTILS_UNUSED uint32_t dwRGBBitCount;
+    UTILS_UNUSED uint32_t dwRBitMask;
+    UTILS_UNUSED uint32_t dwGBitMask;
+    UTILS_UNUSED uint32_t dwBBitMask;
+    UTILS_UNUSED uint32_t dwABitMask;
 };
 
 struct DDS_HEADER {
-    uint32_t        UTILS_UNUSED dwSize;
+    UTILS_UNUSED uint32_t dwSize;
     uint32_t                     dwFlags;
-    uint32_t        UTILS_UNUSED dwHeight;
-    uint32_t        UTILS_UNUSED dwWidth;
-    uint32_t        UTILS_UNUSED dwPitchOrLinearSize;
-    uint32_t        UTILS_UNUSED dwDepth;
-    uint32_t        UTILS_UNUSED dwMipMapCount;
-    uint32_t        UTILS_UNUSED dwReserved1[11];
-    DDS_PIXELFORMAT UTILS_UNUSED ddspf;
-    uint32_t        UTILS_UNUSED dwCaps;
-    uint32_t        UTILS_UNUSED dwCaps2;
-    uint32_t        UTILS_UNUSED dwCaps3;
-    uint32_t        UTILS_UNUSED dwCaps4;
-    uint32_t        UTILS_UNUSED dwReserved2;
+    UTILS_UNUSED uint32_t dwHeight;
+    UTILS_UNUSED uint32_t dwWidth;
+    UTILS_UNUSED uint32_t dwPitchOrLinearSize;
+    UTILS_UNUSED uint32_t dwDepth;
+    UTILS_UNUSED uint32_t dwMipMapCount;
+    UTILS_UNUSED uint32_t dwReserved1[11];
+    UTILS_UNUSED DDS_PIXELFORMAT ddspf;
+    UTILS_UNUSED uint32_t dwCaps;
+    UTILS_UNUSED uint32_t dwCaps2;
+    UTILS_UNUSED uint32_t dwCaps3;
+    UTILS_UNUSED uint32_t dwCaps4;
+    UTILS_UNUSED uint32_t dwReserved2;
 };
 
 struct DDS_HEADER_DXT10 {
     uint32_t              dxgiFormat;
-    uint32_t UTILS_UNUSED resourceDimension;
-    uint32_t UTILS_UNUSED miscFlag;
-    uint32_t UTILS_UNUSED arraySize;
-    uint32_t UTILS_UNUSED miscFlags2;
+    UTILS_UNUSED uint32_t resourceDimension;
+    UTILS_UNUSED uint32_t miscFlag;
+    UTILS_UNUSED uint32_t arraySize;
+    UTILS_UNUSED uint32_t miscFlags2;
 };
 #pragma pack(pop)
 
diff --git a/libs/utils/include/utils/StructureOfArrays.h b/libs/utils/include/utils/StructureOfArrays.h
index d92a45f4..2e15150d 100644
--- a/libs/utils/include/utils/StructureOfArrays.h
+++ b/libs/utils/include/utils/StructureOfArrays.h
@@ -742,7 +742,7 @@ typename StructureOfArraysBase<Allocator, Elements...>::IteratorValueRef&
 StructureOfArraysBase<Allocator, Elements...>::IteratorValueRef::assign(
         IteratorValue const& rhs, std::index_sequence<Is...>) {
     // implements IteratorValueRef& IteratorValueRef::operator=(IteratorValue const& rhs)
-    auto UTILS_UNUSED l = { (soa->elementAt<Is>(index) = std::get<Is>(rhs.elements), 0)... };
+    UTILS_UNUSED auto l = { (soa->elementAt<Is>(index) = std::get<Is>(rhs.elements), 0)... };
     return *this;
 }
 
@@ -751,7 +751,7 @@ template<size_t... Is>
 typename StructureOfArraysBase<Allocator, Elements...>::IteratorValueRef&
 StructureOfArraysBase<Allocator, Elements...>::IteratorValueRef::assign(
         Structure const& rhs, std::index_sequence<Is...>) {
-    auto UTILS_UNUSED l = {(soa->template elementAt<Is>(index) = std::get<Is>(rhs), 0)...};
+    UTILS_UNUSED auto l = {(soa->template elementAt<Is>(index) = std::get<Is>(rhs), 0)...};
     return *this;
 }
 
@@ -760,7 +760,7 @@ template<size_t... Is>
 typename StructureOfArraysBase<Allocator, Elements...>::IteratorValueRef&
 StructureOfArraysBase<Allocator, Elements...>::IteratorValueRef::assign(
         Structure&& rhs, std::index_sequence<Is...>) noexcept {
-    auto UTILS_UNUSED l = {(soa->template elementAt<Is>(index) = std::move(std::get<Is>(rhs)), 0)...};
+    UTILS_UNUSED auto l = {(soa->template elementAt<Is>(index) = std::move(std::get<Is>(rhs)), 0)...};
     return *this;
 }
 
@@ -770,7 +770,7 @@ typename StructureOfArraysBase<Allocator, Elements...>::IteratorValueRef&
 StructureOfArraysBase<Allocator, Elements...>::IteratorValueRef::assign(
         IteratorValue&& rhs, std::index_sequence<Is...>) noexcept {
     // implements IteratorValueRef& IteratorValueRef::operator=(IteratorValue&& rhs) noexcept
-    auto UTILS_UNUSED l = {
+    UTILS_UNUSED auto l = {
             (soa->elementAt<Is>(index) = std::move(std::get<Is>(rhs.elements)), 0)... };
     return *this;
 }
diff --git a/libs/utils/src/CallStack.cpp b/libs/utils/src/CallStack.cpp
index 798fd642..be5f15d4 100644
--- a/libs/utils/src/CallStack.cpp
+++ b/libs/utils/src/CallStack.cpp
@@ -92,7 +92,7 @@ void CallStack::update(size_t ignore) noexcept {
     update_gcc(ignore);
 }
 
-void CallStack::update_gcc(size_t UTILS_UNUSED ignore) noexcept {
+void CallStack::update_gcc(UTILS_UNUSED size_t ignore) noexcept {
     // reset the object
     ssize_t size = 0;
 
@@ -140,7 +140,7 @@ CString CallStack::demangleTypeName(const char* mangled) {
 
 // ------------------------------------------------------------------------------------------------
 
-io::ostream& operator<<(io::ostream& stream, CallStack const& UTILS_UNUSED callstack) {
+io::ostream& operator<<(io::ostream& stream, UTILS_UNUSED CallStack const& callstack) {
 #if HAS_EXECINFO
     size_t const size = callstack.getFrameCount();
     char buf[1024];
diff --git a/third_party/getopt/src/getopt.c b/third_party/getopt/src/getopt.c
index cf2984af..1dacef63 100644
--- a/third_party/getopt/src/getopt.c
+++ b/third_party/getopt/src/getopt.c
@@ -1,5 +1,6 @@
 #ifdef _WIN32
 #include <windows.h>
+#include <io.h>
 #else
 #include <unistd.h>
 #endif
diff --git a/tools/cmgen/src/cmgen.cpp b/tools/cmgen/src/cmgen.cpp
index 722e5737..288be3ce 100644
--- a/tools/cmgen/src/cmgen.cpp
+++ b/tools/cmgen/src/cmgen.cpp
@@ -131,7 +131,7 @@ static void outputSh(std::ostream& out, const std::unique_ptr<filament::math::fl
         size_t numBands);
 static void outputBinarySh(std::ostream& out, const std::unique_ptr<filament::math::float3[]>& sh,
         size_t numBands);
-static void UTILS_UNUSED outputSpectrum(std::ostream& out,
+UTILS_UNUSED static void outputSpectrum(std::ostream& out,
         const std::unique_ptr<filament::math::float3[]>& sh, size_t numBands);
 static void saveImage(const std::string& path, ImageEncoder::Format format, const Image& image,
         const std::string& compression);
@@ -846,7 +846,7 @@ void outputBinarySh(std::ostream& out,
 }
 
 
-void UTILS_UNUSED outputSpectrum(std::ostream& out,
+UTILS_UNUSED void outputSpectrum(std::ostream& out,
         const std::unique_ptr<filament::math::float3[]>& sh, size_t numBands) {
     // We assume a symetrical function (i.e. m!=0 terms are zero)
     for (ssize_t l = 0; l < numBands; l++) {

diff --git a/third_party/spirv-cross/CMakeLists.txt b/third_party/spirv-cross/CMakeLists.txt
--- a/third_party/spirv-cross/CMakeLists.txt
+++ b/third_party/spirv-cross/CMakeLists.txt
@@ -30,3 +30,7 @@
 cmake_minimum_required(VERSION 3.10)
-set(CMAKE_CXX_STANDARD 11)
+if (WIN32)
+	set(CMAKE_CXX_STANDARD 17)
+else()
+	set(CMAKE_CXX_STANDARD 11)
+endif()
 set(CMAKE_CXX_EXTENSIONS OFF)

diff --git a/third_party/spirv-cross/tnt/CMakeLists.txt b/third_party/spirv-cross/tnt/CMakeLists.txt
--- a/third_party/spirv-cross/tnt/CMakeLists.txt
+++ b/third_party/spirv-cross/tnt/CMakeLists.txt
@@ -38,4 +38,8 @@
 # However, we require the C++11 dialect.
 if (NOT "${MSVC}")
-  set(spirv-compiler-options ${spirv-compiler-options} -std=c++11 -Wall -Wextra -Werror -Wshadow)
+  if (WIN32)
+    set(spirv-compiler-options ${spirv-compiler-options} -std=c++17 -Wall -Wextra -Werror -Wshadow)
+  else()
+    set(spirv-compiler-options ${spirv-compiler-options} -std=c++11 -Wall -Wextra -Werror -Wshadow)
+  endif()
   set(spirv-compiler-defines ${spirv-compiler-defines} __STDC_LIMIT_MACROS)

diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt
--- a/filament/CMakeLists.txt
+++ b/filament/CMakeLists.txt
@@ -793,5 +793,8 @@
             -Wweak-vtables -Wnon-virtual-dtor -Wclass-varargs -Wimplicit-fallthrough
             -Wover-aligned
             -Werror
     )
+    if (WIN32)
+        list(APPEND FILAMENT_WARNINGS -Wno-error=cast-function-type-mismatch -Wno-error=unused-variable -Wno-error=microsoft-unqualified-friend)
+    endif()
 endif()

diff --git a/filament/backend/CMakeLists.txt b/filament/backend/CMakeLists.txt
--- a/filament/backend/CMakeLists.txt
+++ b/filament/backend/CMakeLists.txt
@@ -525,3 +525,7 @@
 endif()
 
+if (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+    list(APPEND FILAMENT_WARNINGS -Wno-error=cast-function-type-mismatch -Wno-error=unused-variable -Wno-error=microsoft-unqualified-friend)
+endif()
+
 if (APPLE)

