diff --git a/bindings/bf/bgfx.bf b/bindings/bf/bgfx.bf index 5c88429f5..207530bd8 100644 --- a/bindings/bf/bgfx.bf +++ b/bindings/bf/bgfx.bf @@ -4527,6 +4527,23 @@ public static class bgfx [LinkName("bgfx_encoder_set_texture")] public static extern void encoder_set_texture(Encoder* _this, uint8 _stage, UniformHandle _sampler, TextureHandle _handle, uint32 _flags); + /// + /// Set texture stage for draw primitive, selecting a sub-range of the + /// texture's array layers and mip levels. + /// + /// + /// Texture unit. + /// Program sampler. + /// Texture handle. + /// First array layer. + /// Number of array layers. + /// First (most detailed) mip level. + /// Number of mip levels. + /// Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. + /// + [LinkName("bgfx_encoder_set_texture_view")] + public static extern void encoder_set_texture_view(Encoder* _this, uint8 _stage, UniformHandle _sampler, TextureHandle _handle, uint16 _firstLayer, uint16 _numLayers, uint8 _firstMip, uint8 _numMips, uint32 _flags); + /// /// Submit an empty primitive for rendering. Uniforms and draw state /// will be applied but no geometry will be submitted. Useful in cases @@ -5173,6 +5190,23 @@ public static class bgfx [LinkName("bgfx_set_texture")] public static extern void set_texture(uint8 _stage, UniformHandle _sampler, TextureHandle _handle, uint32 _flags); + /// + /// Set texture stage for draw primitive, selecting a sub-range of the + /// texture's array layers and mip levels. + /// + /// + /// Texture unit. + /// Program sampler. + /// Texture handle. + /// First array layer. + /// Number of array layers. + /// First (most detailed) mip level. + /// Number of mip levels. + /// Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. + /// + [LinkName("bgfx_set_texture_view")] + public static extern void set_texture_view(uint8 _stage, UniformHandle _sampler, TextureHandle _handle, uint16 _firstLayer, uint16 _numLayers, uint8 _firstMip, uint8 _numMips, uint32 _flags); + /// /// Submit an empty primitive for rendering. Uniforms and draw state /// will be applied but no geometry will be submitted. diff --git a/bindings/c3/bgfx.c3 b/bindings/c3/bgfx.c3 index 5157359c5..16765ce91 100644 --- a/bindings/c3/bgfx.c3 +++ b/bindings/c3/bgfx.c3 @@ -3136,6 +3136,18 @@ extern fn void encoder_set_instance_count(Encoder* _this, uint _numInstances) @c // _flags : `Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling.` extern fn void encoder_set_texture(Encoder* _this, char _stage, UniformHandle _sampler, TextureHandle _handle, uint _flags) @cname("bgfx_encoder_set_texture"); +// Set texture stage for draw primitive, selecting a sub-range of the +// texture's array layers and mip levels. +// _stage : `Texture unit.` +// _sampler : `Program sampler.` +// _handle : `Texture handle.` +// _firstLayer : `First array layer.` +// _numLayers : `Number of array layers.` +// _firstMip : `First (most detailed) mip level.` +// _numMips : `Number of mip levels.` +// _flags : `Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling.` +extern fn void encoder_set_texture_view(Encoder* _this, char _stage, UniformHandle _sampler, TextureHandle _handle, ushort _firstLayer, ushort _numLayers, char _firstMip, char _numMips, uint _flags) @extern("bgfx_encoder_set_texture_view"); + // Submit an empty primitive for rendering. Uniforms and draw state // will be applied but no geometry will be submitted. Useful in cases // when no other draw/compute primitive is submitted to view, but it's @@ -3553,6 +3565,18 @@ extern fn void set_instance_count(uint _numInstances) @cname("bgfx_set_instance_ // _flags : `Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling.` extern fn void set_texture(char _stage, UniformHandle _sampler, TextureHandle _handle, uint _flags) @cname("bgfx_set_texture"); +// Set texture stage for draw primitive, selecting a sub-range of the +// texture's array layers and mip levels. +// _stage : `Texture unit.` +// _sampler : `Program sampler.` +// _handle : `Texture handle.` +// _firstLayer : `First array layer.` +// _numLayers : `Number of array layers.` +// _firstMip : `First (most detailed) mip level.` +// _numMips : `Number of mip levels.` +// _flags : `Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling.` +extern fn void set_texture_view(char _stage, UniformHandle _sampler, TextureHandle _handle, ushort _firstLayer, ushort _numLayers, char _firstMip, char _numMips, uint _flags) @extern("bgfx_set_texture_view"); + // Submit an empty primitive for rendering. Uniforms and draw state // will be applied but no geometry will be submitted. // diff --git a/bindings/cs/bgfx.cs b/bindings/cs/bgfx.cs index d3de03d7c..85f839b7a 100644 --- a/bindings/cs/bgfx.cs +++ b/bindings/cs/bgfx.cs @@ -4480,6 +4480,23 @@ public static partial class bgfx [DllImport(DllName, EntryPoint="bgfx_encoder_set_texture", CallingConvention = CallingConvention.Cdecl)] public static extern unsafe void encoder_set_texture(Encoder* _this, byte _stage, UniformHandle _sampler, TextureHandle _handle, uint _flags); + /// + /// Set texture stage for draw primitive, selecting a sub-range of the + /// texture's array layers and mip levels. + /// + /// + /// Texture unit. + /// Program sampler. + /// Texture handle. + /// First array layer. + /// Number of array layers. + /// First (most detailed) mip level. + /// Number of mip levels. + /// Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. + /// + [DllImport(DllName, EntryPoint="bgfx_encoder_set_texture_view", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe void encoder_set_texture_view(Encoder* _this, byte _stage, UniformHandle _sampler, TextureHandle _handle, ushort _firstLayer, ushort _numLayers, byte _firstMip, byte _numMips, uint _flags); + /// /// Submit an empty primitive for rendering. Uniforms and draw state /// will be applied but no geometry will be submitted. Useful in cases @@ -5126,6 +5143,23 @@ public static partial class bgfx [DllImport(DllName, EntryPoint="bgfx_set_texture", CallingConvention = CallingConvention.Cdecl)] public static extern unsafe void set_texture(byte _stage, UniformHandle _sampler, TextureHandle _handle, uint _flags); + /// + /// Set texture stage for draw primitive, selecting a sub-range of the + /// texture's array layers and mip levels. + /// + /// + /// Texture unit. + /// Program sampler. + /// Texture handle. + /// First array layer. + /// Number of array layers. + /// First (most detailed) mip level. + /// Number of mip levels. + /// Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. + /// + [DllImport(DllName, EntryPoint="bgfx_set_texture_view", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe void set_texture_view(byte _stage, UniformHandle _sampler, TextureHandle _handle, ushort _firstLayer, ushort _numLayers, byte _firstMip, byte _numMips, uint _flags); + /// /// Submit an empty primitive for rendering. Uniforms and draw state /// will be applied but no geometry will be submitted. diff --git a/bindings/d/package.d b/bindings/d/package.d index 81c4f501d..2e44da2c5 100644 --- a/bindings/d/package.d +++ b/bindings/d/package.d @@ -9,7 +9,7 @@ import bindbc.common.types: c_int64, c_uint64, va_list; import bindbc.bgfx.config; static import bgfx.impl; -enum uint apiVersion = 143; +enum uint apiVersion = 144; alias ViewID = ushort; @@ -1772,6 +1772,26 @@ extern(C++, "bgfx") struct Encoder{ */ {q{void}, q{setTexture}, q{ubyte stage, UniformHandle sampler, TextureHandle handle, uint flags=uint.max}, ext: `C++`}, + /** + Set texture stage for draw primitive, selecting a sub-range of the + texture's array layers and mip levels. + Params: + stage = Texture unit. + sampler = Program sampler. + handle = Texture handle. + firstLayer = First array layer. + numLayers = Number of array layers. + firstMIP = First (most detailed) mip level. + numMIPs = Number of mip levels. + flags = Texture sampling mode. Default value UINT32_MAX uses + texture sampling settings from the texture. + - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap + mode. + - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic + sampling. + */ + {q{void}, q{setTexture}, q{ubyte stage, UniformHandle sampler, TextureHandle handle, ushort firstLayer, ushort numLayers, ubyte firstMIP, ubyte numMIPs, uint flags=uint.max}, ext: `C++`}, + /** Submit an empty primitive for rendering. Uniforms and draw state will be applied but no geometry will be submitted. Useful in cases @@ -3726,6 +3746,26 @@ mixin(joinFnBinds((){ */ {q{void}, q{setTexture}, q{ubyte stage, UniformHandle sampler, TextureHandle handle, uint flags=uint.max}, ext: `C++, "bgfx"`}, + /** + * Set texture stage for draw primitive, selecting a sub-range of the + * texture's array layers and mip levels. + Params: + stage = Texture unit. + sampler = Program sampler. + handle = Texture handle. + firstLayer = First array layer. + numLayers = Number of array layers. + firstMIP = First (most detailed) mip level. + numMIPs = Number of mip levels. + flags = Texture sampling mode. Default value UINT32_MAX uses + texture sampling settings from the texture. + - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap + mode. + - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic + sampling. + */ + {q{void}, q{setTexture}, q{ubyte stage, UniformHandle sampler, TextureHandle handle, ushort firstLayer, ushort numLayers, ubyte firstMIP, ubyte numMIPs, uint flags=uint.max}, ext: `C++, "bgfx"`}, + /** * Submit an empty primitive for rendering. Uniforms and draw state * will be applied but no geometry will be submitted. diff --git a/bindings/zig/bgfx.zig b/bindings/zig/bgfx.zig index b6e303468..814d13ccb 100644 --- a/bindings/zig/bgfx.zig +++ b/bindings/zig/bgfx.zig @@ -1962,6 +1962,19 @@ pub const Init = extern struct { pub inline fn setTexture(self: ?*Encoder, _stage: u8, _sampler: UniformHandle, _handle: TextureHandle, _flags: u32) void { return bgfx_encoder_set_texture(self, _stage, _sampler, _handle, _flags); } + /// Set texture stage for draw primitive, selecting a sub-range of the + /// texture's array layers and mip levels. + /// Texture unit. + /// Program sampler. + /// Texture handle. + /// First array layer. + /// Number of array layers. + /// First (most detailed) mip level. + /// Number of mip levels. + /// Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. + pub inline fn setTextureView(self: ?*Encoder, _stage: u8, _sampler: UniformHandle, _handle: TextureHandle, _firstLayer: u16, _numLayers: u16, _firstMip: u8, _numMips: u8, _flags: u32) void { + return bgfx_encoder_set_texture_view(self, _stage, _sampler, _handle, _firstLayer, _numLayers, _firstMip, _numMips, _flags); + } /// Submit an empty primitive for rendering. Uniforms and draw state /// will be applied but no geometry will be submitted. Useful in cases /// when no other draw/compute primitive is submitted to view, but it's @@ -3537,6 +3550,18 @@ extern fn bgfx_encoder_set_instance_count(self: ?*Encoder, _numInstances: u32) v /// Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. extern fn bgfx_encoder_set_texture(self: ?*Encoder, _stage: u8, _sampler: UniformHandle, _handle: TextureHandle, _flags: u32) void; +/// Set texture stage for draw primitive, selecting a sub-range of the +/// texture's array layers and mip levels. +/// Texture unit. +/// Program sampler. +/// Texture handle. +/// First array layer. +/// Number of array layers. +/// First (most detailed) mip level. +/// Number of mip levels. +/// Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. +extern fn bgfx_encoder_set_texture_view(self: ?*Encoder, _stage: u8, _sampler: UniformHandle, _handle: TextureHandle, _firstLayer: u16, _numLayers: u16, _firstMip: u8, _numMips: u8, _flags: u32) void; + /// Submit an empty primitive for rendering. Uniforms and draw state /// will be applied but no geometry will be submitted. Useful in cases /// when no other draw/compute primitive is submitted to view, but it's @@ -4047,6 +4072,21 @@ pub inline fn setTexture(_stage: u8, _sampler: UniformHandle, _handle: TextureHa } extern fn bgfx_set_texture(_stage: u8, _sampler: UniformHandle, _handle: TextureHandle, _flags: u32) void; +/// Set texture stage for draw primitive, selecting a sub-range of the +/// texture's array layers and mip levels. +/// Texture unit. +/// Program sampler. +/// Texture handle. +/// First array layer. +/// Number of array layers. +/// First (most detailed) mip level. +/// Number of mip levels. +/// Texture sampling mode. Default value UINT32_MAX uses texture sampling settings from the texture. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. +pub inline fn setTextureView(_stage: u8, _sampler: UniformHandle, _handle: TextureHandle, _firstLayer: u16, _numLayers: u16, _firstMip: u8, _numMips: u8, _flags: u32) void { + return bgfx_set_texture_view(_stage, _sampler, _handle, _firstLayer, _numLayers, _firstMip, _numMips, _flags); +} +extern fn bgfx_set_texture_view(_stage: u8, _sampler: UniformHandle, _handle: TextureHandle, _firstLayer: u16, _numLayers: u16, _firstMip: u8, _numMips: u8, _flags: u32) void; + /// Submit an empty primitive for rendering. Uniforms and draw state /// will be applied but no geometry will be submitted. /// diff --git a/docs/bgfx.rst b/docs/bgfx.rst index 1c67f6454..6fd9fa0f4 100644 --- a/docs/bgfx.rst +++ b/docs/bgfx.rst @@ -454,7 +454,8 @@ Textures Bind textures to texture stages for draw calls. -.. doxygenfunction:: bgfx::setTexture +.. doxygenfunction:: bgfx::setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint32_t _flags = UINT32_MAX) +.. doxygenfunction:: bgfx::setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags = UINT32_MAX) Uniforms ******** diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index 5c346adbd..67a4d31eb 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -1401,6 +1401,36 @@ namespace bgfx , uint32_t _flags = UINT32_MAX ); + /// Set texture stage for draw primitive, selecting a sub-range of the + /// texture's array layers and mip levels. + /// + /// @param[in] _stage Texture unit. + /// @param[in] _sampler Program sampler. + /// @param[in] _handle Texture handle. + /// @param[in] _firstLayer First array layer. + /// @param[in] _numLayers Number of array layers. + /// @param[in] _firstMip First (most detailed) mip level. + /// @param[in] _numMips Number of mip levels. + /// @param[in] _flags Texture sampling mode. Default value UINT32_MAX uses + /// texture sampling settings from the texture. + /// - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap + /// mode. + /// - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic + /// sampling. + /// + /// @attention C99's equivalent binding is `bgfx_encoder_set_texture_view`. + /// + void setTexture( + uint8_t _stage + , UniformHandle _sampler + , TextureHandle _handle + , uint16_t _firstLayer + , uint16_t _numLayers + , uint8_t _firstMip + , uint8_t _numMips + , uint32_t _flags = UINT32_MAX + ); + /// Submit an empty primitive for rendering. Uniforms and draw state /// will be applied but no geometry will be submitted. Useful in cases /// when no other draw/compute primitive is submitted to view, but it's @@ -4358,6 +4388,36 @@ namespace bgfx , uint32_t _flags = UINT32_MAX ); + /// Set texture stage for draw primitive, selecting a sub-range of the + /// texture's array layers and mip levels. + /// + /// @param[in] _stage Texture unit. + /// @param[in] _sampler Program sampler. + /// @param[in] _handle Texture handle. + /// @param[in] _firstLayer First array layer. + /// @param[in] _numLayers Number of array layers. + /// @param[in] _firstMip First (most detailed) mip level. + /// @param[in] _numMips Number of mip levels. + /// @param[in] _flags Texture sampling mode. Default value UINT32_MAX uses + /// texture sampling settings from the texture. + /// - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap + /// mode. + /// - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic + /// sampling. + /// + /// @attention C99's equivalent binding is `bgfx_set_texture_view`. + /// + void setTexture( + uint8_t _stage + , UniformHandle _sampler + , TextureHandle _handle + , uint16_t _firstLayer + , uint16_t _numLayers + , uint8_t _firstMip + , uint8_t _numMips + , uint32_t _flags = UINT32_MAX + ); + /// Submit an empty primitive for rendering. Uniforms and draw state /// will be applied but no geometry will be submitted. /// diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h index 6169ad6b9..1fb5c9f98 100644 --- a/include/bgfx/c99/bgfx.h +++ b/include/bgfx/c99/bgfx.h @@ -2919,6 +2919,27 @@ BGFX_C_API void bgfx_encoder_set_instance_count(bgfx_encoder_t* _this, uint32_t */ BGFX_C_API void bgfx_encoder_set_texture(bgfx_encoder_t* _this, uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint32_t _flags); +/** + * Set texture stage for draw primitive, selecting a sub-range of the + * texture's array layers and mip levels. + * + * @param[in] _stage Texture unit. + * @param[in] _sampler Program sampler. + * @param[in] _handle Texture handle. + * @param[in] _firstLayer First array layer. + * @param[in] _numLayers Number of array layers. + * @param[in] _firstMip First (most detailed) mip level. + * @param[in] _numMips Number of mip levels. + * @param[in] _flags Texture sampling mode. Default value UINT32_MAX uses + * texture sampling settings from the texture. + * - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap + * mode. + * - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic + * sampling. + * + */ +BGFX_C_API void bgfx_encoder_set_texture_view(bgfx_encoder_t* _this, uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags); + /** * Submit an empty primitive for rendering. Uniforms and draw state * will be applied but no geometry will be submitted. Useful in cases @@ -3553,6 +3574,27 @@ BGFX_C_API void bgfx_set_instance_count(uint32_t _numInstances); */ BGFX_C_API void bgfx_set_texture(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint32_t _flags); +/** + * Set texture stage for draw primitive, selecting a sub-range of the + * texture's array layers and mip levels. + * + * @param[in] _stage Texture unit. + * @param[in] _sampler Program sampler. + * @param[in] _handle Texture handle. + * @param[in] _firstLayer First array layer. + * @param[in] _numLayers Number of array layers. + * @param[in] _firstMip First (most detailed) mip level. + * @param[in] _numMips Number of mip levels. + * @param[in] _flags Texture sampling mode. Default value UINT32_MAX uses + * texture sampling settings from the texture. + * - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap + * mode. + * - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic + * sampling. + * + */ +BGFX_C_API void bgfx_set_texture_view(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags); + /** * Submit an empty primitive for rendering. Uniforms and draw state * will be applied but no geometry will be submitted. @@ -3893,6 +3935,7 @@ typedef enum bgfx_function_id BGFX_FUNCTION_ID_ENCODER_SET_INSTANCE_DATA_FROM_DYNAMIC_VERTEX_BUFFER, BGFX_FUNCTION_ID_ENCODER_SET_INSTANCE_COUNT, BGFX_FUNCTION_ID_ENCODER_SET_TEXTURE, + BGFX_FUNCTION_ID_ENCODER_SET_TEXTURE_VIEW, BGFX_FUNCTION_ID_ENCODER_TOUCH, BGFX_FUNCTION_ID_ENCODER_SUBMIT, BGFX_FUNCTION_ID_ENCODER_SUBMIT_OCCLUSION_QUERY, @@ -3939,6 +3982,7 @@ typedef enum bgfx_function_id BGFX_FUNCTION_ID_SET_INSTANCE_DATA_FROM_DYNAMIC_VERTEX_BUFFER, BGFX_FUNCTION_ID_SET_INSTANCE_COUNT, BGFX_FUNCTION_ID_SET_TEXTURE, + BGFX_FUNCTION_ID_SET_TEXTURE_VIEW, BGFX_FUNCTION_ID_TOUCH, BGFX_FUNCTION_ID_SUBMIT, BGFX_FUNCTION_ID_SUBMIT_OCCLUSION_QUERY, @@ -4102,6 +4146,7 @@ struct bgfx_interface_vtbl void (*encoder_set_instance_data_from_dynamic_vertex_buffer)(bgfx_encoder_t* _this, bgfx_dynamic_vertex_buffer_handle_t _handle, uint32_t _startVertex, uint32_t _num); void (*encoder_set_instance_count)(bgfx_encoder_t* _this, uint32_t _numInstances); void (*encoder_set_texture)(bgfx_encoder_t* _this, uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint32_t _flags); + void (*encoder_set_texture_view)(bgfx_encoder_t* _this, uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags); void (*encoder_touch)(bgfx_encoder_t* _this, bgfx_view_id_t _id); void (*encoder_submit)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, uint8_t _flags); void (*encoder_submit_occlusion_query)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, uint8_t _flags); @@ -4148,6 +4193,7 @@ struct bgfx_interface_vtbl void (*set_instance_data_from_dynamic_vertex_buffer)(bgfx_dynamic_vertex_buffer_handle_t _handle, uint32_t _startVertex, uint32_t _num); void (*set_instance_count)(uint32_t _numInstances); void (*set_texture)(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint32_t _flags); + void (*set_texture_view)(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags); void (*touch)(bgfx_view_id_t _id); void (*submit)(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _depth, uint8_t _flags); void (*submit_occlusion_query)(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, uint32_t _depth, uint8_t _flags); diff --git a/include/bgfx/defines.h b/include/bgfx/defines.h index faccff44c..e741a97c4 100644 --- a/include/bgfx/defines.h +++ b/include/bgfx/defines.h @@ -15,7 +15,7 @@ #ifndef BGFX_DEFINES_H_HEADER_GUARD #define BGFX_DEFINES_H_HEADER_GUARD -#define BGFX_API_VERSION UINT32_C(143) +#define BGFX_API_VERSION UINT32_C(144) /** * Color RGB/alpha/depth write. When it's not specified write will be disabled. diff --git a/scripts/bgfx.idl b/scripts/bgfx.idl index 610e33847..855fbf962 100644 --- a/scripts/bgfx.idl +++ b/scripts/bgfx.idl @@ -1,7 +1,7 @@ -- vim: syntax=lua -- bgfx interface -version(143) +version(144) typedef "bool" typedef "char" @@ -2617,6 +2617,24 @@ func.Encoder.setTexture { section = "Draw/Textures" } --- - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic --- sampling. +--- Set texture stage for draw primitive, selecting a sub-range of the +--- texture's array layers and mip levels. +func.Encoder.setTexture { cname = "set_texture_view", section = "Draw/Textures" } + "void" + .stage "uint8_t" --- Texture unit. + .sampler "UniformHandle" --- Program sampler. + .handle "TextureHandle" --- Texture handle. + .firstLayer "uint16_t" --- First array layer. + .numLayers "uint16_t" --- Number of array layers. + .firstMip "uint8_t" --- First (most detailed) mip level. + .numMips "uint8_t" --- Number of mip levels. + .flags "uint32_t" --- Texture sampling mode. Default value UINT32_MAX uses + { default = UINT32_MAX } --- texture sampling settings from the texture. + --- - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap + --- mode. + --- - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic + --- sampling. + --- Submit an empty primitive for rendering. Uniforms and draw state --- will be applied but no geometry will be submitted. Useful in cases --- when no other draw/compute primitive is submitted to view, but it's @@ -3220,6 +3238,24 @@ func.setTexture { section = "Draw/Textures" } --- - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic --- sampling. +--- Set texture stage for draw primitive, selecting a sub-range of the +--- texture's array layers and mip levels. +func.setTexture { cname = "set_texture_view", section = "Draw/Textures" } + "void" + .stage "uint8_t" --- Texture unit. + .sampler "UniformHandle" --- Program sampler. + .handle "TextureHandle" --- Texture handle. + .firstLayer "uint16_t" --- First array layer. + .numLayers "uint16_t" --- Number of array layers. + .firstMip "uint8_t" --- First (most detailed) mip level. + .numMips "uint8_t" --- Number of mip levels. + .flags "uint32_t" --- Texture sampling mode. Default value UINT32_MAX uses + { default = UINT32_MAX } --- texture sampling settings from the texture. + --- - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap + --- mode. + --- - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic + --- sampling. + --- Submit an empty primitive for rendering. Uniforms and draw state --- will be applied but no geometry will be submitted. --- diff --git a/src/bgfx.cpp b/src/bgfx.cpp index ae4190c1b..7c203f509 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -4183,6 +4183,24 @@ namespace bgfx BGFX_ENCODER(setTexture(_stage, _sampler, _handle, _flags) ); } + void Encoder::setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags) + { + BGFX_CHECK_HANDLE("setTexture/UniformHandle", s_ctx->m_uniformHandle, _sampler); + BGFX_CHECK_HANDLE_INVALID_OK("setTexture/TextureHandle", s_ctx->m_textureHandle, _handle); + BX_ASSERT(_stage < g_caps.limits.maxTextureSamplers, "Invalid stage %d (max %d).", _stage, g_caps.limits.maxTextureSamplers); + + if (isValid(_handle) ) + { + const TextureRef& ref = s_ctx->m_textureRef[_handle.idx]; + BX_ASSERT(!ref.isReadBack() + , "Can't sample from texture which was created with BGFX_TEXTURE_READ_BACK. This is CPU only texture." + ); + BX_UNUSED(ref); + } + + BGFX_ENCODER(setTexture(_stage, _sampler, _handle, _firstLayer, _numLayers, _firstMip, _numMips, _flags) ); + } + void Encoder::touch(ViewId _id) { discard(); @@ -5884,6 +5902,12 @@ namespace bgfx s_ctx->m_encoder0->setTexture(_stage, _sampler, _handle, _flags); } + void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags) + { + BGFX_CHECK_ENCODER0(); + s_ctx->m_encoder0->setTexture(_stage, _sampler, _handle, _firstLayer, _numLayers, _firstMip, _numMips, _flags); + } + void touch(ViewId _id) { BGFX_CHECK_ENCODER0(); diff --git a/src/bgfx.idl.inl b/src/bgfx.idl.inl index b28a39916..ad1e6b4a3 100644 --- a/src/bgfx.idl.inl +++ b/src/bgfx.idl.inl @@ -897,6 +897,14 @@ BGFX_C_API void bgfx_encoder_set_texture(bgfx_encoder_t* _this, uint8_t _stage, This->setTexture(_stage, sampler.cpp, handle.cpp, _flags); } +BGFX_C_API void bgfx_encoder_set_texture_view(bgfx_encoder_t* _this, uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags) +{ + bgfx::Encoder* This = (bgfx::Encoder*)_this; + union { bgfx_uniform_handle_t c; bgfx::UniformHandle cpp; } sampler = { _sampler }; + union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } handle = { _handle }; + This->setTexture(_stage, sampler.cpp, handle.cpp, _firstLayer, _numLayers, _firstMip, _numMips, _flags); +} + BGFX_C_API void bgfx_encoder_touch(bgfx_encoder_t* _this, bgfx_view_id_t _id) { bgfx::Encoder* This = (bgfx::Encoder*)_this; @@ -1180,6 +1188,13 @@ BGFX_C_API void bgfx_set_texture(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx::setTexture(_stage, sampler.cpp, handle.cpp, _flags); } +BGFX_C_API void bgfx_set_texture_view(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags) +{ + union { bgfx_uniform_handle_t c; bgfx::UniformHandle cpp; } sampler = { _sampler }; + union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } handle = { _handle }; + bgfx::setTexture(_stage, sampler.cpp, handle.cpp, _firstLayer, _numLayers, _firstMip, _numMips, _flags); +} + BGFX_C_API void bgfx_touch(bgfx_view_id_t _id) { bgfx::touch((bgfx::ViewId)_id); @@ -1454,6 +1469,7 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version) bgfx_encoder_set_instance_data_from_dynamic_vertex_buffer, bgfx_encoder_set_instance_count, bgfx_encoder_set_texture, + bgfx_encoder_set_texture_view, bgfx_encoder_touch, bgfx_encoder_submit, bgfx_encoder_submit_occlusion_query, @@ -1500,6 +1516,7 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version) bgfx_set_instance_data_from_dynamic_vertex_buffer, bgfx_set_instance_count, bgfx_set_texture, + bgfx_set_texture_view, bgfx_touch, bgfx_submit, bgfx_submit_occlusion_query, diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 8ecde77c0..aba1a67c4 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -1799,12 +1799,93 @@ namespace bgfx Count }; + void reset() + { + m_samplerFlags = BGFX_SAMPLER_NONE; + m_firstLayer = 0; + m_numLayers = UINT16_MAX; + m_idx = kInvalidHandle; + m_type = 0; + m_format = 0; + m_access = 0; + m_firstMip = 0; + m_numMips = UINT8_MAX; + } + + void setTexture(TextureHandle _handle, uint32_t _samplerFlags, uint8_t _firstMip = 0, uint8_t _numMips = UINT8_MAX) + { + m_samplerFlags = _samplerFlags; + m_firstLayer = 0; + m_numLayers = UINT16_MAX; + m_idx = _handle.idx; + m_type = uint8_t(Binding::Texture); + m_format = 0; + m_access = 0; + m_firstMip = _firstMip; + m_numMips = _numMips; + } + + void setTexture(TextureHandle _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _samplerFlags) + { + m_samplerFlags = _samplerFlags; + m_firstLayer = _firstLayer; + m_numLayers = _numLayers; + m_idx = _handle.idx; + m_type = uint8_t(Binding::Texture); + m_format = 0; + m_access = 0; + m_firstMip = _firstMip; + m_numMips = _numMips; + } + + void setIndexBuffer(IndexBufferHandle _handle, Access::Enum _access) + { + m_samplerFlags = BGFX_SAMPLER_NONE; + m_firstLayer = 0; + m_numLayers = UINT16_MAX; + m_idx = _handle.idx; + m_type = uint8_t(Binding::IndexBuffer); + m_format = 0; + m_access = uint8_t(_access); + m_firstMip = 0; + m_numMips = UINT8_MAX; + } + + void setBuffer(VertexBufferHandle _handle, Access::Enum _access) + { + m_samplerFlags = BGFX_SAMPLER_NONE; + m_firstLayer = 0; + m_numLayers = UINT16_MAX; + m_idx = _handle.idx; + m_type = uint8_t(Binding::VertexBuffer); + m_format = 0; + m_access = uint8_t(_access); + m_firstMip = 0; + m_numMips = UINT8_MAX; + } + + void setImage(TextureHandle _handle, uint8_t _mip, Access::Enum _access, TextureFormat::Enum _format) + { + m_samplerFlags = BGFX_SAMPLER_NONE; + m_firstLayer = 0; + m_numLayers = UINT16_MAX; + m_idx = _handle.idx; + m_type = uint8_t(Binding::Image); + m_format = uint8_t(_format); + m_access = uint8_t(_access); + m_firstMip = _mip; + m_numMips = 1; + } + uint32_t m_samplerFlags; + uint16_t m_firstLayer; + uint16_t m_numLayers; uint16_t m_idx; uint8_t m_type; uint8_t m_format; uint8_t m_access; - uint8_t m_mip; + uint8_t m_firstMip; + uint8_t m_numMips; }; struct Stream @@ -1830,12 +1911,8 @@ namespace bgfx for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++ii) { Binding& bind = m_bind[ii]; - bind.m_idx = kInvalidHandle; - bind.m_type = 0; - bind.m_samplerFlags = 0; - bind.m_format = 0; - bind.m_access = 0; - bind.m_mip = 0; + bind.reset(); + } } }; @@ -3035,15 +3112,33 @@ namespace bgfx void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint32_t _flags) { Binding& bind = m_bind.m_bind[_stage]; - bind.m_idx = _handle.idx; - bind.m_type = uint8_t(Binding::Texture); - bind.m_samplerFlags = (_flags&BGFX_SAMPLER_INTERNAL_DEFAULT) - ? BGFX_SAMPLER_INTERNAL_DEFAULT - : _flags - ; - bind.m_format = 0; - bind.m_access = 0; - bind.m_mip = 0; + bind.setTexture( + _handle + , 0 != (_flags&BGFX_SAMPLER_INTERNAL_DEFAULT) + ? BGFX_SAMPLER_INTERNAL_DEFAULT + : _flags + ); + + if (isValid(_sampler) ) + { + uint32_t stage = _stage; + setUniform(UniformType::Sampler, _sampler, &stage, 1); + } + } + + void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips, uint32_t _flags) + { + Binding& bind = m_bind.m_bind[_stage]; + bind.setTexture( + _handle + , _firstLayer + , _numLayers + , _firstMip + , _numMips + , 0 != (_flags&BGFX_SAMPLER_INTERNAL_DEFAULT) + ? BGFX_SAMPLER_INTERNAL_DEFAULT + : _flags + ); if (isValid(_sampler) ) { @@ -3055,31 +3150,19 @@ namespace bgfx void setBuffer(uint8_t _stage, IndexBufferHandle _handle, Access::Enum _access) { Binding& bind = m_bind.m_bind[_stage]; - bind.m_idx = _handle.idx; - bind.m_type = uint8_t(Binding::IndexBuffer); - bind.m_format = 0; - bind.m_access = uint8_t(_access); - bind.m_mip = 0; + bind.setIndexBuffer(_handle, _access); } void setBuffer(uint8_t _stage, VertexBufferHandle _handle, Access::Enum _access) { Binding& bind = m_bind.m_bind[_stage]; - bind.m_idx = _handle.idx; - bind.m_type = uint8_t(Binding::VertexBuffer); - bind.m_format = 0; - bind.m_access = uint8_t(_access); - bind.m_mip = 0; + bind.setBuffer(_handle, _access); } void setImage(uint8_t _stage, TextureHandle _handle, uint8_t _mip, Access::Enum _access, TextureFormat::Enum _format) { Binding& bind = m_bind.m_bind[_stage]; - bind.m_idx = _handle.idx; - bind.m_type = uint8_t(Binding::Image); - bind.m_format = uint8_t(_format); - bind.m_access = uint8_t(_access); - bind.m_mip = _mip; + bind.setImage(_handle, _mip, _access, _format); } void discard(uint8_t _flags) diff --git a/src/glimports.h b/src/glimports.h index e3a22ba49..c74a3e6e6 100644 --- a/src/glimports.h +++ b/src/glimports.h @@ -205,6 +205,7 @@ typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsi typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); @@ -407,6 +408,7 @@ GL_IMPORT______(true, PFNGLTEXSTORAGE2DPROC, glTexStorage2 GL_IMPORT______(true, PFNGLTEXSTORAGE3DPROC, glTexStorage3D); GL_IMPORT______(false, PFNGLTEXSUBIMAGE2DPROC, glTexSubImage2D); GL_IMPORT______(true, PFNGLTEXSUBIMAGE3DPROC, glTexSubImage3D); +GL_IMPORT______(true, PFNGLTEXTUREVIEWPROC, glTextureView); GL_IMPORT______(false, PFNGLUNIFORM1IPROC, glUniform1i); GL_IMPORT______(false, PFNGLUNIFORM1IVPROC, glUniform1iv); GL_IMPORT______(false, PFNGLUNIFORM1FPROC, glUniform1f); @@ -534,8 +536,8 @@ GL_IMPORT_OES__(true, PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedT GL_IMPORT_EXT__(true, PFNGLTEXSTORAGE2DPROC, glTexStorage2D); GL_IMPORT_EXT__(true, PFNGLTEXSTORAGE3DPROC, glTexStorage3D); +GL_IMPORT_EXT__(true, PFNGLTEXTUREVIEWPROC, glTextureView); GL_IMPORT______(true, PFNGLTEXIMAGE2DMULTISAMPLEPROC, glTexImage2DMultisample); -GL_IMPORT______(true, PFNGLTEXIMAGE3DMULTISAMPLEPROC, glTexImage3DMultisample); GL_IMPORT_EXT__(true, PFNGLFRAMEBUFFERTEXTUREPROC, glFramebufferTexture); GL_IMPORT_EXT__(true, PFNGLFRAMEBUFFERTEXTURELAYERPROC, glFramebufferTextureLayer); @@ -630,6 +632,7 @@ GL_IMPORT______(true, PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedT GL_IMPORT______(true, PFNGLTEXSTORAGE2DPROC, glTexStorage2D); GL_IMPORT______(true, PFNGLTEXSTORAGE3DPROC, glTexStorage3D); +GL_IMPORT______(true, PFNGLTEXTUREVIEWPROC, glTextureView); GL_IMPORT______(true, PFNGLTEXIMAGE2DMULTISAMPLEPROC, glTexImage2DMultisample); GL_IMPORT______(true, PFNGLTEXIMAGE3DMULTISAMPLEPROC, glTexImage3DMultisample); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index c46333935..d7522cc0d 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -3305,12 +3305,20 @@ namespace bgfx { namespace d3d11 return uav; } - ID3D11ShaderResourceView* getCachedSrv(TextureHandle _handle, uint8_t _mip, bool _compute = false, bool _stencil = false) + ID3D11ShaderResourceView* getCachedSrv(TextureHandle _handle, uint8_t _firstMip, uint8_t _numMips = 1, uint16_t _firstLayer = 0, uint16_t _numLayers = UINT16_MAX, bool _compute = false, bool _stencil = false) { + const TextureD3D11& texture = m_textures[_handle.idx]; + + const uint8_t numMips = bx::min(_numMips, uint8_t(texture.m_numMips - _firstMip) ); + const uint16_t numLayers = bx::min(_numLayers, uint16_t(texture.m_numLayers - _firstLayer) ); + bx::HashMurmur2A murmur; murmur.begin(); murmur.add(_handle); - murmur.add(_mip); + murmur.add(_firstMip); + murmur.add(numMips); + murmur.add(_firstLayer); + murmur.add(numLayers); murmur.add(0); murmur.add(_compute); murmur.add(_stencil); @@ -3320,13 +3328,16 @@ namespace bgfx { namespace d3d11 ID3D11ShaderResourceView* srv; if (NULL == ptr) { - const TextureD3D11& texture = m_textures[_handle.idx]; const uint32_t msaaQuality = bx::satSub(uint32_t( (texture.m_flags&BGFX_TEXTURE_RT_MSAA_MASK) >> BGFX_TEXTURE_RT_MSAA_SHIFT ), 1u); const DXGI_SAMPLE_DESC& msaa = s_msaa[msaaQuality]; const bool msaaSample = 1 < msaa.Count && 0 != (texture.m_flags&BGFX_TEXTURE_MSAA_SAMPLE); D3D11_SHADER_RESOURCE_VIEW_DESC desc; - desc.Format = _stencil ? DXGI_FORMAT_X24_TYPELESS_G8_UINT : texture.getSrvFormat(); + desc.Format = _stencil + ? DXGI_FORMAT_X24_TYPELESS_G8_UINT + : texture.getSrvFormat() + ; + switch (texture.m_type) { case TextureD3D11::Texture2D: @@ -3336,10 +3347,10 @@ namespace bgfx { namespace d3d11 ? D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY : D3D11_SRV_DIMENSION_TEXTURE2DARRAY ; - desc.Texture2DArray.MostDetailedMip = _mip; - desc.Texture2DArray.MipLevels = 1; - desc.Texture2DArray.FirstArraySlice = 0; - desc.Texture2DArray.ArraySize = texture.m_numLayers; + desc.Texture2DArray.MostDetailedMip = _firstMip; + desc.Texture2DArray.MipLevels = numMips; + desc.Texture2DArray.FirstArraySlice = _firstLayer; + desc.Texture2DArray.ArraySize = numLayers; } else { @@ -3347,20 +3358,21 @@ namespace bgfx { namespace d3d11 ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D ; - desc.Texture2D.MostDetailedMip = _mip; - desc.Texture2D.MipLevels = 1; + desc.Texture2D.MostDetailedMip = _firstMip; + desc.Texture2D.MipLevels = numMips; } break; case TextureD3D11::TextureCube: desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - desc.TextureCube.MostDetailedMip = _mip; - desc.TextureCube.MipLevels = 1; + desc.TextureCube.MostDetailedMip = _firstMip; + desc.TextureCube.MipLevels = numMips; break; + case TextureD3D11::Texture3D: desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; - desc.Texture3D.MostDetailedMip = _mip; - desc.Texture3D.MipLevels = 1; + desc.Texture3D.MostDetailedMip = _firstMip; + desc.Texture3D.MipLevels = numMips; break; } @@ -4833,19 +4845,41 @@ namespace bgfx { namespace d3d11 } } - void TextureD3D11::commit(uint8_t _stage, uint32_t _flags, const float _palette[][4]) + void TextureD3D11::commit(uint8_t _stage, uint32_t _flags, const float _palette[][4], uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips) { TextureStage& ts = s_renderD3D11->m_textureStage; + const uint8_t numMips = bx::min(_numMips, uint8_t(m_numMips - _firstMip) ); + const uint16_t numLayers = bx::min(_numLayers, uint16_t(m_numLayers - _firstLayer) ); + + const bool fullRange = 0 == _firstMip + && 0 == _firstLayer + && numMips == m_numMips + && numLayers == m_numLayers + ; + if (0 != (_flags & BGFX_SAMPLER_SAMPLE_STENCIL) ) { ts.m_srv[_stage] = s_renderD3D11->getCachedSrv( TextureHandle{ uint16_t(this - s_renderD3D11->m_textures) } , 0 + , 1 + , 0 + , UINT16_MAX , false , true ); } + else if (!fullRange) + { + ts.m_srv[_stage] = s_renderD3D11->getCachedSrv( + TextureHandle{ uint16_t(this - s_renderD3D11->m_textures) } + , _firstMip + , numMips + , _firstLayer + , numLayers + ); + } else { ts.m_srv[_stage] = m_srv; @@ -5840,14 +5874,14 @@ namespace bgfx { namespace d3d11 TextureD3D11& texture = m_textures[bind.m_idx]; if (Access::Read != bind.m_access) { - uav[stage] = 0 == bind.m_mip + uav[stage] = 0 == bind.m_firstMip ? texture.m_uav - : s_renderD3D11->getCachedUav(texture.getHandle(), bind.m_mip) + : s_renderD3D11->getCachedUav(texture.getHandle(), bind.m_firstMip) ; } else { - m_textureStage.m_srv[stage] = s_renderD3D11->getCachedSrv(texture.getHandle(), bind.m_mip, true); + m_textureStage.m_srv[stage] = s_renderD3D11->getCachedSrv(texture.getHandle(), bind.m_firstMip, 1, 0, UINT16_MAX, true); m_textureStage.m_sampler[stage] = s_renderD3D11->getSamplerState(uint32_t(texture.m_flags), NULL); } } @@ -5856,7 +5890,7 @@ namespace bgfx { namespace d3d11 case Binding::Texture: { TextureD3D11& texture = m_textures[bind.m_idx]; - texture.commit(stage, bind.m_samplerFlags, _render->m_colorPalette); + texture.commit(stage, bind.m_samplerFlags, _render->m_colorPalette, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips); } break; @@ -6160,6 +6194,10 @@ namespace bgfx { namespace d3d11 if (current.m_idx != bind.m_idx || current.m_type != bind.m_type || current.m_samplerFlags != bind.m_samplerFlags + || current.m_firstLayer != bind.m_firstLayer + || current.m_numLayers != bind.m_numLayers + || current.m_firstMip != bind.m_firstMip + || current.m_numMips != bind.m_numMips || programChanged) { if (kInvalidHandle != bind.m_idx) @@ -6171,14 +6209,14 @@ namespace bgfx { namespace d3d11 TextureD3D11& texture = m_textures[bind.m_idx]; if (Access::Read != bind.m_access) { - m_textureStage.m_uav[stage] = 0 == bind.m_mip + m_textureStage.m_uav[stage] = 0 == bind.m_firstMip ? texture.m_uav - : s_renderD3D11->getCachedUav(texture.getHandle(), bind.m_mip) + : s_renderD3D11->getCachedUav(texture.getHandle(), bind.m_firstMip) ; } else { - m_textureStage.m_srv[stage] = s_renderD3D11->getCachedSrv(texture.getHandle(), bind.m_mip, true); + m_textureStage.m_srv[stage] = s_renderD3D11->getCachedSrv(texture.getHandle(), bind.m_firstMip, 1, 0, UINT16_MAX, true); m_textureStage.m_sampler[stage] = s_renderD3D11->getSamplerState(uint32_t(texture.m_flags), NULL); } } @@ -6187,7 +6225,7 @@ namespace bgfx { namespace d3d11 case Binding::Texture: { TextureD3D11& texture = m_textures[bind.m_idx]; - texture.commit(stage, bind.m_samplerFlags, _render->m_colorPalette); + texture.commit(stage, bind.m_samplerFlags, _render->m_colorPalette, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips); } break; diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index d376185e5..d87a7776c 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -285,7 +285,7 @@ namespace bgfx { namespace d3d11 void destroy(); void overrideInternal(uintptr_t _ptr, uint16_t _layerIndex); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); - void commit(uint8_t _stage, uint32_t _flags, const float _palette[][4]); + void commit(uint8_t _stage, uint32_t _flags, const float _palette[][4], uint16_t _firstLayer = 0, uint16_t _numLayers = UINT16_MAX, uint8_t _firstMip = 0, uint8_t _numMips = UINT8_MAX); void resolve(uint8_t _resolve, uint32_t _layer, uint32_t _numLayers, uint32_t _mip) const; TextureHandle getHandle() const; DXGI_FORMAT getSrvFormat() const; diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index 2f2d4ef2c..0c1c2cc6f 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -4015,13 +4015,22 @@ namespace bgfx { namespace d3d12 return data; } - void ScratchBufferD3D12::allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, TextureD3D12& _texture, uint8_t _mip) + void ScratchBufferD3D12::allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, TextureD3D12& _texture, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips) { ID3D12Device* device = s_renderD3D12->m_device; + const uint8_t numMips = bx::min(_numMips, uint8_t(_texture.m_numMips - _firstMip) ); + const uint16_t numLayers = bx::min(_numLayers, uint16_t(_texture.m_numLayers - _firstLayer) ); + + const bool fullRange = 0 == _firstMip + && 0 == _firstLayer + && numMips >= _texture.m_numMips + && numLayers >= _texture.m_numLayers + ; + D3D12_SHADER_RESOURCE_VIEW_DESC tmpSrvd; D3D12_SHADER_RESOURCE_VIEW_DESC* srvd = &_texture.m_srvd; - if (0 != _mip) + if (!fullRange) { bx::memCopy(&tmpSrvd, srvd, sizeof(tmpSrvd) ); srvd = &tmpSrvd; @@ -4030,21 +4039,43 @@ namespace bgfx { namespace d3d12 { default: case D3D12_SRV_DIMENSION_TEXTURE2D: - srvd->Texture2D.MostDetailedMip = _mip; - srvd->Texture2D.MipLevels = 1; - srvd->Texture2D.PlaneSlice = 0; + srvd->Texture2D.MostDetailedMip = _firstMip; + srvd->Texture2D.MipLevels = numMips; + srvd->Texture2D.PlaneSlice = 0; srvd->Texture2D.ResourceMinLODClamp = 0; break; + case D3D12_SRV_DIMENSION_TEXTURE2DARRAY: + srvd->Texture2DArray.MostDetailedMip = _firstMip; + srvd->Texture2DArray.MipLevels = numMips; + srvd->Texture2DArray.FirstArraySlice = _firstLayer; + srvd->Texture2DArray.ArraySize = numLayers; + srvd->Texture2DArray.PlaneSlice = 0; + srvd->Texture2DArray.ResourceMinLODClamp = 0; + break; + + case D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY: + srvd->Texture2DMSArray.FirstArraySlice = _firstLayer; + srvd->Texture2DMSArray.ArraySize = numLayers; + break; + case D3D12_SRV_DIMENSION_TEXTURECUBE: - srvd->TextureCube.MostDetailedMip = _mip; - srvd->TextureCube.MipLevels = 1; + srvd->TextureCube.MostDetailedMip = _firstMip; + srvd->TextureCube.MipLevels = numMips; srvd->TextureCube.ResourceMinLODClamp = 0; break; + case D3D12_SRV_DIMENSION_TEXTURECUBEARRAY: + srvd->TextureCubeArray.MostDetailedMip = _firstMip; + srvd->TextureCubeArray.MipLevels = numMips; + srvd->TextureCubeArray.First2DArrayFace = _firstLayer; + srvd->TextureCubeArray.NumCubes = numLayers; + srvd->TextureCubeArray.ResourceMinLODClamp = 0; + break; + case D3D12_SRV_DIMENSION_TEXTURE3D: - srvd->Texture3D.MostDetailedMip = _mip; - srvd->Texture3D.MipLevels = 1; + srvd->Texture3D.MostDetailedMip = _firstMip; + srvd->Texture3D.MipLevels = numMips; srvd->Texture3D.ResourceMinLODClamp = 0; break; } @@ -5804,7 +5835,7 @@ namespace bgfx { namespace d3d12 } else { - const uint32_t savedMipLevels = resourceDesc.MipLevels; + const uint16_t savedMipLevels = resourceDesc.MipLevels; const D3D12_RESOURCE_FLAGS savedFlags = resourceDesc.Flags; if (needResolve) @@ -7293,12 +7324,12 @@ namespace bgfx { namespace d3d12 if (Access::Read != bind.m_access) { texture.setState(m_commandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); - scratchBuffer.allocUav(srvHandle[stage], texture, bind.m_mip); + scratchBuffer.allocUav(srvHandle[stage], texture, bind.m_firstMip); } else { texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); - scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_mip); + scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips); samplerFlags[stage] = uint32_t(texture.m_flags); } @@ -7310,7 +7341,7 @@ namespace bgfx { namespace d3d12 { TextureD3D12& texture = m_textures[bind.m_idx]; texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); - scratchBuffer.allocSrv(srvHandle[stage], texture); + scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips); samplerFlags[stage] = (0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags) ? bind.m_samplerFlags : texture.m_flags @@ -7603,12 +7634,12 @@ namespace bgfx { namespace d3d12 if (Access::Read != bind.m_access) { texture.setState(m_commandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); - scratchBuffer.allocUav(srvHandle[stage], texture, bind.m_mip); + scratchBuffer.allocUav(srvHandle[stage], texture, bind.m_firstMip); } else { texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); - scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_mip); + scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips); samplerFlags[stage] = uint32_t(texture.m_flags); } @@ -7620,7 +7651,7 @@ namespace bgfx { namespace d3d12 { TextureD3D12& texture = m_textures[bind.m_idx]; texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); - scratchBuffer.allocSrv(srvHandle[stage], texture); + scratchBuffer.allocSrv(srvHandle[stage], texture, bind.m_firstLayer, bind.m_numLayers, bind.m_firstMip, bind.m_numMips); samplerFlags[stage] = (0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & bind.m_samplerFlags) ? bind.m_samplerFlags : texture.m_flags diff --git a/src/renderer_d3d12.h b/src/renderer_d3d12.h index cdf190288..ea5c8becf 100644 --- a/src/renderer_d3d12.h +++ b/src/renderer_d3d12.h @@ -122,7 +122,7 @@ namespace bgfx { namespace d3d12 void* allocCbv(D3D12_GPU_VIRTUAL_ADDRESS& _gpuAddress, uint32_t _size); - void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint8_t _mip = 0); + void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint16_t _firstLayer = 0, uint16_t _numLayers = UINT16_MAX, uint8_t _firstMip = 0, uint8_t _numMips = UINT8_MAX); void allocSrv(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct BufferD3D12& _buffer); void allocUav(D3D12_GPU_DESCRIPTOR_HANDLE& _gpuHandle, struct TextureD3D12& _texture, uint8_t _mip = 0); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index d98bdf9d5..9df640b2f 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -609,6 +609,7 @@ namespace bgfx { namespace gl ARB_texture_stencil8, ARB_texture_storage, ARB_texture_swizzle, + ARB_texture_view, ARB_timer_query, ARB_uniform_buffer_object, ARB_vertex_array_object, @@ -666,6 +667,7 @@ namespace bgfx { namespace gl EXT_texture_sRGB, EXT_texture_storage, EXT_texture_swizzle, + EXT_texture_view, EXT_texture_type_2_10_10_10_REV, EXT_timer_query, EXT_unpack_subimage, @@ -720,6 +722,7 @@ namespace bgfx { namespace gl OES_texture_half_float_linear, OES_texture_stencil8, OES_texture_storage_multisample_2d_array, + OES_texture_view, OES_vertex_array_object, OES_vertex_half_float, OES_vertex_type_10_10_10_2, @@ -827,6 +830,7 @@ namespace bgfx { namespace gl { "ARB_texture_stencil8", false, true }, { "ARB_texture_storage", BGFX_CONFIG_RENDERER_OPENGL >= 42, true }, { "ARB_texture_swizzle", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, + { "ARB_texture_view", BGFX_CONFIG_RENDERER_OPENGL >= 43, true }, { "ARB_timer_query", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, { "ARB_uniform_buffer_object", BGFX_CONFIG_RENDERER_OPENGL >= 31, true }, { "ARB_vertex_array_object", BGFX_CONFIG_RENDERER_OPENGL >= 30, true }, @@ -884,6 +888,7 @@ namespace bgfx { namespace gl { "EXT_texture_sRGB", false, true }, { "EXT_texture_storage", false, true }, { "EXT_texture_swizzle", false, true }, + { "EXT_texture_view", false, true }, { "EXT_texture_type_2_10_10_10_REV", false, true }, { "EXT_timer_query", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, { "EXT_unpack_subimage", false, true }, @@ -938,6 +943,7 @@ namespace bgfx { namespace gl { "OES_texture_half_float_linear", false, true }, { "OES_texture_stencil8", false, true }, { "OES_texture_storage_multisample_2d_array", false, true }, + { "OES_texture_view", false, true }, { "OES_vertex_array_object", false, true }, { "OES_vertex_half_float", false, true }, { "OES_vertex_type_10_10_10_2", false, true }, @@ -2249,6 +2255,7 @@ namespace bgfx { namespace gl , m_maxMsaa(0) , m_vao(0) , m_blitSupported(false) + , m_textureViewSupported(false) , m_readBackSupported(BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) ) , m_vaoSupport(false) , m_samplerObjectSupport(false) @@ -2906,6 +2913,13 @@ namespace bgfx { namespace gl m_blitSupported = NULL != glCopyImageSubData; } + if (s_extension[Extension::ARB_texture_view].m_supported + || s_extension[Extension::EXT_texture_view].m_supported + || s_extension[Extension::OES_texture_view].m_supported) + { + m_textureViewSupported = NULL != glTextureView; + } + g_caps.supported |= m_blitSupported || BX_ENABLED(BGFX_GL_CONFIG_BLIT_EMULATION) ? BGFX_CAPS_TEXTURE_BLIT : 0 @@ -4220,6 +4234,8 @@ namespace bgfx { namespace gl { m_samplerStateCache.invalidate(); } + + m_textureViewStateCache.invalidate(); } void setSamplerState(uint32_t _stage, uint32_t _numMips, uint32_t _flags, const float _rgba[4]) @@ -4810,6 +4826,7 @@ namespace bgfx { namespace gl OcclusionQueryGL m_occlusionQuery; SamplerStateCache m_samplerStateCache; + TextureViewStateCache m_textureViewStateCache; UniformStateCache m_uniformStateCache; TextVideoMem m_textVideoMem; @@ -4827,6 +4844,7 @@ namespace bgfx { namespace gl GLuint m_vao; uint16_t m_maxLabelLen; bool m_blitSupported; + bool m_textureViewSupported; bool m_readBackSupported; bool m_vaoSupport; bool m_samplerObjectSupport; @@ -5628,6 +5646,9 @@ namespace bgfx { namespace gl : s_textureFormat[m_textureFormat].m_internalFmt ; + m_internalFmt = internalFmt; + m_numLayers = textureArray ? _depth : 1; + if (textureArray) { GL_CHECK(glTexStorage3D(_target @@ -5637,6 +5658,7 @@ namespace bgfx { namespace gl , m_height , _depth ) ); + m_immutableStorage = true; } else if (computeWrite) { @@ -5659,6 +5681,7 @@ namespace bgfx { namespace gl , m_height ) ); } + m_immutableStorage = true; } setSamplerState(uint32_t(_flags), NULL); @@ -5979,6 +6002,8 @@ namespace bgfx { namespace gl void TextureGL::destroy() { + s_renderGL->m_textureViewStateCache.invalidateWithParent(uint16_t(this - s_renderGL->m_textures) ); + if (0 == (m_flags & BGFX_SAMPLER_INTERNAL_SHARED) && 0 != m_id) { @@ -6233,7 +6258,60 @@ namespace bgfx { namespace gl } } - void TextureGL::commit(uint32_t _stage, uint32_t _flags, const float _palette[][4]) + GLuint TextureGL::getViewId(uint8_t _firstMip, uint8_t _numMips, uint16_t _firstLayer, uint16_t _numLayers) + { + const uint8_t firstMip = bx::min(_firstMip, uint8_t(m_numMips - 1) ); + const uint8_t numMips = bx::min(_numMips, uint8_t(m_numMips - firstMip) ); + const uint16_t numLayers0 = uint16_t(bx::max(m_numLayers, 1) ); + const uint16_t firstLayer = bx::min(_firstLayer, uint16_t(numLayers0 - 1) ); + const uint16_t numLayers = bx::min(_numLayers, uint16_t(numLayers0 - firstLayer) ); + + const bool fullRange = 0 == firstMip + && numMips >= m_numMips + && 0 == firstLayer + && numLayers >= numLayers0 + ; + + if (fullRange + || !s_renderGL->m_textureViewSupported + || !m_immutableStorage + || GL_ZERO == m_internalFmt + || NULL == glTextureView) + { + return m_id; + } + + const uint16_t parent = uint16_t(this - s_renderGL->m_textures); + + const uint64_t key = 0 + | (uint64_t(parent) << 48) + | (uint64_t(firstMip) << 40) + | (uint64_t(numMips) << 32) + | (uint64_t(firstLayer) << 16) + | (uint64_t(numLayers) << 0) + ; + + GLuint viewId = s_renderGL->m_textureViewStateCache.find(key); + if (UINT32_MAX != viewId) + { + return viewId; + } + + viewId = s_renderGL->m_textureViewStateCache.add(key, parent); + GL_CHECK(glTextureView(viewId + , m_target + , m_id + , m_internalFmt + , firstMip + , numMips + , firstLayer + , numLayers + ) ); + + return viewId; + } + + void TextureGL::commit(uint32_t _stage, uint32_t _flags, const float _palette[][4], uint8_t _firstMip, uint8_t _numMips, uint16_t _firstLayer, uint16_t _numLayers) { const uint32_t flags = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & _flags) ? _flags @@ -6241,8 +6319,10 @@ namespace bgfx { namespace gl ; const uint32_t index = (flags & BGFX_SAMPLER_BORDER_COLOR_MASK) >> BGFX_SAMPLER_BORDER_COLOR_SHIFT; + const GLuint id = getViewId(_firstMip, _numMips, _firstLayer, _numLayers); + GL_CHECK(glActiveTexture(GL_TEXTURE0+_stage) ); - GL_CHECK(glBindTexture(m_target, m_id) ); + GL_CHECK(glBindTexture(m_target, id) ); if (s_renderGL->m_samplerObjectSupport) { @@ -7747,7 +7827,7 @@ namespace bgfx { namespace gl case Binding::Texture: { TextureGL& texture = m_textures[bind.m_idx]; - texture.commit(ii, bind.m_samplerFlags, _render->m_colorPalette); + texture.commit(ii, bind.m_samplerFlags, _render->m_colorPalette, bind.m_firstMip, bind.m_numMips, bind.m_firstLayer, bind.m_numLayers); } break; @@ -7756,7 +7836,7 @@ namespace bgfx { namespace gl const TextureGL& texture = m_textures[bind.m_idx]; GL_CHECK(glBindImageTexture(ii , texture.m_id - , bind.m_mip + , bind.m_firstMip , texture.isCubeMap() || texture.m_target == GL_TEXTURE_2D_ARRAY ? GL_TRUE : GL_FALSE , 0 , s_access[bind.m_access] @@ -8270,13 +8350,13 @@ namespace bgfx { namespace gl { const TextureGL& texture = m_textures[bind.m_idx]; GL_CHECK(glBindImageTexture(stage - , texture.m_id - , bind.m_mip - , texture.isCubeMap() || texture.m_target == GL_TEXTURE_2D_ARRAY ? GL_TRUE : GL_FALSE - , 0 - , s_access[bind.m_access] - , s_imageFormat[bind.m_format]) - ); + , texture.m_id + , bind.m_firstMip + , texture.isCubeMap() || texture.m_target == GL_TEXTURE_2D_ARRAY ? GL_TRUE : GL_FALSE + , 0 + , s_access[bind.m_access] + , s_imageFormat[bind.m_format]) + ); barrier |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; } break; @@ -8284,7 +8364,7 @@ namespace bgfx { namespace gl case Binding::Texture: { TextureGL& texture = m_textures[bind.m_idx]; - texture.commit(stage, bind.m_samplerFlags, _render->m_colorPalette); + texture.commit(stage, bind.m_samplerFlags, _render->m_colorPalette, bind.m_firstMip, bind.m_numMips, bind.m_firstLayer, bind.m_numLayers); } break; diff --git a/src/renderer_gl.h b/src/renderer_gl.h index a85dec920..5eb5760bf 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -1343,6 +1343,85 @@ namespace bgfx { namespace gl HashMap m_hashMap; }; + class TextureViewStateCache + { + public: + GLuint add(uint64_t _key, uint16_t _parent) + { + invalidate(_key); + + GLuint viewId; + GL_CHECK(glGenTextures(1, &viewId) ); + + m_hashMap.insert(stl::make_pair(_key, Data{viewId, _parent}) ); + + return viewId; + } + + GLuint find(uint64_t _key) + { + HashMap::iterator it = m_hashMap.find(_key); + if (it != m_hashMap.end() ) + { + return it->second.m_textureViewId; + } + + return UINT32_MAX; + } + + void invalidate(uint64_t _key) + { + HashMap::iterator it = m_hashMap.find(_key); + if (it != m_hashMap.end() ) + { + GL_CHECK(glDeleteTextures(1, &it->second.m_textureViewId) ); + m_hashMap.erase(it); + } + } + + void invalidateWithParent(uint16_t _parent) + { + for (HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd;) + { + if (it->second.m_parent == _parent) + { + GL_CHECK(glDeleteTextures(1, &it->second.m_textureViewId) ); + HashMap::iterator itErase = it; + ++it; + m_hashMap.erase(itErase); + } + else + { + ++it; + } + } + } + + void invalidate() + { + for (HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it) + { + GL_CHECK(glDeleteTextures(1, &it->second.m_textureViewId) ); + } + m_hashMap.clear(); + } + + uint32_t getCount() const + { + return uint32_t(m_hashMap.size() ); + } + + private: + struct Data + { + GLuint m_textureViewId; + uint16_t m_parent; + }; + + typedef stl::unordered_map HashMap; + HashMap m_hashMap; + }; + struct IndexBufferGL { void create(uint32_t _size, void* _data, uint16_t _flags) @@ -1445,9 +1524,11 @@ namespace bgfx { namespace gl , m_target(GL_TEXTURE_2D) , m_fmt(GL_ZERO) , m_type(GL_ZERO) + , m_internalFmt(GL_ZERO) , m_flags(0) , m_currentSamplerHash(UINT32_MAX) , m_numMips(0) + , m_immutableStorage(false) { } @@ -1457,7 +1538,8 @@ namespace bgfx { namespace gl void overrideInternal(uintptr_t _ptr); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void setSamplerState(uint32_t _flags, const float _rgba[4]); - void commit(uint32_t _stage, uint32_t _flags, const float _palette[][4]); + void commit(uint32_t _stage, uint32_t _flags, const float _palette[][4], uint8_t _firstMip, uint8_t _numMips, uint16_t _firstLayer, uint16_t _numLayers); + GLuint getViewId(uint8_t _firstMip, uint8_t _numMips, uint16_t _firstLayer, uint16_t _numLayers); void resolve(uint8_t _resolve) const; bool isCubeMap() const @@ -1473,6 +1555,7 @@ namespace bgfx { namespace gl GLenum m_target; GLenum m_fmt; GLenum m_type; + GLenum m_internalFmt; uint64_t m_flags; uint32_t m_currentSamplerHash; uint32_t m_width; @@ -1482,6 +1565,7 @@ namespace bgfx { namespace gl uint8_t m_numMips; uint8_t m_requestedFormat; uint8_t m_textureFormat; + bool m_immutableStorage; }; struct ShaderGL diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index 457aaac19..6139dda35 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -3645,6 +3645,13 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames { MTL_RELEASE_W(m_ptrMips[ii], 0); } + + for (stl::unordered_map::iterator it = m_ptrViews.begin(), itEnd = m_ptrViews.end(); it != itEnd; ++it) + { + MTL::Texture* view = it->second; + MTL_RELEASE_W(view, 0); + } + m_ptrViews.clear(); } void TextureMtl::overrideInternal(uintptr_t _ptr) @@ -3760,11 +3767,11 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames } } - void TextureMtl::commit(uint8_t _stage, bool _vertex, bool _fragment, uint32_t _flags, uint8_t _mip) + void TextureMtl::commit(uint8_t _stage, bool _vertex, bool _fragment, uint32_t _flags, uint8_t _mip, uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips) { if (_vertex) { - MTL::Texture* p = _mip != UINT8_MAX ? getTextureMipLevel(_mip) : m_ptr; + MTL::Texture* p = _mip != UINT8_MAX ? getTextureMipLevel(_mip) : getTextureView(_firstLayer, _numLayers, _firstMip, _numMips); s_renderMtl->m_renderCommandEncoder->setVertexTexture(p, _stage); s_renderMtl->m_renderCommandEncoder->setVertexSamplerState( 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & _flags) @@ -3776,7 +3783,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (_fragment) { - MTL::Texture* p = _mip != UINT8_MAX ? getTextureMipLevel(_mip) : m_ptr; + MTL::Texture* p = _mip != UINT8_MAX ? getTextureMipLevel(_mip) : getTextureView(_firstLayer, _numLayers, _firstMip, _numMips); s_renderMtl->m_renderCommandEncoder->setFragmentTexture(p, _stage); s_renderMtl->m_renderCommandEncoder->setFragmentSamplerState( 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & _flags) @@ -3787,6 +3794,55 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames } } + MTL::Texture* TextureMtl::getTextureView(uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips) + { + if (NULL == m_ptr) + { + return NULL; + } + + const uint32_t totalLayers = uint32_t(m_ptr->arrayLength() * (TextureCube == m_type ? 6 : 1) ); + + const uint8_t firstMip = bx::min(_firstMip, uint8_t(m_numMips - 1) ); + const uint8_t numMips = bx::min(_numMips, uint8_t(m_numMips - firstMip) ); + const uint32_t firstLayer = bx::min(_firstLayer, totalLayers - 1); + const uint32_t numLayers = bx::min(_numLayers, totalLayers - firstLayer); + + const bool fullRange = 0 == firstMip + && 0 == firstLayer + && numMips >= m_numMips + && numLayers >= totalLayers + ; + + if (fullRange) + { + return m_ptr; + } + + const uint64_t key = 0 + | uint64_t(firstMip) + | (uint64_t(numMips) << 8) + | (uint64_t(firstLayer) << 16) + | (uint64_t(numLayers) << 32) + ; + + stl::unordered_map::iterator it = m_ptrViews.find(key); + if (it != m_ptrViews.end() ) + { + return it->second; + } + + MTL::Texture* view = m_ptr->newTextureView( + m_ptr->pixelFormat() + , TextureCube == m_type ? (MTL::TextureType)MTL::TextureType2DArray : m_ptr->textureType() + , NS::Range::Make(firstMip, numMips) + , NS::Range::Make(firstLayer, numLayers) + ); + m_ptrViews[key] = view; + + return view; + } + MTL::Texture* TextureMtl::getTextureMipLevel(uint8_t _mip) { _mip = bx::clamp(_mip, 0, m_numMips); @@ -5090,7 +5146,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames case Binding::Image: { TextureMtl& texture = m_textures[bind.m_idx]; - m_computeCommandEncoder->setTexture(texture.getTextureMipLevel(bind.m_mip), stage); + m_computeCommandEncoder->setTexture(texture.getTextureMipLevel(bind.m_firstMip), stage); } break; @@ -5509,7 +5565,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames , 0 != (bindingTypes[stage] & PipelineStateMtl::BindToVertexShader) , 0 != (bindingTypes[stage] & PipelineStateMtl::BindToFragmentShader) , bind.m_samplerFlags - , bind.m_mip + , bind.m_firstMip ); } break; @@ -5522,6 +5578,11 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames , 0 != (bindingTypes[stage] & PipelineStateMtl::BindToVertexShader) , 0 != (bindingTypes[stage] & PipelineStateMtl::BindToFragmentShader) , bind.m_samplerFlags + , UINT8_MAX + , bind.m_firstLayer + , bind.m_numLayers + , bind.m_firstMip + , bind.m_numMips ); } break; diff --git a/src/renderer_mtl.h b/src/renderer_mtl.h index 3f87afc60..6c95bca7a 100644 --- a/src/renderer_mtl.h +++ b/src/renderer_mtl.h @@ -500,14 +500,20 @@ namespace bgfx { namespace mtl , bool _fragment , uint32_t _flags = BGFX_SAMPLER_INTERNAL_DEFAULT , uint8_t _mip = UINT8_MAX + , uint16_t _firstLayer = 0 + , uint16_t _numLayers = UINT16_MAX + , uint8_t _firstMip = 0 + , uint8_t _numMips = UINT8_MAX ); MTL::Texture* getTextureMipLevel(uint8_t _mip); + MTL::Texture* getTextureView(uint16_t _firstLayer, uint16_t _numLayers, uint8_t _firstMip, uint8_t _numMips); MTL::Texture* m_ptr; MTL::Texture* m_ptrMsaa; MTL::Texture* m_ptrStencil; // for emulating packed depth/stencil formats - only for iOS8... MTL::Texture* m_ptrMips[14]; + stl::unordered_map m_ptrViews; MTL::SamplerState* m_sampler; uint64_t m_flags; uint32_t m_width; diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index bf7b33697..ea68b212d 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -3750,19 +3750,26 @@ VK_IMPORT_DEVICE return sampler; } - VkImageView getCachedImageView(TextureHandle _handle, uint32_t _mip, uint32_t _numMips, VkImageViewType _type, bool _stencil = false) + VkImageView getCachedImageView(TextureHandle _handle, uint32_t _mip, uint32_t _numMips, VkImageViewType _type, bool _stencil = false, uint32_t _firstLayer = 0, uint32_t _numLayers = UINT32_MAX) { const TextureVK& texture = m_textures[_handle.idx]; _stencil = _stencil && !!(texture.m_aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT); + const uint32_t firstLayer = bx::min(_firstLayer, texture.m_numSides); + const uint32_t numLayers = bx::min(_numLayers, texture.m_numSides - firstLayer); + const uint32_t firstMip = bx::min(_mip, texture.m_numMips); + const uint32_t numMips = bx::min(_numMips, texture.m_numMips - firstMip); + bx::HashMurmur2A hash; hash.begin(); hash.add(_handle.idx); - hash.add(_mip); - hash.add(_numMips); + hash.add(firstMip); + hash.add(numMips); hash.add(_type); hash.add(_stencil); + hash.add(firstLayer); + hash.add(numLayers); uint32_t hashKey = hash.end(); VkImageView* viewCached = m_imageViewCache.find(hashKey); @@ -3778,7 +3785,7 @@ VK_IMPORT_DEVICE ; VkImageView view; - VK_CHECK(texture.createView(0, texture.m_numSides, _mip, _numMips, _type, aspectMask, false, &view) ); + VK_CHECK(texture.createView(firstLayer, numLayers, firstMip, numMips, _type, aspectMask, false, &view) ); m_imageViewCache.add(hashKey, view, _handle.idx); return view; @@ -4149,8 +4156,8 @@ VK_IMPORT_DEVICE imageInfo[imageCount].sampler = VK_NULL_HANDLE; imageInfo[imageCount].imageView = getCachedImageView( { bind.m_idx } - , bind.m_mip - , 1 + , bind.m_firstMip + , bind.m_numMips , type ); wds[wdsCount].pImageInfo = &imageInfo[imageCount]; @@ -4210,10 +4217,12 @@ VK_IMPORT_DEVICE imageInfo[imageCount].sampler = sampler; imageInfo[imageCount].imageView = getCachedImageView( { bind.m_idx } - , 0 - , texture.m_numMips + , bind.m_firstMip + , bind.m_numMips , type , sampleStencil + , bind.m_firstLayer + , bind.m_numLayers ); wds[wdsCount].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp index f07508024..2c049bbff 100644 --- a/src/renderer_webgpu.cpp +++ b/src/renderer_webgpu.cpp @@ -1976,12 +1976,7 @@ WGPU_IMPORT RenderBind renderBind; renderBind.clear(); Binding& bind = renderBind.m_bind[0]; - bind.m_idx = _blitter.m_texture.idx; - bind.m_type = uint8_t(Binding::Texture); - bind.m_samplerFlags = uint32_t(texture.m_flags & BGFX_SAMPLER_BITS_MASK); - bind.m_format = 0; - bind.m_access = 0; - bind.m_mip = 0; + bind.setTexture(_blitter.m_texture, uint32_t(texture.m_flags & BGFX_SAMPLER_BITS_MASK) ); const Stream stream = { @@ -3055,8 +3050,8 @@ WGPU_IMPORT .size = 0, .sampler = NULL, .textureView = _isCompute - ? texture.getTextureView(bind.m_mip, 1, Binding::Image == bind.m_type) - : texture.getTextureView(0, UINT8_MAX, false) + ? texture.getTextureView(bind.m_firstMip, bind.m_numMips, Binding::Image == bind.m_type) + : texture.getTextureView(bind.m_firstMip, bind.m_numMips, false, bind.m_firstLayer, bind.m_numLayers) , }; @@ -4243,6 +4238,8 @@ retry: void TextureWGPU::destroy() { + s_renderWGPU->m_textureViewStateCache.invalidateWithParent(uint16_t(this - s_renderWGPU->m_textures) ); + wgpuDestroy(m_texture); wgpuDestroy(m_textureResolve); } @@ -4357,7 +4354,7 @@ retry: return sampler; } - WGPUTextureView TextureWGPU::getTextureView(uint8_t _baseMipLevel, uint8_t _mipLevelCount, bool _storage, bool _array) const + WGPUTextureView TextureWGPU::getTextureView(uint8_t _baseMipLevel, uint8_t _mipLevelCount, bool _storage, uint16_t _baseArrayLayer, uint16_t _arrayLayerCount) const { bx::HashMurmur3 murmur; murmur.begin(); @@ -4365,7 +4362,8 @@ retry: murmur.add(_baseMipLevel); murmur.add(_mipLevelCount); murmur.add(_storage); - murmur.add(_array); + murmur.add(_baseArrayLayer); + murmur.add(_arrayLayerCount); const uint32_t hash = murmur.end(); WGPUTextureView textureView = s_renderWGPU->m_textureViewStateCache.find(hash); @@ -4373,13 +4371,12 @@ retry: if (NULL == textureView) { WGPUTextureViewDimension tvd = m_viewDimension; - uint32_t arrayLayerCount = WGPU_ARRAY_LAYER_COUNT_UNDEFINED; + const uint32_t arrayLayerCount = UINT16_MAX == _arrayLayerCount + ? WGPU_ARRAY_LAYER_COUNT_UNDEFINED + : _arrayLayerCount + ; - if (_array) - { - tvd = WGPUTextureViewDimension_2DArray; - } - else if (_storage) + if (_storage) { if (WGPUTextureViewDimension_Cube == tvd) { @@ -4395,16 +4392,17 @@ retry: .dimension = tvd, .baseMipLevel = _baseMipLevel, .mipLevelCount = UINT8_MAX == _mipLevelCount ? WGPU_MIP_LEVEL_COUNT_UNDEFINED : _mipLevelCount, - .baseArrayLayer = 0, + .baseArrayLayer = _baseArrayLayer, .arrayLayerCount = arrayLayerCount, .aspect = WGPUTextureAspect_All, - .usage = WGPUTextureUsage_TextureBinding + .usage = 0 + | WGPUTextureUsage_TextureBinding | (_storage ? WGPUTextureUsage_StorageBinding : 0) , }; textureView = WGPU_CHECK(wgpuTextureCreateView(m_texture, &textureViewDesc) ); - s_renderWGPU->m_textureViewStateCache.add(hash, textureView); + s_renderWGPU->m_textureViewStateCache.add(hash, textureView, uint16_t(this - s_renderWGPU->m_textures) ); } return textureView; @@ -5475,22 +5473,19 @@ m_resolution.formatColor = TextureFormat::BGRA8; for (uint32_t ii = 0; ii < 4; ++ii) { Binding& bind = renderBind.m_bind[ii]; - bind.m_type = Binding::Image; - bind.m_access = Access::Write; - bind.m_idx = _textureHandle.idx; - bind.m_mip = uint8_t(bx::min(topMip + 1 + ii, uint32_t(_texture.m_numMips - 1) ) ); + bind.setImage(_textureHandle, uint8_t(bx::min(topMip + 1 + ii, uint32_t(_texture.m_numMips - 1) ) ), Access::Write, TextureFormat::Enum(0) ); } { - Binding& bind = renderBind.m_bind[4]; - bind.m_type = Binding::Texture; - bind.m_idx = _textureHandle.idx; - bind.m_mip = uint8_t(topMip); - bind.m_samplerFlags = 0 + Binding& bind = renderBind.m_bind[4]; + bind.setTexture( + _textureHandle + , 0 | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP - ; + , uint8_t(topMip) + ); } ComputePipeline* computePipeline = getPipeline(prog, renderBind); diff --git a/src/renderer_webgpu.h b/src/renderer_webgpu.h index 0bf9c3b7a..9150034c5 100644 --- a/src/renderer_webgpu.h +++ b/src/renderer_webgpu.h @@ -391,10 +391,10 @@ namespace bgfx { namespace wgpu class StateCacheT { public: - void add(uint64_t _key, Ty _value) + void add(uint64_t _key, Ty _value, uint16_t _parent = UINT16_MAX) { invalidate(_key); - m_hashMap.insert(stl::make_pair(_key, _value) ); + m_hashMap.insert(stl::make_pair(_key, Data{_value, _parent}) ); } Ty find(uint64_t _key) @@ -402,7 +402,7 @@ namespace bgfx { namespace wgpu typename HashMap::iterator it = m_hashMap.find(_key); if (it != m_hashMap.end() ) { - return it->second; + return it->second.m_value; } return 0; @@ -413,16 +413,34 @@ namespace bgfx { namespace wgpu typename HashMap::iterator it = m_hashMap.find(_key); if (it != m_hashMap.end() ) { - wgpuRelease(it->second); + wgpuRelease(it->second.m_value); m_hashMap.erase(it); } } + void invalidateWithParent(uint16_t _parent) + { + for (typename HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd;) + { + if (it->second.m_parent == _parent) + { + wgpuRelease(it->second.m_value); + typename HashMap::iterator itErase = it; + ++it; + m_hashMap.erase(itErase); + } + else + { + ++it; + } + } + } + void invalidate() { for (typename HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it) { - wgpuRelease(it->second); + wgpuRelease(it->second.m_value); } m_hashMap.clear(); @@ -434,7 +452,13 @@ namespace bgfx { namespace wgpu } private: - typedef stl::unordered_map HashMap; + struct Data + { + Ty m_value; + uint16_t m_parent; + }; + + typedef stl::unordered_map HashMap; HashMap m_hashMap; }; @@ -687,7 +711,7 @@ namespace bgfx { namespace wgpu void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); WGPUSampler getSamplerState(uint32_t _samplerFlags) const; - WGPUTextureView getTextureView(uint8_t _baseMipLevel, uint8_t _mipLevelCount, bool _storage, bool _array = false) const; + WGPUTextureView getTextureView(uint8_t _baseMipLevel, uint8_t _mipLevelCount, bool _storage, uint16_t _baseArrayLayer = 0, uint16_t _arrayLayerCount = UINT16_MAX) const; WGPUTexture m_texture; WGPUTexture m_textureResolve;