Add custom texture create function

This commit is contained in:
Bastiaan Olij 2023-07-10 22:31:27 +10:00
parent 202e4b2c1e
commit 63d6e9c557
26 changed files with 1130 additions and 3 deletions

View file

@ -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.
</description>
</method>
<method name="texture_get_format">
<return type="RDTextureFormat" />
<param index="0" name="texture" type="RID" />
<description>
Returns the data format used to create this texture.
</description>
</method>
<method name="texture_get_native_handle">
<return type="int" />
<param index="0" name="texture" type="RID" />

View file

@ -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.
</description>
</method>
<method name="texture_get_format" qualifiers="const">
<return type="int" enum="Image.Format" />
<param index="0" name="texture" type="RID" />
<description>
Returns the [enum Image.Format] for the texture.
</description>
</method>
<method name="texture_get_native_handle" qualifiers="const">
<return type="int" />
<param index="0" name="texture" type="RID" />
@ -3319,6 +3326,14 @@
[i]Deprecated.[/i] ProxyTexture was removed in Godot 4, so this method cannot be used anymore.
</description>
</method>
<method name="texture_rd_create">
<return type="RID" />
<param index="0" name="rd_texture" type="RID" />
<param index="1" name="layer_type" type="int" enum="RenderingServer.TextureLayeredType" default="0" />
<description>
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.
</description>
</method>
<method name="texture_replace">
<return type="void" />
<param index="0" name="texture" type="RID" />

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Texture2DArrayRD" inherits="TextureLayeredRD" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Texture Array for 2D that is bound to a texture created on the [RenderingDevice].
</brief_description>
<description>
This texture array class allows you to use a 2D array texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc.
</description>
<tutorials>
</tutorials>
</class>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Texture2DRD" inherits="Texture2D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Texture for 2D that is bound to a texture created on the [RenderingDevice].
</brief_description>
<description>
This texture class allows you to use a 2D texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc.
</description>
<tutorials>
</tutorials>
<members>
<member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="texture_rd_rid" type="RID" setter="set_texture_rd_rid" getter="get_texture_rd_rid" default="RID()">
The RID of the texture object created on the [RenderingDevice].
</member>
</members>
</class>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Texture3DRD" inherits="Texture3D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Texture for 3D that is bound to a texture created on the [RenderingDevice].
</brief_description>
<description>
This texture class allows you to use a 3D texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc.
</description>
<tutorials>
</tutorials>
<members>
<member name="texture_rd_rid" type="RID" setter="set_texture_rd_rid" getter="get_texture_rd_rid" default="RID()">
The RID of the texture object created on the [RenderingDevice].
</member>
</members>
</class>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TextureCubemapArrayRD" inherits="TextureLayeredRD" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Texture Array for Cubemaps that is bound to a texture created on the [RenderingDevice].
</brief_description>
<description>
This texture class allows you to use a cubemap array texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc.
</description>
<tutorials>
</tutorials>
</class>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TextureCubemapRD" inherits="TextureLayeredRD" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Texture for Cubemap that is bound to a texture created on the [RenderingDevice].
</brief_description>
<description>
This texture class allows you to use a cubemap texture created directly on the [RenderingDevice] as a texture for materials, meshes, etc.
</description>
<tutorials>
</tutorials>
</class>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TextureLayeredRD" inherits="TextureLayered" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Abstract base class for layered texture RD types.
</brief_description>
<description>
Base class for [Texture2DArrayRD], [TextureCubemapRD] and [TextureCubemapArrayRD]. Cannot be used directly, but contains all the functions necessary for accessing the derived resource types.
</description>
<tutorials>
</tutorials>
<members>
<member name="texture_rd_rid" type="RID" setter="set_texture_rd_rid" getter="get_texture_rd_rid" default="RID()">
The RID of the texture object created on the [RenderingDevice].
</member>
</members>
</class>

View file

@ -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();
}

View file

@ -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<Image> &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;

View file

@ -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_

View file

@ -1082,6 +1082,7 @@ public:
virtual bool texture_is_format_supported_for_usage(DataFormat p_format, BitField<RenderingDevice::TextureUsageBits> 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);

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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<Image> Texture2DRD::get_image() const {
ERR_FAIL_NULL_V(RS::get_singleton(), Ref<Image>());
if (texture_rid.is_valid()) {
return RS::get_singleton()->texture_2d_get(texture_rid);
} else {
return Ref<Image>();
}
}
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<Image> TextureLayeredRD::get_layer_data(int p_layer) const {
ERR_FAIL_INDEX_V(p_layer, (int)layers, Ref<Image>());
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();
}
}

View file

@ -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<Image> 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<Image> 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

View file

@ -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; };

View file

@ -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<Image> TextureStorage::_validate_texture_format(const Ref<Image> &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 {

View file

@ -196,6 +196,27 @@ private:
Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format);
void _texture_2d_update(RID p_texture, const Ref<Image> &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;

View file

@ -114,6 +114,14 @@ RID RenderingDevice::_texture_create_shared_from_slice(const Ref<RDTextureView>
return texture_create_shared_from_slice(p_view->base, p_with_texture, p_layer, p_mipmap, p_mipmaps, p_slice_type);
}
Ref<RDTextureFormat> RenderingDevice::_texture_get_format(RID p_rd_texture) {
Ref<RDTextureFormat> rtf;
rtf.instantiate();
rtf->base = texture_get_format(p_rd_texture);
return rtf;
}
RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count) {
Vector<AttachmentFormat> 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));

View file

@ -541,6 +541,7 @@ public:
virtual bool texture_is_format_supported_for_usage(DataFormat p_format, BitField<RenderingDevice::TextureUsageBits> 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<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data = Array());
RID _texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture);
RID _texture_create_shared_from_slice(const Ref<RDTextureView> &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<RDTextureFormat> _texture_get_format(RID p_rd_texture);
FramebufferFormatID _framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count);
FramebufferFormatID _framebuffer_format_create_multipass(const TypedArray<RDAttachmentFormat> &p_attachments, const TypedArray<RDFramebufferPass> &p_passes, uint32_t p_view_count);

View file

@ -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<TextureInfo> *)
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)

View file

@ -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;

View file

@ -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));

View file

@ -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;