diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/basis_universal/SCsub | 4 | ||||
-rw-r--r-- | modules/basis_universal/image_compress_basisu.cpp | 206 | ||||
-rw-r--r-- | modules/basis_universal/image_compress_basisu.h | 9 | ||||
-rw-r--r-- | modules/basis_universal/patches/external-jpgd.patch | 13 | ||||
-rw-r--r-- | modules/betsy/SCsub | 1 | ||||
-rw-r--r-- | modules/betsy/bc4.glsl | 151 | ||||
-rw-r--r-- | modules/betsy/image_compress_betsy.cpp | 80 | ||||
-rw-r--r-- | modules/betsy/image_compress_betsy.h | 7 | ||||
-rw-r--r-- | modules/gltf/gltf_document.cpp | 6 | ||||
-rw-r--r-- | modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0301.cs | 13 | ||||
-rw-r--r-- | modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs | 2 | ||||
-rw-r--r-- | modules/navigation/nav_map.cpp | 22 |
12 files changed, 394 insertions, 120 deletions
diff --git a/modules/basis_universal/SCsub b/modules/basis_universal/SCsub index 9bea0a0ca9..e201452385 100644 --- a/modules/basis_universal/SCsub +++ b/modules/basis_universal/SCsub @@ -14,6 +14,8 @@ thirdparty_obj = [] thirdparty_dir = "#thirdparty/basis_universal/" # Sync list with upstream CMakeLists.txt encoder_sources = [ + "3rdparty/android_astc_decomp.cpp", + "basisu_astc_hdr_enc.cpp", "basisu_backend.cpp", "basisu_basis_file.cpp", "basisu_bc7enc.cpp", @@ -45,6 +47,8 @@ else: if env["builtin_zstd"]: env_basisu.Prepend(CPPPATH=["#thirdparty/zstd"]) +env_basisu.Prepend(CPPPATH=["#thirdparty/tinyexr"]) + if env.dev_build: env_basisu.Append(CPPDEFINES=[("BASISU_DEVEL_MESSAGES", 1), ("BASISD_ENABLE_DEBUG_FLAGS", 1)]) diff --git a/modules/basis_universal/image_compress_basisu.cpp b/modules/basis_universal/image_compress_basisu.cpp index ab20d00b5b..d48ea363a7 100644 --- a/modules/basis_universal/image_compress_basisu.cpp +++ b/modules/basis_universal/image_compress_basisu.cpp @@ -30,6 +30,8 @@ #include "image_compress_basisu.h" +#include "core/os/os.h" +#include "core/string/print_string.h" #include "servers/rendering_server.h" #include <transcoder/basisu_transcoder.h> @@ -46,9 +48,48 @@ void basis_universal_init() { } #ifdef TOOLS_ENABLED +template <typename T> +inline void _basisu_pad_mipmap(const uint8_t *p_image_mip_data, Vector<uint8_t> &r_mip_data_padded, int p_next_width, int p_next_height, int p_width, int p_height, int64_t p_size) { + // Source mip's data interpreted as 32-bit RGBA blocks to help with copying pixel data. + const T *mip_src_data = reinterpret_cast<const T *>(p_image_mip_data); + + // Reserve space in the padded buffer. + r_mip_data_padded.resize(p_next_width * p_next_height * sizeof(T)); + T *data_padded_ptr = reinterpret_cast<T *>(r_mip_data_padded.ptrw()); + + // Pad mipmap to the nearest block by smearing. + int x = 0, y = 0; + for (y = 0; y < p_height; y++) { + for (x = 0; x < p_width; x++) { + data_padded_ptr[p_next_width * y + x] = mip_src_data[p_width * y + x]; + } + + // First, smear in x. + for (; x < p_next_width; x++) { + data_padded_ptr[p_next_width * y + x] = data_padded_ptr[p_next_width * y + x - 1]; + } + } + + // Then, smear in y. + for (; y < p_next_height; y++) { + for (x = 0; x < p_next_width; x++) { + data_padded_ptr[p_next_width * y + x] = data_padded_ptr[p_next_width * y + x - p_next_width]; + } + } +} + Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedChannels p_channels) { + uint64_t start_time = OS::get_singleton()->get_ticks_msec(); + Ref<Image> image = p_image->duplicate(); - image->convert(Image::FORMAT_RGBA8); + bool is_hdr = false; + + if (image->get_format() <= Image::FORMAT_RGB565) { + image->convert(Image::FORMAT_RGBA8); + } else if (image->get_format() <= Image::FORMAT_RGBE9995) { + image->convert(Image::FORMAT_RGBAF); + is_hdr = true; + } basisu::basis_compressor_params params; @@ -74,32 +115,42 @@ Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedCha basisu::job_pool job_pool(OS::get_singleton()->get_processor_count()); params.m_pJob_pool = &job_pool; - BasisDecompressFormat decompress_format = BASIS_DECOMPRESS_RG; - switch (p_channels) { - case Image::USED_CHANNELS_L: { - decompress_format = BASIS_DECOMPRESS_RGB; - } break; - case Image::USED_CHANNELS_LA: { - params.m_force_alpha = true; - decompress_format = BASIS_DECOMPRESS_RGBA; - } break; - case Image::USED_CHANNELS_R: { - decompress_format = BASIS_DECOMPRESS_R; - } break; - case Image::USED_CHANNELS_RG: { - params.m_force_alpha = true; - image->convert_rg_to_ra_rgba8(); - decompress_format = BASIS_DECOMPRESS_RG; - } break; - case Image::USED_CHANNELS_RGB: { - decompress_format = BASIS_DECOMPRESS_RGB; - } break; - case Image::USED_CHANNELS_RGBA: { - params.m_force_alpha = true; - decompress_format = BASIS_DECOMPRESS_RGBA; - } break; + BasisDecompressFormat decompress_format = BASIS_DECOMPRESS_MAX; + + if (is_hdr) { + decompress_format = BASIS_DECOMPRESS_HDR_RGB; + params.m_hdr = true; + params.m_uastc_hdr_options.set_quality_level(0); + + } else { + switch (p_channels) { + case Image::USED_CHANNELS_L: { + decompress_format = BASIS_DECOMPRESS_RGB; + } break; + case Image::USED_CHANNELS_LA: { + params.m_force_alpha = true; + decompress_format = BASIS_DECOMPRESS_RGBA; + } break; + case Image::USED_CHANNELS_R: { + decompress_format = BASIS_DECOMPRESS_R; + } break; + case Image::USED_CHANNELS_RG: { + params.m_force_alpha = true; + image->convert_rg_to_ra_rgba8(); + decompress_format = BASIS_DECOMPRESS_RG; + } break; + case Image::USED_CHANNELS_RGB: { + decompress_format = BASIS_DECOMPRESS_RGB; + } break; + case Image::USED_CHANNELS_RGBA: { + params.m_force_alpha = true; + decompress_format = BASIS_DECOMPRESS_RGBA; + } break; + } } + ERR_FAIL_COND_V(decompress_format == BASIS_DECOMPRESS_MAX, Vector<uint8_t>()); + // Copy the source image data with mipmaps into BasisU. { const int orig_width = image->get_width(); @@ -113,9 +164,10 @@ Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedCha Vector<uint8_t> image_data = image->get_data(); basisu::vector<basisu::image> basisu_mipmaps; + basisu::vector<basisu::imagef> basisu_mipmaps_hdr; // Buffer for storing padded mipmap data. - Vector<uint32_t> mip_data_padded; + Vector<uint8_t> mip_data_padded; for (int32_t i = 0; i <= image->get_mipmap_count(); i++) { int64_t ofs, size; @@ -126,31 +178,10 @@ Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedCha // Pad the mipmap's data if its resolution isn't divisible by 4. if (image->has_mipmaps() && !is_res_div_4 && (width > 2 && height > 2) && (width != next_width || height != next_height)) { - // Source mip's data interpreted as 32-bit RGBA blocks to help with copying pixel data. - const uint32_t *mip_src_data = reinterpret_cast<const uint32_t *>(image_mip_data); - - // Reserve space in the padded buffer. - mip_data_padded.resize(next_width * next_height); - uint32_t *data_padded_ptr = mip_data_padded.ptrw(); - - // Pad mipmap to the nearest block by smearing. - int x = 0, y = 0; - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - data_padded_ptr[next_width * y + x] = mip_src_data[width * y + x]; - } - - // First, smear in x. - for (; x < next_width; x++) { - data_padded_ptr[next_width * y + x] = data_padded_ptr[next_width * y + x - 1]; - } - } - - // Then, smear in y. - for (; y < next_height; y++) { - for (x = 0; x < next_width; x++) { - data_padded_ptr[next_width * y + x] = data_padded_ptr[next_width * y + x - next_width]; - } + if (is_hdr) { + _basisu_pad_mipmap<BasisRGBAF>(image_mip_data, mip_data_padded, next_width, next_height, width, height, size); + } else { + _basisu_pad_mipmap<uint32_t>(image_mip_data, mip_data_padded, next_width, next_height, width, height, size); } // Override the image_mip_data pointer with our temporary Vector. @@ -159,7 +190,7 @@ Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedCha // Override the mipmap's properties. width = next_width; height = next_height; - size = mip_data_padded.size() * 4; + size = mip_data_padded.size(); } // Get the next mipmap's resolution. @@ -167,44 +198,61 @@ Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedCha next_height /= 2; // Copy the source mipmap's data to a BasisU image. - basisu::image basisu_image(width, height); - memcpy(basisu_image.get_ptr(), image_mip_data, size); + if (is_hdr) { + basisu::imagef basisu_image(width, height); + memcpy(reinterpret_cast<uint8_t *>(basisu_image.get_ptr()), image_mip_data, size); + + if (i == 0) { + params.m_source_images_hdr.push_back(basisu_image); + } else { + basisu_mipmaps_hdr.push_back(basisu_image); + } - if (i == 0) { - params.m_source_images.push_back(basisu_image); } else { - basisu_mipmaps.push_back(basisu_image); + basisu::image basisu_image(width, height); + memcpy(basisu_image.get_ptr(), image_mip_data, size); + + if (i == 0) { + params.m_source_images.push_back(basisu_image); + } else { + basisu_mipmaps.push_back(basisu_image); + } } } - params.m_source_mipmap_images.push_back(basisu_mipmaps); + if (is_hdr) { + params.m_source_mipmap_images_hdr.push_back(basisu_mipmaps_hdr); + } else { + params.m_source_mipmap_images.push_back(basisu_mipmaps); + } } // Encode the image data. - Vector<uint8_t> basisu_data; - basisu::basis_compressor compressor; compressor.init(params); int basisu_err = compressor.process(); - ERR_FAIL_COND_V(basisu_err != basisu::basis_compressor::cECSuccess, basisu_data); + ERR_FAIL_COND_V(basisu_err != basisu::basis_compressor::cECSuccess, Vector<uint8_t>()); - const basisu::uint8_vec &basisu_out = compressor.get_output_basis_file(); - basisu_data.resize(basisu_out.size() + 4); + const basisu::uint8_vec &basisu_encoded = compressor.get_output_basis_file(); - // Copy the encoded data to the buffer. - { - uint8_t *wb = basisu_data.ptrw(); - *(uint32_t *)wb = decompress_format; + Vector<uint8_t> basisu_data; + basisu_data.resize(basisu_encoded.size() + 4); + uint8_t *basisu_data_ptr = basisu_data.ptrw(); - memcpy(wb + 4, basisu_out.get_ptr(), basisu_out.size()); - } + // Copy the encoded BasisU data into the output buffer. + *(uint32_t *)basisu_data_ptr = decompress_format; + memcpy(basisu_data_ptr + 4, basisu_encoded.get_ptr(), basisu_encoded.size()); + + print_verbose(vformat("BasisU: Encoding a %dx%d image with %d mipmaps took %d ms.", p_image->get_width(), p_image->get_height(), p_image->get_mipmap_count(), OS::get_singleton()->get_ticks_msec() - start_time)); return basisu_data; } #endif // TOOLS_ENABLED Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) { + uint64_t start_time = OS::get_singleton()->get_ticks_msec(); + Ref<Image> image; ERR_FAIL_NULL_V_MSG(p_data, image, "Cannot unpack invalid BasisUniversal data."); @@ -320,6 +368,23 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) { } } break; + case BASIS_DECOMPRESS_HDR_RGB: { + if (bptc_supported) { + basisu_format = basist::transcoder_texture_format::cTFBC6H; + image_format = Image::FORMAT_BPTC_RGBFU; + } else if (astc_supported) { + basisu_format = basist::transcoder_texture_format::cTFASTC_HDR_4x4_RGBA; + image_format = Image::FORMAT_ASTC_4x4_HDR; + } else { + // No supported VRAM compression formats, decompress. + basisu_format = basist::transcoder_texture_format::cTFRGB_9E5; + image_format = Image::FORMAT_RGBE9995; + } + + } break; + default: { + ERR_FAIL_V(image); + } break; } src_ptr += 4; @@ -371,6 +436,9 @@ Ref<Image> basis_universal_unpacker_ptr(const uint8_t *p_data, int p_size) { } } + print_verbose(vformat("BasisU: Transcoding a %dx%d image with %d mipmaps into %s took %d ms.", + image->get_width(), image->get_height(), image->get_mipmap_count(), Image::get_format_name(image_format), OS::get_singleton()->get_ticks_msec() - start_time)); + return image; } diff --git a/modules/basis_universal/image_compress_basisu.h b/modules/basis_universal/image_compress_basisu.h index 5e36d448f6..81c8511f60 100644 --- a/modules/basis_universal/image_compress_basisu.h +++ b/modules/basis_universal/image_compress_basisu.h @@ -39,11 +39,20 @@ enum BasisDecompressFormat { BASIS_DECOMPRESS_RGBA, BASIS_DECOMPRESS_RG_AS_RA, BASIS_DECOMPRESS_R, + BASIS_DECOMPRESS_HDR_RGB, + BASIS_DECOMPRESS_MAX }; void basis_universal_init(); #ifdef TOOLS_ENABLED +struct BasisRGBAF { + uint32_t r; + uint32_t g; + uint32_t b; + uint32_t a; +}; + Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedChannels p_channels); #endif diff --git a/modules/basis_universal/patches/external-jpgd.patch b/modules/basis_universal/patches/external-jpgd.patch deleted file mode 100644 index 7a805d00cb..0000000000 --- a/modules/basis_universal/patches/external-jpgd.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/thirdparty/basis_universal/encoder/basisu_enc.cpp b/thirdparty/basis_universal/encoder/basisu_enc.cpp -index c431ceaf12..e87dd636a2 100644 ---- a/thirdparty/basis_universal/encoder/basisu_enc.cpp -+++ b/thirdparty/basis_universal/encoder/basisu_enc.cpp -@@ -409,7 +409,7 @@ namespace basisu - bool load_jpg(const char *pFilename, image& img) - { - int width = 0, height = 0, actual_comps = 0; -- uint8_t *pImage_data = jpgd::decompress_jpeg_image_from_file(pFilename, &width, &height, &actual_comps, 4, jpgd::jpeg_decoder::cFlagLinearChromaFiltering); -+ uint8_t *pImage_data = jpgd::decompress_jpeg_image_from_file(pFilename, &width, &height, &actual_comps, 4, jpgd::jpeg_decoder::cFlagBoxChromaFiltering); - if (!pImage_data) - return false; - diff --git a/modules/betsy/SCsub b/modules/betsy/SCsub index 2735116cc3..621ba58ae3 100644 --- a/modules/betsy/SCsub +++ b/modules/betsy/SCsub @@ -7,6 +7,7 @@ Import("env_modules") env_betsy = env_modules.Clone() env_betsy.GLSL_HEADER("bc6h.glsl") env_betsy.GLSL_HEADER("bc1.glsl") +env_betsy.GLSL_HEADER("bc4.glsl") env_betsy.Depends(Glob("*.glsl.gen.h"), ["#glsl_builders.py"]) # Thirdparty source files diff --git a/modules/betsy/bc4.glsl b/modules/betsy/bc4.glsl new file mode 100644 index 0000000000..b7a5f6a686 --- /dev/null +++ b/modules/betsy/bc4.glsl @@ -0,0 +1,151 @@ +#[versions] + +unsigned = ""; +signed = "#define SNORM"; + +#[compute] +#version 450 + +#include "CrossPlatformSettings_piece_all.glsl" +#include "UavCrossPlatform_piece_all.glsl" + +#VERSION_DEFINES + +shared float2 g_minMaxValues[4u * 4u * 4u]; +shared uint2 g_mask[4u * 4u]; + +layout(binding = 0) uniform sampler2D srcTex; +layout(binding = 1, rg32ui) uniform restrict writeonly uimage2D dstTexture; + +layout(push_constant, std430) uniform Params { + uint p_channelIdx; + uint p_padding[3]; +} +params; + +layout(local_size_x = 4, // + local_size_y = 4, // + local_size_z = 4) in; + +/// Each block is 16 pixels +/// Each thread works on 4 pixels +/// Therefore each block needs 4 threads, generating 8 masks +/// At the end these 8 masks get merged into 2 and results written to output +/// +/// **Q: Why 4 pixels per thread? Why not 1 pixel per thread? Why not 2? Why not 16?** +/// +/// A: It's a sweetspot. +/// - Very short threads cannot fill expensive GPUs with enough work (dispatch bound) +/// - Lots of threads means lots of synchronization (e.g. evaluating min/max, merging masks) +/// overhead, and also more LDS usage which reduces occupancy. +/// - Long threads (e.g. 1 thread per block) misses parallelism opportunities +void main() { + float minVal, maxVal; + float4 srcPixel; + + const uint blockThreadId = gl_LocalInvocationID.x; + + const uint2 pixelsToLoadBase = gl_GlobalInvocationID.yz << 2u; + + for (uint i = 0u; i < 4u; ++i) { + const uint2 pixelsToLoad = pixelsToLoadBase + uint2(i, blockThreadId); + + const float4 value = OGRE_Load2D(srcTex, int2(pixelsToLoad), 0).xyzw; + srcPixel[i] = params.p_channelIdx == 0 ? value.x : (params.p_channelIdx == 1 ? value.y : value.w); + srcPixel[i] *= 255.0f; + } + + minVal = min3(srcPixel.x, srcPixel.y, srcPixel.z); + maxVal = max3(srcPixel.x, srcPixel.y, srcPixel.z); + minVal = min(minVal, srcPixel.w); + maxVal = max(maxVal, srcPixel.w); + + const uint minMaxIdxBase = (gl_LocalInvocationID.z << 4u) + (gl_LocalInvocationID.y << 2u); + const uint maskIdxBase = (gl_LocalInvocationID.z << 2u) + gl_LocalInvocationID.y; + + g_minMaxValues[minMaxIdxBase + blockThreadId] = float2(minVal, maxVal); + g_mask[maskIdxBase] = uint2(0u, 0u); + + memoryBarrierShared(); + barrier(); + + // Have all 4 threads in the block grab the min/max value by comparing what all 4 threads uploaded + for (uint i = 0u; i < 4u; ++i) { + minVal = min(g_minMaxValues[minMaxIdxBase + i].x, minVal); + maxVal = max(g_minMaxValues[minMaxIdxBase + i].y, maxVal); + } + + // determine bias and emit color indices + // given the choice of maxVal/minVal, these indices are optimal: + // http://fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination/ + float dist = maxVal - minVal; + float dist4 = dist * 4.0f; + float dist2 = dist * 2.0f; + float bias = (dist < 8) ? (dist - 1) : (trunc(dist * 0.5f) + 2); + bias -= minVal * 7; + + uint mask0 = 0u, mask1 = 0u; + + for (uint i = 0u; i < 4u; ++i) { + float a = srcPixel[i] * 7.0f + bias; + + int ind = 0; + + // select index. this is a "linear scale" lerp factor between 0 (val=min) and 7 (val=max). + if (a >= dist4) { + ind = 4; + a -= dist4; + } + + if (a >= dist2) { + ind += 2; + a -= dist2; + } + + if (a >= dist) + ind += 1; + + // turn linear scale into DXT index (0/1 are extremal pts) + ind = -ind & 7; + ind ^= (2 > ind) ? 1 : 0; + + // write index + const uint bits = 16u + ((blockThreadId << 2u) + i) * 3u; + if (bits < 32u) { + mask0 |= uint(ind) << bits; + if (bits + 3u > 32u) { + mask1 |= uint(ind) >> (32u - bits); + } + } else { + mask1 |= uint(ind) << (bits - 32u); + } + } + + if (mask0 != 0u) + atomicOr(g_mask[maskIdxBase].x, mask0); + if (mask1 != 0u) + atomicOr(g_mask[maskIdxBase].y, mask1); + + memoryBarrierShared(); + barrier(); + + if (blockThreadId == 0u) { + // Save data + uint2 outputBytes; + +#ifdef SNORM + outputBytes.x = + packSnorm4x8(float4(maxVal * (1.0f / 255.0f) * 2.0f - 1.0f, + minVal * (1.0f / 255.0f) * 2.0f - 1.0f, 0.0f, 0.0f)); +#else + outputBytes.x = packUnorm4x8( + float4(maxVal * (1.0f / 255.0f), minVal * (1.0f / 255.0f), 0.0f, 0.0f)); +#endif + + outputBytes.x |= g_mask[maskIdxBase].x; + outputBytes.y = g_mask[maskIdxBase].y; + + uint2 dstUV = gl_GlobalInvocationID.yz; + imageStore(dstTexture, int2(dstUV), uint4(outputBytes.xy, 0u, 0u)); + } +} diff --git a/modules/betsy/image_compress_betsy.cpp b/modules/betsy/image_compress_betsy.cpp index 7b4d8b3dfb..6bfe01f65c 100644 --- a/modules/betsy/image_compress_betsy.cpp +++ b/modules/betsy/image_compress_betsy.cpp @@ -35,6 +35,7 @@ #include "betsy_bc1.h" #include "bc1.glsl.gen.h" +#include "bc4.glsl.gen.h" #include "bc6h.glsl.gen.h" static Mutex betsy_mutex; @@ -165,6 +166,10 @@ static String get_shader_name(BetsyFormat p_format) { case BETSY_FORMAT_BC3: return "BC3"; + case BETSY_FORMAT_BC4_SIGNED: + case BETSY_FORMAT_BC4_UNSIGNED: + return "BC4"; + case BETSY_FORMAT_BC6_SIGNED: case BETSY_FORMAT_BC6_UNSIGNED: return "BC6"; @@ -202,6 +207,12 @@ Error BetsyCompressor::_compress(BetsyFormat p_format, Image *r_img) { dest_format = Image::FORMAT_DXT1; break; + case BETSY_FORMAT_BC4_UNSIGNED: + version = "unsigned"; + dst_rd_format = RD::DATA_FORMAT_R32G32_UINT; + dest_format = Image::FORMAT_RGTC_R; + break; + case BETSY_FORMAT_BC6_SIGNED: version = "signed"; dst_rd_format = RD::DATA_FORMAT_R32G32B32A32_UINT; @@ -235,8 +246,13 @@ Error BetsyCompressor::_compress(BetsyFormat p_format, Image *r_img) { err = source->parse_versions_from_text(bc1_shader_glsl); break; - case BETSY_FORMAT_BC6_UNSIGNED: + case BETSY_FORMAT_BC4_SIGNED: + case BETSY_FORMAT_BC4_UNSIGNED: + err = source->parse_versions_from_text(bc4_shader_glsl); + break; + case BETSY_FORMAT_BC6_SIGNED: + case BETSY_FORMAT_BC6_UNSIGNED: err = source->parse_versions_from_text(bc6h_shader_glsl); break; @@ -430,26 +446,45 @@ Error BetsyCompressor::_compress(BetsyFormat p_format, Image *r_img) { compress_rd->compute_list_bind_compute_pipeline(compute_list, shader.pipeline); compress_rd->compute_list_bind_uniform_set(compute_list, uniform_set, 0); - if (dest_format == Image::FORMAT_BPTC_RGBFU || dest_format == Image::FORMAT_BPTC_RGBF) { - BC6PushConstant push_constant; - push_constant.sizeX = 1.0f / width; - push_constant.sizeY = 1.0f / height; - push_constant.padding[0] = 0; - push_constant.padding[1] = 0; - - compress_rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(BC6PushConstant)); - - } else { - BC1PushConstant push_constant; - push_constant.num_refines = 2; - push_constant.padding[0] = 0; - push_constant.padding[1] = 0; - push_constant.padding[2] = 0; - - compress_rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(BC1PushConstant)); + switch (dest_format) { + case Image::FORMAT_BPTC_RGBFU: + case Image::FORMAT_BPTC_RGBF: { + BC6PushConstant push_constant; + push_constant.sizeX = 1.0f / width; + push_constant.sizeY = 1.0f / height; + push_constant.padding[0] = 0; + push_constant.padding[1] = 0; + + compress_rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(BC6PushConstant)); + compress_rd->compute_list_dispatch(compute_list, get_next_multiple(width, 32) / 32, get_next_multiple(height, 32) / 32, 1); + } break; + + case Image::FORMAT_DXT1: { + BC1PushConstant push_constant; + push_constant.num_refines = 2; + push_constant.padding[0] = 0; + push_constant.padding[1] = 0; + push_constant.padding[2] = 0; + + compress_rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(BC1PushConstant)); + compress_rd->compute_list_dispatch(compute_list, get_next_multiple(width, 32) / 32, get_next_multiple(height, 32) / 32, 1); + } break; + + case Image::FORMAT_RGTC_R: { + BC4PushConstant push_constant; + push_constant.channel_idx = 0; + push_constant.padding[0] = 0; + push_constant.padding[1] = 0; + push_constant.padding[2] = 0; + + compress_rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(BC4PushConstant)); + compress_rd->compute_list_dispatch(compute_list, 1, get_next_multiple(width, 16) / 16, get_next_multiple(height, 16) / 16); + } break; + + default: { + } break; } - compress_rd->compute_list_dispatch(compute_list, get_next_multiple(width, 32) / 32, get_next_multiple(height, 32) / 32, 1); compress_rd->compute_list_end(); compress_rd->submit(); @@ -511,13 +546,14 @@ Error _betsy_compress_s3tc(Image *r_img, Image::UsedChannels p_channels) { switch (p_channels) { case Image::USED_CHANNELS_RGB: - result = betsy->compress(BETSY_FORMAT_BC1_DITHER, r_img); - break; - case Image::USED_CHANNELS_L: result = betsy->compress(BETSY_FORMAT_BC1, r_img); break; + case Image::USED_CHANNELS_R: + result = betsy->compress(BETSY_FORMAT_BC4_UNSIGNED, r_img); + break; + default: break; } diff --git a/modules/betsy/image_compress_betsy.h b/modules/betsy/image_compress_betsy.h index 70e4ae85ed..4e0bf0538f 100644 --- a/modules/betsy/image_compress_betsy.h +++ b/modules/betsy/image_compress_betsy.h @@ -50,6 +50,8 @@ enum BetsyFormat { BETSY_FORMAT_BC1, BETSY_FORMAT_BC1_DITHER, BETSY_FORMAT_BC3, + BETSY_FORMAT_BC4_SIGNED, + BETSY_FORMAT_BC4_UNSIGNED, BETSY_FORMAT_BC6_SIGNED, BETSY_FORMAT_BC6_UNSIGNED, }; @@ -65,6 +67,11 @@ struct BC1PushConstant { uint32_t padding[3]; }; +struct BC4PushConstant { + uint32_t channel_idx; + uint32_t padding[3]; +}; + void free_device(); Error _betsy_compress_bptc(Image *r_img, Image::UsedChannels p_channels); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 992075e980..0a487430a3 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -613,12 +613,8 @@ Error GLTFDocument::_parse_nodes(Ref<GLTFState> p_state) { if (n.has("scale")) { node->set_scale(_arr_to_vec3(n["scale"])); } - - Transform3D godot_rest_transform; - godot_rest_transform.basis.set_quaternion_scale(node->transform.basis.get_rotation_quaternion(), node->transform.basis.get_scale()); - godot_rest_transform.origin = node->transform.origin; - node->set_additional_data("GODOT_rest_transform", godot_rest_transform); } + node->set_additional_data("GODOT_rest_transform", node->transform); if (n.has("extensions")) { Dictionary extensions = n["extensions"]; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0301.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0301.cs index 053ae36ae7..5654060d38 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0301.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/MustBeVariant.GD0301.cs @@ -395,6 +395,11 @@ public class MustBeVariantAnnotatedMethods public void MethodWithWrongAttribute() { } + + [NestedGenericTypeAttributeContainer.NestedGenericTypeAttribute<bool>()] + public void MethodWithNestedAttribute() + { + } } [GenericTypeAttribute<bool>()] @@ -657,3 +662,11 @@ public class ClassNonVariantAnnotated public class GenericTypeAttribute<[MustBeVariant] T> : Attribute { } + +public class NestedGenericTypeAttributeContainer +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public class NestedGenericTypeAttribute<[MustBeVariant] T> : Attribute + { + } +} diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs index e894e7a86c..a72a8c5880 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/MustBeVariantAnalyzer.cs @@ -135,7 +135,7 @@ namespace Godot.SourceGenerators { ITypeParameterSymbol? typeParamSymbol = parentSymbol switch { - IMethodSymbol methodSymbol when parentSyntax.Parent is AttributeSyntax && + IMethodSymbol methodSymbol when parentSyntax.Ancestors().Any(s => s is AttributeSyntax) && methodSymbol.ContainingType.TypeParameters.Length > 0 => methodSymbol.ContainingType.TypeParameters[typeArgumentIndex], diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index dd77e81b45..8df1db533d 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -480,6 +480,8 @@ void NavMap::sync() { // connection, integration and path finding. _new_pm_edge_free_count = free_edges.size(); + real_t sqr_edge_connection_margin = edge_connection_margin * edge_connection_margin; + for (int i = 0; i < free_edges.size(); i++) { const gd::Edge::Connection &free_edge = free_edges[i]; Vector3 edge_p1 = free_edge.polygon->points[free_edge.edge].pos; @@ -510,7 +512,7 @@ void NavMap::sync() { } else { other1 = other_edge_p1.lerp(other_edge_p2, (1.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio)); } - if (other1.distance_to(self1) > edge_connection_margin) { + if (other1.distance_squared_to(self1) > sqr_edge_connection_margin) { continue; } @@ -521,7 +523,7 @@ void NavMap::sync() { } else { other2 = other_edge_p1.lerp(other_edge_p2, (0.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio)); } - if (other2.distance_to(self2) > edge_connection_margin) { + if (other2.distance_squared_to(self2) > sqr_edge_connection_margin) { continue; } @@ -549,11 +551,11 @@ void NavMap::sync() { const Vector3 end = link->get_end_position(); gd::Polygon *closest_start_polygon = nullptr; - real_t closest_start_distance = link_connection_radius; + real_t closest_start_sqr_dist = link_connection_radius * link_connection_radius; Vector3 closest_start_point; gd::Polygon *closest_end_polygon = nullptr; - real_t closest_end_distance = link_connection_radius; + real_t closest_end_sqr_dist = link_connection_radius * link_connection_radius; Vector3 closest_end_point; // Create link to any polygons within the search radius of the start point. @@ -564,11 +566,11 @@ void NavMap::sync() { for (uint32_t start_point_id = 2; start_point_id < start_poly.points.size(); start_point_id += 1) { const Face3 start_face(start_poly.points[0].pos, start_poly.points[start_point_id - 1].pos, start_poly.points[start_point_id].pos); const Vector3 start_point = start_face.get_closest_point_to(start); - const real_t start_distance = start_point.distance_to(start); + const real_t sqr_dist = start_point.distance_squared_to(start); // Pick the polygon that is within our radius and is closer than anything we've seen yet. - if (start_distance <= link_connection_radius && start_distance < closest_start_distance) { - closest_start_distance = start_distance; + if (sqr_dist < closest_start_sqr_dist) { + closest_start_sqr_dist = sqr_dist; closest_start_point = start_point; closest_start_polygon = &start_poly; } @@ -581,11 +583,11 @@ void NavMap::sync() { for (uint32_t end_point_id = 2; end_point_id < end_poly.points.size(); end_point_id += 1) { const Face3 end_face(end_poly.points[0].pos, end_poly.points[end_point_id - 1].pos, end_poly.points[end_point_id].pos); const Vector3 end_point = end_face.get_closest_point_to(end); - const real_t end_distance = end_point.distance_to(end); + const real_t sqr_dist = end_point.distance_squared_to(end); // Pick the polygon that is within our radius and is closer than anything we've seen yet. - if (end_distance <= link_connection_radius && end_distance < closest_end_distance) { - closest_end_distance = end_distance; + if (sqr_dist < closest_end_sqr_dist) { + closest_end_sqr_dist = sqr_dist; closest_end_point = end_point; closest_end_polygon = &end_poly; } |