From 63d6e9c557b2d88e9385865bf2c60445d4afafc2 Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Mon, 10 Jul 2023 22:31:27 +1000 Subject: [PATCH] Add custom texture create function --- doc/classes/RenderingDevice.xml | 7 + doc/classes/RenderingServer.xml | 15 + doc/classes/Texture2DArrayRD.xml | 11 + doc/classes/Texture2DRD.xml | 17 + doc/classes/Texture3DRD.xml | 16 + doc/classes/TextureCubemapArrayRD.xml | 11 + doc/classes/TextureCubemapRD.xml | 11 + doc/classes/TextureLayeredRD.xml | 16 + drivers/gles3/storage/texture_storage.cpp | 3 + drivers/gles3/storage/texture_storage.h | 3 +- drivers/vulkan/rendering_device_vulkan.cpp | 23 + drivers/vulkan/rendering_device_vulkan.h | 1 + scene/register_scene_types.cpp | 9 + scene/resources/image_texture.cpp | 2 +- .../resources/portable_compressed_texture.cpp | 2 +- scene/resources/texture_rd.cpp | 346 ++++++++++++++ scene/resources/texture_rd.h | 153 ++++++ .../rendering/dummy/storage/texture_storage.h | 3 + .../storage_rd/texture_storage.cpp | 436 ++++++++++++++++++ .../renderer_rd/storage_rd/texture_storage.h | 24 + servers/rendering/rendering_device.cpp | 9 + servers/rendering/rendering_device.h | 2 + servers/rendering/rendering_server_default.h | 4 + servers/rendering/storage/texture_storage.h | 3 + servers/rendering_server.cpp | 3 + servers/rendering_server.h | 3 + 26 files changed, 1130 insertions(+), 3 deletions(-) create mode 100644 doc/classes/Texture2DArrayRD.xml create mode 100644 doc/classes/Texture2DRD.xml create mode 100644 doc/classes/Texture3DRD.xml create mode 100644 doc/classes/TextureCubemapArrayRD.xml create mode 100644 doc/classes/TextureCubemapRD.xml create mode 100644 doc/classes/TextureLayeredRD.xml create mode 100644 scene/resources/texture_rd.cpp create mode 100644 scene/resources/texture_rd.h diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index 40a6ad9787f..3205a331683 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -752,6 +752,13 @@ [b]Note:[/b] [param texture] requires the [constant TEXTURE_USAGE_CAN_COPY_FROM_BIT] to be retrieved. Otherwise, an error is printed and a empty [PackedByteArray] is returned. + + + + + Returns the data format used to create this texture. + + diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 868079a5166..64d54b3ba0b 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -3281,6 +3281,13 @@ [b]Note:[/b] The [param texture] must have the same width, height, depth and format as the current texture data. Otherwise, an error will be printed and the original texture won't be modified. If you need to use different width, height, depth or format, use [method texture_replace] instead. + + + + + Returns the [enum Image.Format] for the texture. + + @@ -3319,6 +3326,14 @@ [i]Deprecated.[/i] ProxyTexture was removed in Godot 4, so this method cannot be used anymore. + + + + + + Creates a new texture object based on a texture created directly on the [RenderingDevice]. If the texture contains layers, [param layer_type] is used to define the layer type. + + diff --git a/doc/classes/Texture2DArrayRD.xml b/doc/classes/Texture2DArrayRD.xml new file mode 100644 index 00000000000..b28cdd436cf --- /dev/null +++ b/doc/classes/Texture2DArrayRD.xml @@ -0,0 +1,11 @@ + + + + Texture Array for 2D that is bound to a texture created on the [RenderingDevice]. + + + This texture array class allows you to use a 2D array texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc. + + + + diff --git a/doc/classes/Texture2DRD.xml b/doc/classes/Texture2DRD.xml new file mode 100644 index 00000000000..b935a7763b5 --- /dev/null +++ b/doc/classes/Texture2DRD.xml @@ -0,0 +1,17 @@ + + + + Texture for 2D that is bound to a texture created on the [RenderingDevice]. + + + This texture class allows you to use a 2D texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc. + + + + + + + The RID of the texture object created on the [RenderingDevice]. + + + diff --git a/doc/classes/Texture3DRD.xml b/doc/classes/Texture3DRD.xml new file mode 100644 index 00000000000..f9d72b7a0fb --- /dev/null +++ b/doc/classes/Texture3DRD.xml @@ -0,0 +1,16 @@ + + + + Texture for 3D that is bound to a texture created on the [RenderingDevice]. + + + This texture class allows you to use a 3D texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc. + + + + + + The RID of the texture object created on the [RenderingDevice]. + + + diff --git a/doc/classes/TextureCubemapArrayRD.xml b/doc/classes/TextureCubemapArrayRD.xml new file mode 100644 index 00000000000..38d5010ee78 --- /dev/null +++ b/doc/classes/TextureCubemapArrayRD.xml @@ -0,0 +1,11 @@ + + + + Texture Array for Cubemaps that is bound to a texture created on the [RenderingDevice]. + + + This texture class allows you to use a cubemap array texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc. + + + + diff --git a/doc/classes/TextureCubemapRD.xml b/doc/classes/TextureCubemapRD.xml new file mode 100644 index 00000000000..bd7c897ad39 --- /dev/null +++ b/doc/classes/TextureCubemapRD.xml @@ -0,0 +1,11 @@ + + + + Texture for Cubemap that is bound to a texture created on the [RenderingDevice]. + + + This texture class allows you to use a cubemap texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc. + + + + diff --git a/doc/classes/TextureLayeredRD.xml b/doc/classes/TextureLayeredRD.xml new file mode 100644 index 00000000000..65f2d876244 --- /dev/null +++ b/doc/classes/TextureLayeredRD.xml @@ -0,0 +1,16 @@ + + + + Abstract base class for layered texture RD types. + + + Base class for [Texture2DArrayRD], [TextureCubemapRD] and [TextureCubemapArrayRD]. Cannot be used directly, but contains all the functions necessary for accessing the derived resource types. + + + + + + The RID of the texture object created on the [RenderingDevice]. + + + diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 649123cdca9..a3f230f9e2a 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -1192,6 +1192,9 @@ Size2 TextureStorage::texture_size_with_proxy(RID p_texture) { } } +void TextureStorage::texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type) { +} + RID TextureStorage::texture_get_rd_texture(RID p_texture, bool p_srgb) const { return RID(); } diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index 37d3a4fb444..bad2b31a315 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -545,11 +545,12 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) override; + virtual void texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY) override; virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override; virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override; void texture_set_data(RID p_texture, const Ref &p_image, int p_layer = 0); - Image::Format texture_get_format(RID p_texture) const; + virtual Image::Format texture_get_format(RID p_texture) const override; uint32_t texture_get_texid(RID p_texture) const; uint32_t texture_get_width(RID p_texture) const; uint32_t texture_get_height(RID p_texture) const; diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 91fe63aad13..be6f8f35807 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -2893,6 +2893,29 @@ bool RenderingDeviceVulkan::texture_is_valid(RID p_texture) { return texture_owner.owns(p_texture); } +RD::TextureFormat RenderingDeviceVulkan::texture_get_format(RID p_texture) { + _THREAD_SAFE_METHOD_ + + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, TextureFormat()); + + TextureFormat tf; + + tf.format = tex->format; + tf.width = tex->width; + tf.height = tex->height; + tf.depth = tex->depth; + tf.array_layers = tex->layers; + tf.mipmaps = tex->mipmaps; + tf.texture_type = tex->type; + tf.samples = tex->samples; + tf.usage_bits = tex->usage_flags; + tf.shareable_formats = tex->allowed_shared_formats; + tf.is_resolve_buffer = tex->is_resolve_buffer; + + return tf; +} + Size2i RenderingDeviceVulkan::texture_size(RID p_texture) { _THREAD_SAFE_METHOD_ diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 9c621c1d441..010f7c9337f 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -1082,6 +1082,7 @@ public: virtual bool texture_is_format_supported_for_usage(DataFormat p_format, BitField p_usage) const; virtual bool texture_is_shared(RID p_texture); virtual bool texture_is_valid(RID p_texture); + virtual TextureFormat texture_get_format(RID p_texture); virtual Size2i texture_size(RID p_texture); virtual uint64_t texture_get_native_handle(RID p_texture); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 1c2ed16e63c..66ada63e2d4 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -211,6 +211,7 @@ #include "scene/resources/text_line.h" #include "scene/resources/text_paragraph.h" #include "scene/resources/texture.h" +#include "scene/resources/texture_rd.h" #include "scene/resources/theme.h" #include "scene/resources/tile_set.h" #include "scene/resources/video_stream.h" @@ -887,6 +888,14 @@ void register_scene_types() { GDREGISTER_CLASS(PlaceholderCubemap); GDREGISTER_CLASS(PlaceholderCubemapArray); + // These classes are part of renderer_rd + GDREGISTER_CLASS(Texture2DRD); + GDREGISTER_ABSTRACT_CLASS(TextureLayeredRD); + GDREGISTER_CLASS(Texture2DArrayRD); + GDREGISTER_CLASS(TextureCubemapRD); + GDREGISTER_CLASS(TextureCubemapArrayRD); + GDREGISTER_CLASS(Texture3DRD); + GDREGISTER_CLASS(Animation); GDREGISTER_CLASS(AnimationLibrary); diff --git a/scene/resources/image_texture.cpp b/scene/resources/image_texture.cpp index 922e90f1ba5..ecf70d96ace 100644 --- a/scene/resources/image_texture.cpp +++ b/scene/resources/image_texture.cpp @@ -142,7 +142,7 @@ int ImageTexture::get_height() const { RID ImageTexture::get_rid() const { if (texture.is_null()) { - //we are in trouble, create something temporary + // We are in trouble, create something temporary. texture = RenderingServer::get_singleton()->texture_2d_placeholder_create(); } return texture; diff --git a/scene/resources/portable_compressed_texture.cpp b/scene/resources/portable_compressed_texture.cpp index fc4e7823f0b..a61799c7d64 100644 --- a/scene/resources/portable_compressed_texture.cpp +++ b/scene/resources/portable_compressed_texture.cpp @@ -198,7 +198,7 @@ int PortableCompressedTexture2D::get_height() const { RID PortableCompressedTexture2D::get_rid() const { if (texture.is_null()) { - //we are in trouble, create something temporary + // We are in trouble, create something temporary. texture = RenderingServer::get_singleton()->texture_2d_placeholder_create(); } return texture; diff --git a/scene/resources/texture_rd.cpp b/scene/resources/texture_rd.cpp new file mode 100644 index 00000000000..6f25af68639 --- /dev/null +++ b/scene/resources/texture_rd.cpp @@ -0,0 +1,346 @@ +/**************************************************************************/ +/* texture_rd.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "texture_rd.h" + +//////////////////////////////////////////////////////////////////////////// +// Texture2DRD + +void Texture2DRD::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture_rd_rid", "texture_rd_rid"), &Texture2DRD::set_texture_rd_rid); + ClassDB::bind_method(D_METHOD("get_texture_rd_rid"), &Texture2DRD::get_texture_rd_rid); + + ADD_PROPERTY(PropertyInfo(Variant::RID, "texture_rd_rid"), "set_texture_rd_rid", "get_texture_rd_rid"); +} + +int Texture2DRD::get_width() const { + return size.width; +} + +int Texture2DRD::get_height() const { + return size.height; +} + +RID Texture2DRD::get_rid() const { + if (texture_rid.is_null()) { + // We are in trouble, create something temporary. + texture_rid = RenderingServer::get_singleton()->texture_2d_placeholder_create(); + } + + return texture_rid; +} + +bool Texture2DRD::has_alpha() const { + return false; +} + +Ref Texture2DRD::get_image() const { + ERR_FAIL_NULL_V(RS::get_singleton(), Ref()); + if (texture_rid.is_valid()) { + return RS::get_singleton()->texture_2d_get(texture_rid); + } else { + return Ref(); + } +} + +void Texture2DRD::set_texture_rd_rid(RID p_texture_rd_rid) { + ERR_FAIL_NULL(RS::get_singleton()); + + if (p_texture_rd_rid.is_valid()) { + ERR_FAIL_NULL(RD::get_singleton()); + ERR_FAIL_COND(!RD::get_singleton()->texture_is_valid(p_texture_rd_rid)); + + RD::TextureFormat tf = RD::get_singleton()->texture_get_format(p_texture_rd_rid); + ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_2D); + ERR_FAIL_COND(tf.depth > 1); + ERR_FAIL_COND(tf.array_layers > 1); + + size.width = tf.width; + size.height = tf.height; + + texture_rd_rid = p_texture_rd_rid; + + if (texture_rid.is_valid()) { + RS::get_singleton()->texture_replace(texture_rid, RS::get_singleton()->texture_rd_create(p_texture_rd_rid)); + } else { + texture_rid = RS::get_singleton()->texture_rd_create(p_texture_rd_rid); + } + + notify_property_list_changed(); + emit_changed(); + } else if (texture_rid.is_valid()) { + RS::get_singleton()->free(texture_rid); + texture_rid = RID(); + size = Size2i(); + + notify_property_list_changed(); + emit_changed(); + } +} + +RID Texture2DRD::get_texture_rd_rid() const { + return texture_rd_rid; +} + +Texture2DRD::Texture2DRD() { + size = Size2i(); +} + +Texture2DRD::~Texture2DRD() { + if (texture_rid.is_valid()) { + ERR_FAIL_NULL(RS::get_singleton()); + RS::get_singleton()->free(texture_rid); + texture_rid = RID(); + } +} + +//////////////////////////////////////////////////////////////////////////// +// TextureLayeredRD + +void TextureLayeredRD::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture_rd_rid", "texture_rd_rid"), &TextureLayeredRD::set_texture_rd_rid); + ClassDB::bind_method(D_METHOD("get_texture_rd_rid"), &TextureLayeredRD::get_texture_rd_rid); + + ADD_PROPERTY(PropertyInfo(Variant::RID, "texture_rd_rid"), "set_texture_rd_rid", "get_texture_rd_rid"); +} + +TextureLayered::LayeredType TextureLayeredRD::get_layered_type() const { + return layer_type; +} + +Image::Format TextureLayeredRD::get_format() const { + return image_format; +} + +int TextureLayeredRD::get_width() const { + return size.width; +} + +int TextureLayeredRD::get_height() const { + return size.height; +} + +int TextureLayeredRD::get_layers() const { + return (int)layers; +} + +bool TextureLayeredRD::has_mipmaps() const { + return mipmaps > 1; +} + +RID TextureLayeredRD::get_rid() const { + if (texture_rid.is_null()) { + // We are in trouble, create something temporary. + texture_rid = RenderingServer::get_singleton()->texture_2d_placeholder_create(); + } + + return texture_rid; +} + +Ref TextureLayeredRD::get_layer_data(int p_layer) const { + ERR_FAIL_INDEX_V(p_layer, (int)layers, Ref()); + return RS::get_singleton()->texture_2d_layer_get(texture_rid, p_layer); +} + +void TextureLayeredRD::set_texture_rd_rid(RID p_texture_rd_rid) { + ERR_FAIL_NULL(RS::get_singleton()); + + if (p_texture_rd_rid.is_valid()) { + ERR_FAIL_NULL(RD::get_singleton()); + ERR_FAIL_COND(!RD::get_singleton()->texture_is_valid(p_texture_rd_rid)); + + RS::TextureLayeredType rs_layer_type; + RD::TextureFormat tf = RD::get_singleton()->texture_get_format(p_texture_rd_rid); + ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_2D_ARRAY); + ERR_FAIL_COND(tf.depth > 1); + switch (layer_type) { + case LAYERED_TYPE_2D_ARRAY: { + ERR_FAIL_COND(tf.array_layers <= 1); + rs_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY; + } break; + case LAYERED_TYPE_CUBEMAP: { + ERR_FAIL_COND(tf.array_layers != 6); + rs_layer_type = RS::TEXTURE_LAYERED_CUBEMAP; + } break; + case LAYERED_TYPE_CUBEMAP_ARRAY: { + ERR_FAIL_COND((tf.array_layers == 0) || ((tf.array_layers % 6) != 0)); + rs_layer_type = RS::TEXTURE_LAYERED_CUBEMAP_ARRAY; + } break; + default: { + ERR_FAIL_MSG("Unknown layer type selected"); + } break; + } + + size.width = tf.width; + size.height = tf.height; + layers = tf.array_layers; + mipmaps = tf.mipmaps; + + texture_rd_rid = p_texture_rd_rid; + + if (texture_rid.is_valid()) { + RS::get_singleton()->texture_replace(texture_rid, RS::get_singleton()->texture_rd_create(p_texture_rd_rid, rs_layer_type)); + } else { + texture_rid = RS::get_singleton()->texture_rd_create(p_texture_rd_rid, rs_layer_type); + } + + image_format = RS::get_singleton()->texture_get_format(texture_rid); + + notify_property_list_changed(); + emit_changed(); + } else if (texture_rid.is_valid()) { + RS::get_singleton()->free(texture_rid); + texture_rid = RID(); + image_format = Image::FORMAT_MAX; + size = Size2i(); + layers = 0; + mipmaps = 0; + + notify_property_list_changed(); + emit_changed(); + } +} + +RID TextureLayeredRD::get_texture_rd_rid() const { + return texture_rd_rid; +} + +TextureLayeredRD::TextureLayeredRD(LayeredType p_layer_type) { + layer_type = p_layer_type; + size = Size2i(); + image_format = Image::FORMAT_MAX; + layers = 0; + mipmaps = 0; +} + +TextureLayeredRD::~TextureLayeredRD() { + if (texture_rid.is_valid()) { + ERR_FAIL_NULL(RS::get_singleton()); + RS::get_singleton()->free(texture_rid); + texture_rid = RID(); + } +} + +//////////////////////////////////////////////////////////////////////////// +// Texture3DRD + +void Texture3DRD::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture_rd_rid", "texture_rd_rid"), &Texture3DRD::set_texture_rd_rid); + ClassDB::bind_method(D_METHOD("get_texture_rd_rid"), &Texture3DRD::get_texture_rd_rid); + + ADD_PROPERTY(PropertyInfo(Variant::RID, "texture_rd_rid"), "set_texture_rd_rid", "get_texture_rd_rid"); +} + +Image::Format Texture3DRD::get_format() const { + return image_format; +} + +int Texture3DRD::get_width() const { + return size.x; +} + +int Texture3DRD::get_height() const { + return size.y; +} + +int Texture3DRD::get_depth() const { + return size.z; +} + +bool Texture3DRD::has_mipmaps() const { + return mipmaps > 1; +} + +RID Texture3DRD::get_rid() const { + if (texture_rid.is_null()) { + // We are in trouble, create something temporary. + texture_rid = RenderingServer::get_singleton()->texture_2d_placeholder_create(); + } + + return texture_rid; +} + +void Texture3DRD::set_texture_rd_rid(RID p_texture_rd_rid) { + ERR_FAIL_NULL(RS::get_singleton()); + + if (p_texture_rd_rid.is_valid()) { + ERR_FAIL_NULL(RD::get_singleton()); + ERR_FAIL_COND(!RD::get_singleton()->texture_is_valid(p_texture_rd_rid)); + + RD::TextureFormat tf = RD::get_singleton()->texture_get_format(p_texture_rd_rid); + ERR_FAIL_COND(tf.texture_type != RD::TEXTURE_TYPE_3D); + ERR_FAIL_COND(tf.array_layers > 1); + + size.x = tf.width; + size.y = tf.height; + size.z = tf.depth; + mipmaps = tf.mipmaps; + + texture_rd_rid = p_texture_rd_rid; + + if (texture_rid.is_valid()) { + RS::get_singleton()->texture_replace(texture_rid, RS::get_singleton()->texture_rd_create(p_texture_rd_rid)); + } else { + texture_rid = RS::get_singleton()->texture_rd_create(p_texture_rd_rid); + } + + image_format = RS::get_singleton()->texture_get_format(texture_rid); + + notify_property_list_changed(); + emit_changed(); + } else if (texture_rid.is_valid()) { + RS::get_singleton()->free(texture_rid); + texture_rid = RID(); + image_format = Image::FORMAT_MAX; + size = Vector3i(); + mipmaps = 0; + + notify_property_list_changed(); + emit_changed(); + } +} + +RID Texture3DRD::get_texture_rd_rid() const { + return texture_rd_rid; +} + +Texture3DRD::Texture3DRD() { + image_format = Image::FORMAT_MAX; + size = Vector3i(); + mipmaps = 0; +} + +Texture3DRD::~Texture3DRD() { + if (texture_rid.is_valid()) { + ERR_FAIL_NULL(RS::get_singleton()); + RS::get_singleton()->free(texture_rid); + texture_rid = RID(); + } +} diff --git a/scene/resources/texture_rd.h b/scene/resources/texture_rd.h new file mode 100644 index 00000000000..f88d6c5155e --- /dev/null +++ b/scene/resources/texture_rd.h @@ -0,0 +1,153 @@ +/**************************************************************************/ +/* texture_rd.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef TEXTURE_RD_H +#define TEXTURE_RD_H + +// Note, these classes are part of the Rendering Device based renderer. +// They are included here to ensure the correct order of registration +// is performed. +// Once the renderer has been moved into a module, these classes should +// be moved as well. + +#include "scene/resources/texture.h" + +class Texture2DRD : public Texture2D { + GDCLASS(Texture2DRD, Texture2D) + + mutable RID texture_rid; + RID texture_rd_rid; + Size2i size; + +protected: + static void _bind_methods(); + +public: + virtual int get_width() const override; + virtual int get_height() const override; + virtual RID get_rid() const override; + virtual bool has_alpha() const override; + + virtual Ref get_image() const override; + + void set_texture_rd_rid(RID p_texture_rd_rid); + RID get_texture_rd_rid() const; + + Texture2DRD(); + ~Texture2DRD(); +}; + +class TextureLayeredRD : public TextureLayered { + GDCLASS(TextureLayeredRD, TextureLayered) + + LayeredType layer_type; + + mutable RID texture_rid; + RID texture_rd_rid; + + Image::Format image_format; + Size2i size; + uint32_t layers = 0; + uint32_t mipmaps = 0; + +protected: + static void _bind_methods(); + +public: + virtual Image::Format get_format() const override; + virtual LayeredType get_layered_type() const override; + virtual int get_width() const override; + virtual int get_height() const override; + virtual int get_layers() const override; + virtual bool has_mipmaps() const override; + virtual RID get_rid() const override; + + virtual Ref get_layer_data(int p_layer) const override; + + void set_texture_rd_rid(RID p_texture_rd_rid); + RID get_texture_rd_rid() const; + + TextureLayeredRD(LayeredType p_layer_type); + ~TextureLayeredRD(); +}; + +class Texture2DArrayRD : public TextureLayeredRD { + GDCLASS(Texture2DArrayRD, TextureLayeredRD) + +public: + Texture2DArrayRD() : + TextureLayeredRD(LAYERED_TYPE_2D_ARRAY) {} +}; + +class TextureCubemapRD : public TextureLayeredRD { + GDCLASS(TextureCubemapRD, TextureLayeredRD) + +public: + TextureCubemapRD() : + TextureLayeredRD(LAYERED_TYPE_CUBEMAP) {} +}; + +class TextureCubemapArrayRD : public TextureLayeredRD { + GDCLASS(TextureCubemapArrayRD, TextureLayeredRD) + +public: + TextureCubemapArrayRD() : + TextureLayeredRD(LAYERED_TYPE_CUBEMAP_ARRAY) {} +}; + +class Texture3DRD : public Texture3D { + GDCLASS(Texture3DRD, Texture3D) + + mutable RID texture_rid; + RID texture_rd_rid; + + Image::Format image_format; + Vector3i size; + uint32_t mipmaps = 0; + +protected: + static void _bind_methods(); + +public: + virtual Image::Format get_format() const override; + virtual int get_width() const override; + virtual int get_height() const override; + virtual int get_depth() const override; + virtual bool has_mipmaps() const override; + virtual RID get_rid() const override; + + void set_texture_rd_rid(RID p_texture_rd_rid); + RID get_texture_rd_rid() const; + + Texture3DRD(); + ~Texture3DRD(); +}; + +#endif // TEXTURE_RD_H diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index 768b1ba7026..71a1801de96 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -117,6 +117,8 @@ public: virtual void texture_set_path(RID p_texture, const String &p_path) override{}; virtual String texture_get_path(RID p_texture) const override { return String(); }; + virtual Image::Format texture_get_format(RID p_texture) const override { return Image::FORMAT_MAX; } + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{}; virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override{}; virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override{}; @@ -127,6 +129,7 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); }; + virtual void texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY) override{}; virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override { return RID(); }; virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override { return 0; }; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 3c4e792b372..d84f6e68506 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -1395,6 +1395,13 @@ String TextureStorage::texture_get_path(RID p_texture) const { return tex->path; } +Image::Format TextureStorage::texture_get_format(RID p_texture) const { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_COND_V(!tex, Image::FORMAT_MAX); + + return tex->format; +} + void TextureStorage::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_COND(!tex); @@ -1429,6 +1436,79 @@ Size2 TextureStorage::texture_size_with_proxy(RID p_proxy) { return texture_2d_get_size(p_proxy); } +void TextureStorage::texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type) { + ERR_FAIL_COND(!RD::get_singleton()->texture_is_valid(p_rd_texture)); + + // TODO : investigate if we can support this, will need to be able to obtain the order and obtain the slice info + ERR_FAIL_COND_MSG(RD::get_singleton()->texture_is_shared(p_rd_texture), "Please create the texture object using the original texture"); + + RD::TextureFormat tf = RD::get_singleton()->texture_get_format(p_rd_texture); + ERR_FAIL_COND(!(tf.usage_bits & RD::TEXTURE_USAGE_SAMPLING_BIT)); + + TextureFromRDFormat imfmt; + _texture_format_from_rd(tf.format, imfmt); + ERR_FAIL_COND(imfmt.image_format == Image::FORMAT_MAX); + + Texture texture; + + switch (tf.texture_type) { + case RD::TEXTURE_TYPE_2D: { + ERR_FAIL_COND(tf.array_layers != 1); + texture.type = TextureStorage::TYPE_2D; + } break; + case RD::TEXTURE_TYPE_2D_ARRAY: { + // RenderingDevice doesn't distinguish between Array textures and Cube textures + // this condition covers TextureArrays, TextureCube, and TextureCubeArray. + ERR_FAIL_COND(tf.array_layers == 1); + texture.type = TextureStorage::TYPE_LAYERED; + texture.layered_type = p_layer_type; + } break; + case RD::TEXTURE_TYPE_3D: { + ERR_FAIL_COND(tf.array_layers != 1); + texture.type = TextureStorage::TYPE_3D; + } break; + default: { + ERR_FAIL_MSG("This RD texture can't be used as a render texture"); + } break; + } + + texture.width = tf.width; + texture.height = tf.height; + texture.depth = tf.depth; + texture.layers = tf.array_layers; + texture.mipmaps = tf.mipmaps; + texture.format = imfmt.image_format; + texture.validated_format = texture.format; // ?? + + RD::TextureView rd_view; + rd_view.format_override = imfmt.rd_format == tf.format ? RD::DATA_FORMAT_MAX : imfmt.rd_format; + rd_view.swizzle_r = imfmt.swizzle_r; + rd_view.swizzle_g = imfmt.swizzle_g; + rd_view.swizzle_b = imfmt.swizzle_b; + rd_view.swizzle_a = imfmt.swizzle_a; + + texture.rd_type = tf.texture_type; + texture.rd_view = rd_view; + texture.rd_format = imfmt.rd_format; + // We create a shared texture here even if our view matches, so we don't obtain ownership. + texture.rd_texture = RD::get_singleton()->texture_create_shared(rd_view, p_rd_texture); + if (imfmt.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = imfmt.rd_format_srgb == tf.format ? RD::DATA_FORMAT_MAX : imfmt.rd_format; + texture.rd_format_srgb = imfmt.rd_format_srgb; + // We create a shared texture here even if our view matches, so we don't obtain ownership. + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, p_rd_texture); + } + + // TODO figure out what to do with slices + + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.is_proxy = false; + + texture_owner.initialize_rid(p_texture, texture); +} + RID TextureStorage::texture_get_rd_texture(RID p_texture, bool p_srgb) const { if (p_texture.is_null()) { return RID(); @@ -1921,6 +2001,362 @@ Ref TextureStorage::_validate_texture_format(const Ref &p_image, T return image; } +void TextureStorage::_texture_format_from_rd(RD::DataFormat p_rd_format, TextureFromRDFormat &r_format) { + switch (p_rd_format) { + case RD::DATA_FORMAT_R8_UNORM: { + r_format.image_format = Image::FORMAT_L8; + r_format.rd_format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //luminance + case RD::DATA_FORMAT_R8G8_UNORM: { + r_format.image_format = Image::FORMAT_LA8; + r_format.rd_format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G; + } break; //luminance-alpha + /* already maps to L8/LA8 + case RD::DATA_FORMAT_R8_UNORM: { + r_format.image_format = Image::FORMAT_R8; + r_format.rd_format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case RD::DATA_FORMAT_R8G8_UNORM: { + r_format.image_format = Image::FORMAT_RG8; + r_format.rd_format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + */ + case RD::DATA_FORMAT_R8G8B8_UNORM: + case RD::DATA_FORMAT_R8G8B8_SRGB: { + r_format.image_format = Image::FORMAT_RGB8; + r_format.rd_format = RD::DATA_FORMAT_R8G8B8_UNORM; + r_format.rd_format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case RD::DATA_FORMAT_R8G8B8A8_UNORM: + case RD::DATA_FORMAT_R8G8B8A8_SRGB: { + r_format.image_format = Image::FORMAT_RGBA8; + r_format.rd_format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.rd_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16: { + r_format.image_format = Image::FORMAT_RGBA4444; + r_format.rd_format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case RD::DATA_FORMAT_B5G6R5_UNORM_PACK16: { + r_format.image_format = Image::FORMAT_RGB565; + r_format.rd_format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case RD::DATA_FORMAT_R32_SFLOAT: { + r_format.image_format = Image::FORMAT_RF; + r_format.rd_format = RD::DATA_FORMAT_R32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float + case RD::DATA_FORMAT_R32G32_SFLOAT: { + r_format.image_format = Image::FORMAT_RGF; + r_format.rd_format = RD::DATA_FORMAT_R32G32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case RD::DATA_FORMAT_R32G32B32_SFLOAT: { + r_format.image_format = Image::FORMAT_RGBF; + r_format.rd_format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case RD::DATA_FORMAT_R32G32B32A32_SFLOAT: { + r_format.image_format = Image::FORMAT_RGBF; + r_format.rd_format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case RD::DATA_FORMAT_R16_SFLOAT: { + r_format.image_format = Image::FORMAT_RH; + r_format.rd_format = RD::DATA_FORMAT_R16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //half float + case RD::DATA_FORMAT_R16G16_SFLOAT: { + r_format.image_format = Image::FORMAT_RGH; + r_format.rd_format = RD::DATA_FORMAT_R16G16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case RD::DATA_FORMAT_R16G16B16_SFLOAT: { + r_format.image_format = Image::FORMAT_RGBH; + r_format.rd_format = RD::DATA_FORMAT_R16G16B16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case RD::DATA_FORMAT_R16G16B16A16_SFLOAT: { + r_format.image_format = Image::FORMAT_RGBAH; + r_format.rd_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32: { + r_format.image_format = Image::FORMAT_RGBE9995; + r_format.rd_format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; + // TODO: Need to make a function in Image to swap bits for this. + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY; + } break; + case RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK: + case RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_DXT1; + r_format.rd_format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //s3tc bc1 + case RD::DATA_FORMAT_BC2_UNORM_BLOCK: + case RD::DATA_FORMAT_BC2_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_DXT3; + r_format.rd_format = RD::DATA_FORMAT_BC2_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //bc2 + case RD::DATA_FORMAT_BC3_UNORM_BLOCK: + case RD::DATA_FORMAT_BC3_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_DXT5; + r_format.rd_format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; //bc3 + case RD::DATA_FORMAT_BC4_UNORM_BLOCK: { + r_format.image_format = Image::FORMAT_RGTC_R; + r_format.rd_format = RD::DATA_FORMAT_BC4_UNORM_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case RD::DATA_FORMAT_BC5_UNORM_BLOCK: { + r_format.image_format = Image::FORMAT_RGTC_RG; + r_format.rd_format = RD::DATA_FORMAT_BC5_UNORM_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case RD::DATA_FORMAT_BC7_UNORM_BLOCK: + case RD::DATA_FORMAT_BC7_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_BPTC_RGBA; + r_format.rd_format = RD::DATA_FORMAT_BC7_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //btpc bc7 + case RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK: { + r_format.image_format = Image::FORMAT_BPTC_RGBF; + r_format.rd_format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float bc6h + case RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK: { + r_format.image_format = Image::FORMAT_BPTC_RGBFU; + r_format.rd_format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //unsigned float bc6hu + case RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK: { + r_format.image_format = Image::FORMAT_ETC2_R11; + r_format.rd_format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //etc2 + case RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK: { + r_format.image_format = Image::FORMAT_ETC2_R11S; + r_format.rd_format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //signed: {} break; NOT srgb. + case RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK: { + r_format.image_format = Image::FORMAT_ETC2_RG11; + r_format.rd_format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK: { + r_format.image_format = Image::FORMAT_ETC2_RG11S; + r_format.rd_format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + case RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_ETC2_RGB8; + r_format.rd_format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + /* already maps to FORMAT_ETC2_RGBA8 + case RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + case RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_ETC2_RGBA8; + r_format.rd_format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + */ + case RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + case RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_ETC2_RGB8A1; + r_format.rd_format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + case RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_ETC2_RA_AS_RG; + r_format.rd_format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + /* already maps to FORMAT_DXT5 + case RD::DATA_FORMAT_BC3_UNORM_BLOCK: + case RD::DATA_FORMAT_BC3_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_DXT5_RA_AS_RG; + r_format.rd_format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + */ + case RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK: { + // Q: Do we do as we do below, just create the sRGB variant? + r_format.image_format = Image::FORMAT_ASTC_4x4; + r_format.rd_format = RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case RD::DATA_FORMAT_ASTC_4x4_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_ASTC_4x4_HDR; + r_format.rd_format = RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_ASTC_4x4_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; // astc 4x4 + case RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK: { + // Q: Do we do as we do below, just create the sRGB variant? + r_format.image_format = Image::FORMAT_ASTC_8x8; + r_format.rd_format = RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK; + } break; + case RD::DATA_FORMAT_ASTC_8x8_SRGB_BLOCK: { + r_format.image_format = Image::FORMAT_ASTC_8x8_HDR; + r_format.rd_format = RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK; + r_format.rd_format_srgb = RD::DATA_FORMAT_ASTC_8x8_SRGB_BLOCK; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; // astc 8x8 + + default: { + ERR_FAIL_MSG("Unsupported image format"); + } + } +} + /* DECAL API */ RID TextureStorage::decal_atlas_get_texture() const { diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 8f021f31791..6df6faa40ab 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -196,6 +196,27 @@ private: Ref _validate_texture_format(const Ref &p_image, TextureToRDFormat &r_format); void _texture_2d_update(RID p_texture, const Ref &p_image, int p_layer = 0, bool p_immediate = false); + struct TextureFromRDFormat { + Image::Format image_format; + RD::DataFormat rd_format; + RD::DataFormat rd_format_srgb; + RD::TextureSwizzle swizzle_r; + RD::TextureSwizzle swizzle_g; + RD::TextureSwizzle swizzle_b; + RD::TextureSwizzle swizzle_a; + TextureFromRDFormat() { + image_format = Image::FORMAT_MAX; + rd_format = RD::DATA_FORMAT_MAX; + rd_format_srgb = RD::DATA_FORMAT_MAX; + swizzle_r = RD::TEXTURE_SWIZZLE_R; + swizzle_g = RD::TEXTURE_SWIZZLE_G; + swizzle_b = RD::TEXTURE_SWIZZLE_B; + swizzle_a = RD::TEXTURE_SWIZZLE_A; + } + }; + + void _texture_format_from_rd(RD::DataFormat p_rd_format, TextureFromRDFormat &r_format); + /* DECAL API */ struct DecalAtlas { @@ -488,6 +509,8 @@ public: virtual void texture_set_path(RID p_texture, const String &p_path) override; virtual String texture_get_path(RID p_texture) const override; + virtual Image::Format texture_get_format(RID p_texture) const override; + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) override; virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) override; @@ -498,6 +521,7 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) override; + virtual void texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY) override; virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const override; virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const override; diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 2dd11e5efe8..7bfa23bfa5d 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -114,6 +114,14 @@ RID RenderingDevice::_texture_create_shared_from_slice(const Ref return texture_create_shared_from_slice(p_view->base, p_with_texture, p_layer, p_mipmap, p_mipmaps, p_slice_type); } +Ref RenderingDevice::_texture_get_format(RID p_rd_texture) { + Ref rtf; + rtf.instantiate(); + rtf->base = texture_get_format(p_rd_texture); + + return rtf; +} + RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create(const TypedArray &p_attachments, uint32_t p_view_count) { Vector attachments; attachments.resize(p_attachments.size()); @@ -720,6 +728,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::texture_clear, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::texture_resolve_multisample, DEFVAL(BARRIER_MASK_ALL_BARRIERS)); + ClassDB::bind_method(D_METHOD("texture_get_format", "texture"), &RenderingDevice::_texture_get_format); ClassDB::bind_method(D_METHOD("texture_get_native_handle", "texture"), &RenderingDevice::texture_get_native_handle); ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments", "view_count"), &RenderingDevice::_framebuffer_format_create, DEFVAL(1)); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 0a362962a16..5edeb109e26 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -541,6 +541,7 @@ public: virtual bool texture_is_format_supported_for_usage(DataFormat p_format, BitField p_usage) const = 0; virtual bool texture_is_shared(RID p_texture) = 0; virtual bool texture_is_valid(RID p_texture) = 0; + virtual TextureFormat texture_get_format(RID p_texture) = 0; virtual Size2i texture_size(RID p_texture) = 0; virtual uint64_t texture_get_native_handle(RID p_texture) = 0; @@ -1316,6 +1317,7 @@ protected: RID _texture_create(const Ref &p_format, const Ref &p_view, const TypedArray &p_data = Array()); RID _texture_create_shared(const Ref &p_view, RID p_with_texture); RID _texture_create_shared_from_slice(const Ref &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D); + Ref _texture_get_format(RID p_rd_texture); FramebufferFormatID _framebuffer_format_create(const TypedArray &p_attachments, uint32_t p_view_count); FramebufferFormatID _framebuffer_format_create_multipass(const TypedArray &p_attachments, const TypedArray &p_passes, uint32_t p_view_count); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 340eb7394b2..c79d3a64cfd 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -210,9 +210,13 @@ public: FUNC2(texture_set_path, RID, const String &) FUNC1RC(String, texture_get_path, RID) + + FUNC1RC(Image::Format, texture_get_format, RID) + FUNC1(texture_debug_usage, List *) FUNC2(texture_set_force_redraw_if_visible, RID, bool) + FUNCRIDTEX2(texture_rd, const RID &, const RS::TextureLayeredType) FUNC2RC(RID, texture_get_rd_texture, RID, bool) FUNC2RC(uint64_t, texture_get_native_handle, RID, bool) diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index 93b32bd3722..c3a257595c2 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -90,6 +90,8 @@ public: virtual void texture_set_path(RID p_texture, const String &p_path) = 0; virtual String texture_get_path(RID p_texture) const = 0; + virtual Image::Format texture_get_format(RID p_texture) const = 0; + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; @@ -100,6 +102,7 @@ public: virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; + virtual void texture_rd_initialize(RID p_texture, const RID &p_rd_texture, const RS::TextureLayeredType p_layer_type = RS::TEXTURE_LAYERED_2D_ARRAY) = 0; virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const = 0; virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const = 0; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 4c6b7651573..4a95dc19639 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1697,7 +1697,10 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("texture_set_path", "texture", "path"), &RenderingServer::texture_set_path); ClassDB::bind_method(D_METHOD("texture_get_path", "texture"), &RenderingServer::texture_get_path); + ClassDB::bind_method(D_METHOD("texture_get_format", "texture"), &RenderingServer::texture_get_format); + ClassDB::bind_method(D_METHOD("texture_set_force_redraw_if_visible", "texture", "enable"), &RenderingServer::texture_set_force_redraw_if_visible); + ClassDB::bind_method(D_METHOD("texture_rd_create", "rd_texture", "layer_type"), &RenderingServer::texture_rd_create, DEFVAL(RenderingServer::TEXTURE_LAYERED_2D_ARRAY)); ClassDB::bind_method(D_METHOD("texture_get_rd_texture", "texture", "srgb"), &RenderingServer::texture_get_rd_texture, DEFVAL(false)); ClassDB::bind_method(D_METHOD("texture_get_native_handle", "texture", "srgb"), &RenderingServer::texture_get_native_handle, DEFVAL(false)); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index deac2a59f92..9ea55c31b45 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -127,6 +127,8 @@ public: virtual void texture_set_path(RID p_texture, const String &p_path) = 0; virtual String texture_get_path(RID p_texture) const = 0; + virtual Image::Format texture_get_format(RID p_texture) const = 0; + typedef void (*TextureDetectCallback)(void *); virtual void texture_set_detect_3d_callback(RID p_texture, TextureDetectCallback p_callback, void *p_userdata) = 0; @@ -158,6 +160,7 @@ public: virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; + virtual RID texture_rd_create(const RID &p_rd_texture, const RenderingServer::TextureLayeredType p_layer_type = RenderingServer::TEXTURE_LAYERED_2D_ARRAY) = 0; virtual RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) const = 0; virtual uint64_t texture_get_native_handle(RID p_texture, bool p_srgb = false) const = 0;