Expose a function to create textures from a native handle in the compatibility renderer

This commit is contained in:
David Snopek 2024-09-12 12:54:57 -05:00
parent 83d54ab2ad
commit 7d56b09f23
12 changed files with 255 additions and 15 deletions

View file

@ -92,6 +92,8 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override{};
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override{}; //all slices, then all the mipmaps, must be coherent
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override { return RID(); }
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override{};
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{};
virtual void texture_proxy_update(RID p_proxy, RID p_base) override{};

View file

@ -1108,6 +1108,195 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
tex->proxies.push_back(p_texture);
}
// Note: We make some big assumptions about format and usage. If developers need more control,
// they should use RD::texture_create_from_extension() instead.
RID TextureStorage::texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
RD::TextureType type;
switch (p_type) {
case RS::TEXTURE_TYPE_2D:
type = RD::TEXTURE_TYPE_2D;
break;
case RS::TEXTURE_TYPE_3D:
type = RD::TEXTURE_TYPE_3D;
break;
case RS::TEXTURE_TYPE_LAYERED:
if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
type = RD::TEXTURE_TYPE_2D_ARRAY;
} else if (p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP) {
type = RD::TEXTURE_TYPE_CUBE;
} else if (p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY) {
type = RD::TEXTURE_TYPE_CUBE_ARRAY;
} else {
// Arbitrary fallback.
type = RD::TEXTURE_TYPE_2D_ARRAY;
}
break;
default:
// Arbitrary fallback.
type = RD::TEXTURE_TYPE_2D;
}
// Only a rough conversion - see note above.
RD::DataFormat format;
switch (p_format) {
case Image::FORMAT_L8:
case Image::FORMAT_R8:
format = RD::DATA_FORMAT_R8_UNORM;
break;
case Image::FORMAT_LA8:
case Image::FORMAT_RG8:
format = RD::DATA_FORMAT_R8G8_UNORM;
break;
case Image::FORMAT_RGB8:
format = RD::DATA_FORMAT_R8G8B8_UNORM;
break;
case Image::FORMAT_RGBA8:
format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
break;
case Image::FORMAT_RGBA4444:
format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16;
break;
case Image::FORMAT_RGB565:
format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16;
break;
case Image::FORMAT_RF:
format = RD::DATA_FORMAT_R32_SFLOAT;
break;
case Image::FORMAT_RGF:
format = RD::DATA_FORMAT_R32G32_SFLOAT;
break;
case Image::FORMAT_RGBF:
format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
break;
case Image::FORMAT_RGBAF:
format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
break;
case Image::FORMAT_RH:
format = RD::DATA_FORMAT_R16_SFLOAT;
break;
case Image::FORMAT_RGH:
format = RD::DATA_FORMAT_R16G16_SFLOAT;
break;
case Image::FORMAT_RGBH:
format = RD::DATA_FORMAT_R16G16B16_SFLOAT;
break;
case Image::FORMAT_RGBAH:
format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
break;
case Image::FORMAT_RGBE9995:
format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
break;
case Image::FORMAT_DXT1:
format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK;
break;
case Image::FORMAT_DXT3:
format = RD::DATA_FORMAT_BC2_UNORM_BLOCK;
break;
case Image::FORMAT_DXT5:
format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
break;
case Image::FORMAT_RGTC_R:
format = RD::DATA_FORMAT_BC4_UNORM_BLOCK;
break;
case Image::FORMAT_RGTC_RG:
format = RD::DATA_FORMAT_BC5_UNORM_BLOCK;
break;
case Image::FORMAT_BPTC_RGBA:
format = RD::DATA_FORMAT_BC7_UNORM_BLOCK;
break;
case Image::FORMAT_BPTC_RGBF:
format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK;
break;
case Image::FORMAT_BPTC_RGBFU:
format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK;
break;
case Image::FORMAT_ETC:
format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
break;
case Image::FORMAT_ETC2_R11:
format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK;
break;
case Image::FORMAT_ETC2_R11S:
format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK;
break;
case Image::FORMAT_ETC2_RG11:
format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK;
break;
case Image::FORMAT_ETC2_RG11S:
format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK;
break;
case Image::FORMAT_ETC2_RGB8:
format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
break;
case Image::FORMAT_ETC2_RGBA8:
format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
break;
case Image::FORMAT_ETC2_RGB8A1:
format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
break;
case Image::FORMAT_ETC2_RA_AS_RG:
format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
break;
case Image::FORMAT_DXT5_RA_AS_RG:
format = RD::DATA_FORMAT_BC3_UNORM_BLOCK;
break;
case Image::FORMAT_ASTC_4x4:
case Image::FORMAT_ASTC_4x4_HDR:
format = RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK;
break;
case Image::FORMAT_ASTC_8x8:
case Image::FORMAT_ASTC_8x8_HDR:
format = RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK;
break;
default:
// Arbitrary fallback.
format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
}
// Assumed to be a color attachment - see note above.
uint64_t usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
return RD::get_singleton()->texture_create_from_extension(type, format, RD::TEXTURE_SAMPLES_1, usage_flags, p_native_handle, p_width, p_height, p_depth, p_layers);
}
void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) {
ERR_FAIL_COND(p_image.is_null() || p_image->is_empty());

View file

@ -493,6 +493,8 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override;
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;

View file

@ -179,6 +179,11 @@ public:
FUNCRIDTEX6(texture_3d, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &)
FUNCRIDTEX1(texture_proxy, RID)
// Called directly, not through the command queue.
virtual RID texture_create_from_native_handle(TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, TextureLayeredType p_layered_type = TEXTURE_LAYERED_2D_ARRAY) override {
return RSG::texture_storage->texture_create_from_native_handle(p_type, p_format, p_native_handle, p_width, p_height, p_depth, p_layers, p_layered_type);
}
//these go through command queue if they are in another thread
FUNC3(texture_2d_update, RID, const Ref<Image> &, int)
FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &)

View file

@ -71,6 +71,8 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) = 0;
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;

View file

@ -2239,6 +2239,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_2d_layered_create", "layers", "layered_type"), &RenderingServer::_texture_2d_layered_create);
ClassDB::bind_method(D_METHOD("texture_3d_create", "format", "width", "height", "depth", "mipmaps", "data"), &RenderingServer::_texture_3d_create);
ClassDB::bind_method(D_METHOD("texture_proxy_create", "base"), &RenderingServer::texture_proxy_create);
ClassDB::bind_method(D_METHOD("texture_create_from_native_handle", "type", "format", "native_handle", "width", "height", "depth", "layers", "layered_type"), &RenderingServer::texture_create_from_native_handle, DEFVAL(1), DEFVAL(TEXTURE_LAYERED_2D_ARRAY));
ClassDB::bind_method(D_METHOD("texture_2d_update", "texture", "image", "layer"), &RenderingServer::texture_2d_update);
ClassDB::bind_method(D_METHOD("texture_3d_update", "texture", "data"), &RenderingServer::_texture_3d_update);
@ -2265,6 +2266,10 @@ void RenderingServer::_bind_methods() {
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));
BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D);
BIND_ENUM_CONSTANT(TEXTURE_TYPE_LAYERED);
BIND_ENUM_CONSTANT(TEXTURE_TYPE_3D);
BIND_ENUM_CONSTANT(TEXTURE_LAYERED_2D_ARRAY);
BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP);
BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP_ARRAY);

View file

@ -113,6 +113,12 @@ public:
/* TEXTURE API */
enum TextureType {
TEXTURE_TYPE_2D,
TEXTURE_TYPE_LAYERED,
TEXTURE_TYPE_3D,
};
enum TextureLayeredType {
TEXTURE_LAYERED_2D_ARRAY,
TEXTURE_LAYERED_CUBEMAP,
@ -133,6 +139,8 @@ public:
virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; //all slices, then all the mipmaps, must be coherent
virtual RID texture_proxy_create(RID p_base) = 0;
virtual RID texture_create_from_native_handle(TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, TextureLayeredType p_layered_type = TEXTURE_LAYERED_2D_ARRAY) = 0;
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0;
virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0;
@ -1793,6 +1801,7 @@ private:
};
// Make variant understand the enums.
VARIANT_ENUM_CAST(RenderingServer::TextureType);
VARIANT_ENUM_CAST(RenderingServer::TextureLayeredType);
VARIANT_ENUM_CAST(RenderingServer::CubeMapLayer);
VARIANT_ENUM_CAST(RenderingServer::ShaderMode);