diff --git a/bindings/bf/bgfx.bf b/bindings/bf/bgfx.bf
index 1e87bc5f9..978052b52 100644
--- a/bindings/bf/bgfx.bf
+++ b/bindings/bf/bgfx.bf
@@ -2619,6 +2619,8 @@ public static class bgfx
public uint32 maxTransientVbSize;
public uint32 maxTransientIbSize;
public uint32 minUniformBufferSize;
+ public uint32 blitRowPitchAlign;
+ public uint32 blitOffsetAlign;
}
public RendererType rendererType;
@@ -2735,6 +2737,29 @@ public static class bgfx
public VertexBufferHandle handle;
}
+ [CRepr]
+ public struct TextureRegion
+ {
+ public TextureHandle handle;
+ public uint8 mip;
+ public uint16 x;
+ public uint16 y;
+ public uint16 z;
+ public uint16 width;
+ public uint16 height;
+ public uint16 depth;
+ }
+
+ [CRepr]
+ public struct BufferRegion
+ {
+ public BufferHandle handle;
+ public uint32 offset;
+ public uint32 size;
+ public uint32 rowPitch;
+ public uint32 slicePitch;
+ }
+
[CRepr]
public struct TextureInfo
{
@@ -2754,7 +2779,7 @@ public static class bgfx
{
public uint32 magic;
public VideoCodec codec;
- public uint8_t* parameterSets;
+ public uint8* parameterSets;
public uint32 parameterSetsSize;
public uint32 cachedAuBytes;
public uint8 flags;
@@ -2771,7 +2796,7 @@ public static class bgfx
public struct VideoDecoderFrame
{
public uint32 magic;
- public uint8_t* bitstream;
+ public uint8* bitstream;
public VideoDecoderAu* aus;
public uint32 numAus;
public int64 presentationTimeUs;
@@ -2838,6 +2863,7 @@ public static class bgfx
public uint32 numDraw;
public uint32 numCompute;
public uint32 numBlit;
+ public uint32 numBlitRepack;
public uint32 numDrawCallsPeak;
public uint32 maxGpuLatency;
public uint32 gpuFrameNum;
@@ -2955,7 +2981,53 @@ public static class bgfx
public bool Valid => idx != uint16.MaxValue;
}
+ [CRepr]
+ public struct BufferHandle {
+ public uint16 idx;
+ public uint16 type;
+ public bool Valid => idx != uint16.MaxValue;
+ }
+
+ ///
+ /// Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+ /// at zero, which addresses mip 0 of the only slice a 2D texture has.
+ ///
+ ///
+ /// Texture handle.
+ /// X position of the region.
+ /// Y position of the region.
+ /// Width of the region. 0 uses the rest of the mip from `_x`.
+ /// Height of the region. 0 uses the rest of the mip from `_y`.
+ ///
+ [LinkName("bgfx_texture_region_init")]
+ public static extern void texture_region_init(TextureRegion* _this, TextureHandle _handle, uint16 _x, uint16 _y, uint16 _width, uint16 _height);
+
+ ///
+ /// Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+ /// fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+ /// `handle` is left untouched, so `size` can be used to create the buffer the
+ /// region will point at.
+ ///
+ ///
+ /// Texture region the buffer is copied to or from.
+ ///
+ [LinkName("bgfx_buffer_region_init_texture")]
+ public static extern void buffer_region_init_texture(BufferRegion* _this, TextureRegion* _texture);
+
+ ///
+ /// Fill in the region a blit between two buffers copies. `rowPitch` and
+ /// `slicePitch` are left at zero, since neither end of such a blit is a
+ /// texture.
+ ///
+ ///
+ /// Buffer handle.
+ /// Byte offset into the buffer.
+ /// Number of bytes. 0 uses the rest of the buffer.
+ ///
+ [LinkName("bgfx_buffer_region_init_buffer")]
+ public static extern void buffer_region_init_buffer(BufferRegion* _this, BufferHandle _handle, uint32 _offset, uint32 _size);
+
///
/// Init attachment.
///
@@ -3345,6 +3417,29 @@ public static class bgfx
[LinkName("bgfx_create_index_buffer")]
public static extern IndexBufferHandle create_index_buffer(Memory* _mem, uint16 _flags);
+ ///
+ /// Read back contents of buffer.
+ ///
+ /// @remarks
+ /// Read back is asynchronous, and the result is available at the returned frame.
+ /// A zero `size` reads the rest of the buffer. `rowPitch` and `slicePitch` are
+ /// unused.
+ ///
+ /// Read back is intended for reading GPU written (compute, or draw indirect) buffers
+ /// back to the CPU. It's not intended to be used in the main render loop, since it
+ /// stalls the GPU.
+ ///
+ /// @attention Buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ ///
+ ///
+ ///
+ /// Source buffer region.
+ /// Destination buffer.
+ ///
+ [LinkName("bgfx_read_buffer")]
+ public static extern uint32 read_buffer(BufferRegion* _src, void* _data);
+
///
/// Set static index buffer debug name.
///
@@ -3885,6 +3980,14 @@ public static class bgfx
///
/// Read back texture content.
///
+ /// @remarks
+ /// Read back is asynchronous, and the result is available at the returned frame.
+ /// `TextureRegion::z` selects cube face, 3D slice, or array layer. The region must
+ /// cover the whole mip.
+ ///
+ /// Read back is not intended to be used in the main render loop, since it stalls
+ /// the GPU.
+ ///
/// @attention Texture must be created with `BGFX_TEXTURE_READ_BACK` flag.
/// It's a texture for CPU readback, and can't be a GPU resource
/// at the same time. See `examples/30-picking`.
@@ -3892,13 +3995,11 @@ public static class bgfx
///
///
///
- /// Texture handle.
+ /// Source texture region.
/// Destination buffer.
- /// Texture layer.
- /// Mip level.
///
[LinkName("bgfx_read_texture")]
- public static extern uint32 read_texture(TextureHandle _handle, void* _data, uint16 _layer, uint8 _mip);
+ public static extern uint32 read_texture(TextureRegion* _src, void* _data);
///
/// Set texture debug name.
@@ -4961,7 +5062,15 @@ public static class bgfx
public static extern void encoder_discard(Encoder* _this, uint8 _flags);
///
- /// Blit 2D texture region between two 2D textures.
+ /// Blit texture region between two textures.
+ ///
+ /// @remarks
+ /// The copy covers the region the two sides have in common: each side gives
+ /// the origin it starts at, and the size is the smaller of the two extents.
+ /// A zero `width`, `height` or `depth` extends to the rest of that mip.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view. In views, all
+ /// draw commands are executed after blit and compute commands.
///
/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
@@ -4969,22 +5078,89 @@ public static class bgfx
///
///
/// View id.
- /// Destination texture handle.
- /// Destination texture mip level.
- /// Destination texture X position.
- /// Destination texture Y position.
- /// If texture is 2D this argument should be 0. If destination texture is cube this argument represents destination texture cube face. For 3D texture this argument represents destination texture Z position.
- /// Source texture handle.
- /// Source texture mip level.
- /// Source texture X position.
- /// Source texture Y position.
- /// If texture is 2D this argument should be 0. If source texture is cube this argument represents source texture cube face. For 3D texture this argument represents source texture Z position.
- /// Width of region.
- /// Height of region.
- /// If texture is 3D this argument represents depth of region, otherwise it's unused.
+ /// Destination texture region.
+ /// Source texture region.
///
[LinkName("bgfx_encoder_blit")]
- public static extern void encoder_blit(Encoder* _this, ViewId _id, TextureHandle _dst, uint8 _dstMip, uint16 _dstX, uint16 _dstY, uint16 _dstZ, TextureHandle _src, uint8 _srcMip, uint16 _srcX, uint16 _srcY, uint16 _srcZ, uint16 _width, uint16 _height, uint16 _depth);
+ public static extern void encoder_blit(Encoder* _this, ViewId _id, TextureRegion* _dst, TextureRegion* _src);
+
+ ///
+ /// Blit buffer region between two buffers.
+ ///
+ /// @remarks
+ /// The source region gives the number of bytes copied, and the destination
+ /// region gives only the offset they land at. A zero `size` copies the rest of
+ /// the source buffer. `rowPitch` and `slicePitch` are unused.
+ ///
+ /// Buffer blit is performed on GPU, and it is ordered within the view, same as
+ /// texture blit. In views, all draw commands are executed after blit and compute
+ /// commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Source and destination buffer must be different.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source buffer region.
+ ///
+ [LinkName("bgfx_encoder_blit_buffer")]
+ public static extern void encoder_blit_buffer(Encoder* _this, ViewId _id, BufferRegion* _dst, BufferRegion* _src);
+
+ ///
+ /// Blit texture region into buffer.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ /// them tightly. `BufferRegion::init` fills in the layout the backend copies
+ /// fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source texture region.
+ ///
+ [LinkName("bgfx_encoder_blit_to_buffer")]
+ public static extern void encoder_blit_to_buffer(Encoder* _this, ViewId _id, BufferRegion* _dst, TextureRegion* _src);
+
+ ///
+ /// Blit buffer contents into texture region.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ /// them tightly packed. `BufferRegion::init` fills in the layout the backend
+ /// copies fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination texture region.
+ /// Source buffer region.
+ ///
+ [LinkName("bgfx_encoder_blit_from_buffer")]
+ public static extern void encoder_blit_from_buffer(Encoder* _this, ViewId _id, TextureRegion* _dst, BufferRegion* _src);
///
/// Request screen shot of window back buffer.
@@ -5638,7 +5814,15 @@ public static class bgfx
public static extern void discard(uint8 _flags);
///
- /// Blit 2D texture region between two 2D textures.
+ /// Blit texture region between two textures.
+ ///
+ /// @remarks
+ /// The copy covers the region the two sides have in common: each side gives
+ /// the origin it starts at, and the size is the smaller of the two extents.
+ /// A zero `width`, `height` or `depth` extends to the rest of that mip.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view. In views, all
+ /// draw commands are executed after blit and compute commands.
///
/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
@@ -5646,22 +5830,89 @@ public static class bgfx
///
///
/// View id.
- /// Destination texture handle.
- /// Destination texture mip level.
- /// Destination texture X position.
- /// Destination texture Y position.
- /// If texture is 2D this argument should be 0. If destination texture is cube this argument represents destination texture cube face. For 3D texture this argument represents destination texture Z position.
- /// Source texture handle.
- /// Source texture mip level.
- /// Source texture X position.
- /// Source texture Y position.
- /// If texture is 2D this argument should be 0. If source texture is cube this argument represents source texture cube face. For 3D texture this argument represents source texture Z position.
- /// Width of region.
- /// Height of region.
- /// If texture is 3D this argument represents depth of region, otherwise it's unused.
+ /// Destination texture region.
+ /// Source texture region.
///
[LinkName("bgfx_blit")]
- public static extern void blit(ViewId _id, TextureHandle _dst, uint8 _dstMip, uint16 _dstX, uint16 _dstY, uint16 _dstZ, TextureHandle _src, uint8 _srcMip, uint16 _srcX, uint16 _srcY, uint16 _srcZ, uint16 _width, uint16 _height, uint16 _depth);
+ public static extern void blit(ViewId _id, TextureRegion* _dst, TextureRegion* _src);
+
+ ///
+ /// Blit buffer region between two buffers.
+ ///
+ /// @remarks
+ /// The source region gives the number of bytes copied, and the destination
+ /// region gives only the offset they land at. A zero `size` copies the rest of
+ /// the source buffer. `rowPitch` and `slicePitch` are unused.
+ ///
+ /// Buffer blit is performed on GPU, and it is ordered within the view, same as
+ /// texture blit. In views, all draw commands are executed after blit and compute
+ /// commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Source and destination buffer must be different.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source buffer region.
+ ///
+ [LinkName("bgfx_blit_buffer")]
+ public static extern void blit_buffer(ViewId _id, BufferRegion* _dst, BufferRegion* _src);
+
+ ///
+ /// Blit texture region into buffer.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ /// them tightly. `BufferRegion::init` fills in the layout the backend copies
+ /// fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source texture region.
+ ///
+ [LinkName("bgfx_blit_to_buffer")]
+ public static extern void blit_to_buffer(ViewId _id, BufferRegion* _dst, TextureRegion* _src);
+
+ ///
+ /// Blit buffer contents into texture region.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ /// them tightly packed. `BufferRegion::init` fills in the layout the backend
+ /// copies fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination texture region.
+ /// Source buffer region.
+ ///
+ [LinkName("bgfx_blit_from_buffer")]
+ public static extern void blit_from_buffer(ViewId _id, TextureRegion* _dst, BufferRegion* _src);
public static bgfx.StateFlags blend_function_separate(bgfx.StateFlags _srcRGB, bgfx.StateFlags _dstRGB, bgfx.StateFlags _srcA, bgfx.StateFlags _dstA)
diff --git a/bindings/c3/bgfx.c3 b/bindings/c3/bgfx.c3
index 46d98c4f0..e9e602685 100644
--- a/bindings/c3/bgfx.c3
+++ b/bindings/c3/bgfx.c3
@@ -1692,6 +1692,12 @@ struct CapsLimits
uint maxTransientIbSize;
// Mimimum uniform buffer size.
uint minUniformBufferSize;
+ // Row pitch alignment, in bytes, that buffer to texture blit copies
+ // natively. Any other `BufferRegion::rowPitch` is repacked internally.
+ uint blitRowPitchAlign;
+ // Offset alignment, in bytes, that buffer to texture blit copies
+ // natively. Any other `BufferRegion::offset` is repacked internally.
+ uint blitOffsetAlign;
}
// Renderer capabilities.
@@ -1945,6 +1951,64 @@ struct InstanceDataBuffer
VertexBufferHandle handle;
}
+// Region of a texture, used as the source or destination of a blit, or as
+// the region handed to `bgfx::read`.
+//
+// Every field defaults to zero, and zero always means "the natural whole".
+// `{ .handle = tex }` therefore addresses all of mip 0.
+struct TextureRegion
+{
+ // Texture handle.
+ TextureHandle handle;
+ // Mip level.
+ char mip;
+ // X position of the region.
+ ushort x;
+ // Y position of the region.
+ ushort y;
+ // If texture is 2D this should be 0. If the texture is a cube map
+ // this is the cube face, for a 2D array it is the layer, and for a
+ // 3D texture it is the Z position.
+ ushort z;
+ // Width of the region. 0 uses the rest of the mip from `x`.
+ ushort width;
+ // Height of the region. 0 uses the rest of the mip from `y`.
+ ushort height;
+ // Depth of the region for a 3D texture, or the number of layers or
+ // cube faces otherwise. 0 uses the rest from `z`.
+ ushort depth;
+}
+
+// Region of a buffer, used as the source or destination of a blit, or as the
+// region handed to `bgfx::read`.
+//
+// `rowPitch` and `slicePitch` describe how texture data is laid out in the
+// buffer, and are ignored when the other end of the blit is also a buffer.
+// Both are in bytes, and 0 selects the tightly packed layout: a row pitch of
+// the region width in blocks multiplied by the block size, and a slice pitch
+// of that row pitch multiplied by the region height in blocks.
+//
+// A pitch the backend cannot copy natively is repacked by bgfx, which costs
+// an extra pass over the data. `Caps::Limits::blitRowPitchAlign` and
+// `blitOffsetAlign` report what the backend copies directly, and
+// `BufferRegion::init` fills in a layout that matches them.
+struct BufferRegion
+{
+ // Buffer handle.
+ BufferHandle handle;
+ // Byte offset into the buffer.
+ uint offset;
+ // Number of bytes. Only used when both ends of a blit are
+ // buffers, or by `bgfx::read`. 0 uses the rest of the buffer.
+ uint size;
+ // Distance in bytes between the start of two consecutive rows
+ // of blocks. 0 is tightly packed.
+ uint rowPitch;
+ // Distance in bytes between the start of two consecutive
+ // slices, layers or cube faces. 0 is tightly packed.
+ uint slicePitch;
+}
+
// Texture info.
struct TextureInfo
{
@@ -1982,7 +2046,7 @@ struct VideoDecoderInit
// Video codec. See: `VideoCodec::Enum`.
VideoCodec codec;
// Codec parameter sets (Annex B for H.264/H.265, OBUs for AV1).
- uint8_t* parameterSets;
+ char* parameterSets;
// Parameter sets size in bytes.
uint parameterSetsSize;
// Soft cap (in bytes) on the streaming access-unit FIFO (when
@@ -2025,7 +2089,7 @@ struct VideoDecoderFrame
// Structure magic. Must be `BX_MAKEFOURCC('V', 'D', 'F', 0x0)`.
uint magic;
// Concatenated access-unit bitstream (decode order). NULL for presentation-only ticks.
- uint8_t* bitstream;
+ char* bitstream;
// Per-AU size and PTS array. NULL when `numAus == 0`.
VideoDecoderAu* aus;
// Number of access units in this batch. 0 for presentation-only ticks.
@@ -2132,6 +2196,10 @@ struct Stats
uint numCompute;
// Number of blit calls submitted.
uint numBlit;
+ // Number of buffer to texture blit calls that had to be repacked,
+ // because `BufferRegion::rowPitch` or `offset` didn't match
+ // `Caps::Limits::blitRowPitchAlign` or `blitOffsetAlign`.
+ uint numBlitRepack;
// Highest number of draw+compute calls requested in a single
// frame so far (peak demand, before any were dropped). Useful
// to tune `Init::Limits::numDrawCalls`.
@@ -2259,6 +2327,35 @@ struct VertexLayoutHandle {
ushort idx;
}
+struct BufferHandle {
+ ushort idx;
+ ushort type;
+}
+
+// Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+// at zero, which addresses mip 0 of the only slice a 2D texture has.
+// _handle : `Texture handle.`
+// _x : `X position of the region.`
+// _y : `Y position of the region.`
+// _width : `Width of the region. 0 uses the rest of the mip from `_x`.`
+// _height : `Height of the region. 0 uses the rest of the mip from `_y`.`
+extern fn void texture_region_init(TextureRegion* _this, TextureHandle _handle, ushort _x, ushort _y, ushort _width, ushort _height) @cname("bgfx_texture_region_init");
+
+// Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+// fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+// `handle` is left untouched, so `size` can be used to create the buffer the
+// region will point at.
+// _texture : `Texture region the buffer is copied to or from.`
+extern fn void buffer_region_init_texture(BufferRegion* _this, TextureRegion* _texture) @cname("bgfx_buffer_region_init_texture");
+
+// Fill in the region a blit between two buffers copies. `rowPitch` and
+// `slicePitch` are left at zero, since neither end of such a blit is a
+// texture.
+// _handle : `Buffer handle.`
+// _offset : `Byte offset into the buffer.`
+// _size : `Number of bytes. 0 uses the rest of the buffer.`
+extern fn void buffer_region_init_buffer(BufferRegion* _this, BufferHandle _handle, uint _offset, uint _size) @cname("bgfx_buffer_region_init_buffer");
+
// Init attachment.
// _handle : `Render target texture handle.`
// _access : `Access. See `Access::Enum`.`
@@ -2498,6 +2595,24 @@ extern fn void dbg_text_image(ushort _x, ushort _y, ushort _width, ushort _heigh
// _flags : `Buffer creation flags. - `BGFX_BUFFER_NONE` - No flags. - `BGFX_BUFFER_COMPUTE_READ` - Buffer will be read from by compute shader. - `BGFX_BUFFER_COMPUTE_WRITE` - Buffer will be written into by compute shader. When buffer is created with `BGFX_BUFFER_COMPUTE_WRITE` flag it cannot be updated from CPU. - `BGFX_BUFFER_COMPUTE_READ_WRITE` - Buffer will be used for read/write by compute shader. - `BGFX_BUFFER_ALLOW_RESIZE` - Buffer will resize on buffer update if a different amount of data is passed. If this flag is not specified, and more data is passed on update, the buffer will be trimmed to fit the existing buffer size. This flag has effect only on dynamic buffers. - `BGFX_BUFFER_INDEX32` - Buffer is using 32-bit indices. This flag has effect only on index buffers.`
extern fn IndexBufferHandle create_index_buffer(Memory* _mem, ushort _flags) @cname("bgfx_create_index_buffer");
+// Read back contents of buffer.
+//
+// @remarks
+// Read back is asynchronous, and the result is available at the returned frame.
+// A zero `size` reads the rest of the buffer. `rowPitch` and `slicePitch` are
+// unused.
+//
+// Read back is intended for reading GPU written (compute, or draw indirect) buffers
+// back to the CPU. It's not intended to be used in the main render loop, since it
+// stalls the GPU.
+//
+// @attention Buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+//
+// _src : `Source buffer region.`
+// _data : `Destination buffer.`
+extern fn uint read_buffer(BufferRegion* _src, void* _data) @cname("bgfx_read_buffer");
+
// Set static index buffer debug name.
// _handle : `Static index buffer handle.`
// _name : `Static index buffer name.`
@@ -2817,16 +2932,22 @@ extern fn void clear_texture(TextureHandle _handle, char _mip, char _numMips, us
// Read back texture content.
//
+// @remarks
+// Read back is asynchronous, and the result is available at the returned frame.
+// `TextureRegion::z` selects cube face, 3D slice, or array layer. The region must
+// cover the whole mip.
+//
+// Read back is not intended to be used in the main render loop, since it stalls
+// the GPU.
+//
// @attention Texture must be created with `BGFX_TEXTURE_READ_BACK` flag.
// It's a texture for CPU readback, and can't be a GPU resource
// at the same time. See `examples/30-picking`.
// @attention Availability depends on: `BGFX_CAPS_TEXTURE_READ_BACK`.
//
-// _handle : `Texture handle.`
+// _src : `Source texture region.`
// _data : `Destination buffer.`
-// _layer : `Texture layer.`
-// _mip : `Mip level.`
-extern fn uint read_texture(TextureHandle _handle, void* _data, ushort _layer, char _mip) @cname("bgfx_read_texture");
+extern fn uint read_texture(TextureRegion* _src, void* _data) @cname("bgfx_read_texture");
// Set texture debug name.
// _handle : `Texture handle.`
@@ -3499,26 +3620,86 @@ extern fn void encoder_dispatch_indirect(Encoder* _this, ushort _id, ProgramHand
// _flags : `Discard or preserve states. See `BGFX_DISCARD_*`.`
extern fn void encoder_discard(Encoder* _this, char _flags) @cname("bgfx_encoder_discard");
-// Blit 2D texture region between two 2D textures.
+// Blit texture region between two textures.
+//
+// @remarks
+// The copy covers the region the two sides have in common: each side gives
+// the origin it starts at, and the size is the smaller of the two extents.
+// A zero `width`, `height` or `depth` extends to the rest of that mip.
+//
+// Blit is performed on GPU, and it is ordered within the view. In views, all
+// draw commands are executed after blit and compute commands.
//
// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
//
// _id : `View id.`
-// _dst : `Destination texture handle.`
-// _dstMip : `Destination texture mip level.`
-// _dstX : `Destination texture X position.`
-// _dstY : `Destination texture Y position.`
-// _dstZ : `If texture is 2D this argument should be 0. If destination texture is cube this argument represents destination texture cube face. For 3D texture this argument represents destination texture Z position.`
-// _src : `Source texture handle.`
-// _srcMip : `Source texture mip level.`
-// _srcX : `Source texture X position.`
-// _srcY : `Source texture Y position.`
-// _srcZ : `If texture is 2D this argument should be 0. If source texture is cube this argument represents source texture cube face. For 3D texture this argument represents source texture Z position.`
-// _width : `Width of region.`
-// _height : `Height of region.`
-// _depth : `If texture is 3D this argument represents depth of region, otherwise it's unused.`
-extern fn void encoder_blit(Encoder* _this, ushort _id, TextureHandle _dst, char _dstMip, ushort _dstX, ushort _dstY, ushort _dstZ, TextureHandle _src, char _srcMip, ushort _srcX, ushort _srcY, ushort _srcZ, ushort _width, ushort _height, ushort _depth) @cname("bgfx_encoder_blit");
+// _dst : `Destination texture region.`
+// _src : `Source texture region.`
+extern fn void encoder_blit(Encoder* _this, ushort _id, TextureRegion* _dst, TextureRegion* _src) @cname("bgfx_encoder_blit");
+
+// Blit buffer region between two buffers.
+//
+// @remarks
+// The source region gives the number of bytes copied, and the destination
+// region gives only the offset they land at. A zero `size` copies the rest of
+// the source buffer. `rowPitch` and `slicePitch` are unused.
+//
+// Buffer blit is performed on GPU, and it is ordered within the view, same as
+// texture blit. In views, all draw commands are executed after blit and compute
+// commands.
+//
+// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+// @attention Source and destination buffer must be different.
+//
+// _id : `View id.`
+// _dst : `Destination buffer region.`
+// _src : `Source buffer region.`
+extern fn void encoder_blit_buffer(Encoder* _this, ushort _id, BufferRegion* _dst, BufferRegion* _src) @cname("bgfx_encoder_blit_buffer");
+
+// Blit texture region into buffer.
+//
+// @remarks
+// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+// them tightly. `BufferRegion::init` fills in the layout the backend copies
+// fastest, and bgfx repacks internally for any other layout.
+//
+// Blit is performed on GPU, and it is ordered within the view, same as texture
+// blit. In views, all draw commands are executed after blit and compute commands.
+//
+// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+//
+// _id : `View id.`
+// _dst : `Destination buffer region.`
+// _src : `Source texture region.`
+extern fn void encoder_blit_to_buffer(Encoder* _this, ushort _id, BufferRegion* _dst, TextureRegion* _src) @cname("bgfx_encoder_blit_to_buffer");
+
+// Blit buffer contents into texture region.
+//
+// @remarks
+// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+// them tightly packed. `BufferRegion::init` fills in the layout the backend
+// copies fastest, and bgfx repacks internally for any other layout.
+//
+// Blit is performed on GPU, and it is ordered within the view, same as texture
+// blit. In views, all draw commands are executed after blit and compute commands.
+//
+// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+//
+// _id : `View id.`
+// _dst : `Destination texture region.`
+// _src : `Source buffer region.`
+extern fn void encoder_blit_from_buffer(Encoder* _this, ushort _id, TextureRegion* _dst, BufferRegion* _src) @cname("bgfx_encoder_blit_from_buffer");
// Request screen shot of window back buffer.
//
@@ -3937,24 +4118,84 @@ extern fn void dispatch_indirect(ushort _id, ProgramHandle _program, IndirectBuf
// _flags : `Draw/compute states to discard.`
extern fn void discard(char _flags) @cname("bgfx_discard");
-// Blit 2D texture region between two 2D textures.
+// Blit texture region between two textures.
+//
+// @remarks
+// The copy covers the region the two sides have in common: each side gives
+// the origin it starts at, and the size is the smaller of the two extents.
+// A zero `width`, `height` or `depth` extends to the rest of that mip.
+//
+// Blit is performed on GPU, and it is ordered within the view. In views, all
+// draw commands are executed after blit and compute commands.
//
// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
//
// _id : `View id.`
-// _dst : `Destination texture handle.`
-// _dstMip : `Destination texture mip level.`
-// _dstX : `Destination texture X position.`
-// _dstY : `Destination texture Y position.`
-// _dstZ : `If texture is 2D this argument should be 0. If destination texture is cube this argument represents destination texture cube face. For 3D texture this argument represents destination texture Z position.`
-// _src : `Source texture handle.`
-// _srcMip : `Source texture mip level.`
-// _srcX : `Source texture X position.`
-// _srcY : `Source texture Y position.`
-// _srcZ : `If texture is 2D this argument should be 0. If source texture is cube this argument represents source texture cube face. For 3D texture this argument represents source texture Z position.`
-// _width : `Width of region.`
-// _height : `Height of region.`
-// _depth : `If texture is 3D this argument represents depth of region, otherwise it's unused.`
-extern fn void blit(ushort _id, TextureHandle _dst, char _dstMip, ushort _dstX, ushort _dstY, ushort _dstZ, TextureHandle _src, char _srcMip, ushort _srcX, ushort _srcY, ushort _srcZ, ushort _width, ushort _height, ushort _depth) @cname("bgfx_blit");
+// _dst : `Destination texture region.`
+// _src : `Source texture region.`
+extern fn void blit(ushort _id, TextureRegion* _dst, TextureRegion* _src) @cname("bgfx_blit");
+
+// Blit buffer region between two buffers.
+//
+// @remarks
+// The source region gives the number of bytes copied, and the destination
+// region gives only the offset they land at. A zero `size` copies the rest of
+// the source buffer. `rowPitch` and `slicePitch` are unused.
+//
+// Buffer blit is performed on GPU, and it is ordered within the view, same as
+// texture blit. In views, all draw commands are executed after blit and compute
+// commands.
+//
+// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+// @attention Source and destination buffer must be different.
+//
+// _id : `View id.`
+// _dst : `Destination buffer region.`
+// _src : `Source buffer region.`
+extern fn void blit_buffer(ushort _id, BufferRegion* _dst, BufferRegion* _src) @cname("bgfx_blit_buffer");
+
+// Blit texture region into buffer.
+//
+// @remarks
+// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+// them tightly. `BufferRegion::init` fills in the layout the backend copies
+// fastest, and bgfx repacks internally for any other layout.
+//
+// Blit is performed on GPU, and it is ordered within the view, same as texture
+// blit. In views, all draw commands are executed after blit and compute commands.
+//
+// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+//
+// _id : `View id.`
+// _dst : `Destination buffer region.`
+// _src : `Source texture region.`
+extern fn void blit_to_buffer(ushort _id, BufferRegion* _dst, TextureRegion* _src) @cname("bgfx_blit_to_buffer");
+
+// Blit buffer contents into texture region.
+//
+// @remarks
+// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+// them tightly packed. `BufferRegion::init` fills in the layout the backend
+// copies fastest, and bgfx repacks internally for any other layout.
+//
+// Blit is performed on GPU, and it is ordered within the view, same as texture
+// blit. In views, all draw commands are executed after blit and compute commands.
+//
+// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+//
+// _id : `View id.`
+// _dst : `Destination texture region.`
+// _src : `Source buffer region.`
+extern fn void blit_from_buffer(ushort _id, TextureRegion* _dst, BufferRegion* _src) @cname("bgfx_blit_from_buffer");
diff --git a/bindings/cs/bgfx.cs b/bindings/cs/bgfx.cs
index 755adf316..567a7a6f4 100644
--- a/bindings/cs/bgfx.cs
+++ b/bindings/cs/bgfx.cs
@@ -2597,6 +2597,8 @@ public static partial class bgfx
public uint maxTransientVbSize;
public uint maxTransientIbSize;
public uint minUniformBufferSize;
+ public uint blitRowPitchAlign;
+ public uint blitOffsetAlign;
}
public RendererType rendererType;
@@ -2704,6 +2706,27 @@ public static partial class bgfx
public VertexBufferHandle handle;
}
+ public unsafe struct TextureRegion
+ {
+ public TextureHandle handle;
+ public byte mip;
+ public ushort x;
+ public ushort y;
+ public ushort z;
+ public ushort width;
+ public ushort height;
+ public ushort depth;
+ }
+
+ public unsafe struct BufferRegion
+ {
+ public BufferHandle handle;
+ public uint offset;
+ public uint size;
+ public uint rowPitch;
+ public uint slicePitch;
+ }
+
public unsafe struct TextureInfo
{
public TextureFormat format;
@@ -2721,7 +2744,7 @@ public static partial class bgfx
{
public uint magic;
public VideoCodec codec;
- public uint8_t* parameterSets;
+ public byte* parameterSets;
public uint parameterSetsSize;
public uint cachedAuBytes;
public byte flags;
@@ -2736,7 +2759,7 @@ public static partial class bgfx
public unsafe struct VideoDecoderFrame
{
public uint magic;
- public uint8_t* bitstream;
+ public byte* bitstream;
public VideoDecoderAu* aus;
public uint numAus;
public long presentationTimeUs;
@@ -2797,6 +2820,7 @@ public static partial class bgfx
public uint numDraw;
public uint numCompute;
public uint numBlit;
+ public uint numBlitRepack;
public uint numDrawCallsPeak;
public uint maxGpuLatency;
public uint gpuFrameNum;
@@ -2900,7 +2924,52 @@ public static partial class bgfx
public bool Valid => idx != UInt16.MaxValue;
}
+ public struct BufferHandle {
+ public ushort idx;
+ public ushort type;
+ public bool Valid => idx != UInt16.MaxValue;
+ }
+
+ ///
+ /// Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+ /// at zero, which addresses mip 0 of the only slice a 2D texture has.
+ ///
+ ///
+ /// Texture handle.
+ /// X position of the region.
+ /// Y position of the region.
+ /// Width of the region. 0 uses the rest of the mip from `_x`.
+ /// Height of the region. 0 uses the rest of the mip from `_y`.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_texture_region_init", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe void texture_region_init(TextureRegion* _this, TextureHandle _handle, ushort _x, ushort _y, ushort _width, ushort _height);
+
+ ///
+ /// Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+ /// fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+ /// `handle` is left untouched, so `size` can be used to create the buffer the
+ /// region will point at.
+ ///
+ ///
+ /// Texture region the buffer is copied to or from.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_buffer_region_init_texture", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe void buffer_region_init_texture(BufferRegion* _this, TextureRegion* _texture);
+
+ ///
+ /// Fill in the region a blit between two buffers copies. `rowPitch` and
+ /// `slicePitch` are left at zero, since neither end of such a blit is a
+ /// texture.
+ ///
+ ///
+ /// Buffer handle.
+ /// Byte offset into the buffer.
+ /// Number of bytes. 0 uses the rest of the buffer.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_buffer_region_init_buffer", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe void buffer_region_init_buffer(BufferRegion* _this, BufferHandle _handle, uint _offset, uint _size);
+
///
/// Init attachment.
///
@@ -3291,6 +3360,29 @@ public static partial class bgfx
[DllImport(DllName, EntryPoint="bgfx_create_index_buffer", CallingConvention = CallingConvention.Cdecl)]
public static extern unsafe IndexBufferHandle create_index_buffer(Memory* _mem, ushort _flags);
+ ///
+ /// Read back contents of buffer.
+ ///
+ /// @remarks
+ /// Read back is asynchronous, and the result is available at the returned frame.
+ /// A zero `size` reads the rest of the buffer. `rowPitch` and `slicePitch` are
+ /// unused.
+ ///
+ /// Read back is intended for reading GPU written (compute, or draw indirect) buffers
+ /// back to the CPU. It's not intended to be used in the main render loop, since it
+ /// stalls the GPU.
+ ///
+ /// @attention Buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ ///
+ ///
+ ///
+ /// Source buffer region.
+ /// Destination buffer.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_read_buffer", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe uint read_buffer(BufferRegion* _src, void* _data);
+
///
/// Set static index buffer debug name.
///
@@ -3835,6 +3927,14 @@ public static partial class bgfx
///
/// Read back texture content.
///
+ /// @remarks
+ /// Read back is asynchronous, and the result is available at the returned frame.
+ /// `TextureRegion::z` selects cube face, 3D slice, or array layer. The region must
+ /// cover the whole mip.
+ ///
+ /// Read back is not intended to be used in the main render loop, since it stalls
+ /// the GPU.
+ ///
/// @attention Texture must be created with `BGFX_TEXTURE_READ_BACK` flag.
/// It's a texture for CPU readback, and can't be a GPU resource
/// at the same time. See `examples/30-picking`.
@@ -3842,13 +3942,11 @@ public static partial class bgfx
///
///
///
- /// Texture handle.
+ /// Source texture region.
/// Destination buffer.
- /// Texture layer.
- /// Mip level.
///
[DllImport(DllName, EntryPoint="bgfx_read_texture", CallingConvention = CallingConvention.Cdecl)]
- public static extern unsafe uint read_texture(TextureHandle _handle, void* _data, ushort _layer, byte _mip);
+ public static extern unsafe uint read_texture(TextureRegion* _src, void* _data);
///
/// Set texture debug name.
@@ -4911,7 +5009,15 @@ public static partial class bgfx
public static extern unsafe void encoder_discard(Encoder* _this, byte _flags);
///
- /// Blit 2D texture region between two 2D textures.
+ /// Blit texture region between two textures.
+ ///
+ /// @remarks
+ /// The copy covers the region the two sides have in common: each side gives
+ /// the origin it starts at, and the size is the smaller of the two extents.
+ /// A zero `width`, `height` or `depth` extends to the rest of that mip.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view. In views, all
+ /// draw commands are executed after blit and compute commands.
///
/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
@@ -4919,22 +5025,89 @@ public static partial class bgfx
///
///
/// View id.
- /// Destination texture handle.
- /// Destination texture mip level.
- /// Destination texture X position.
- /// Destination texture Y position.
- /// If texture is 2D this argument should be 0. If destination texture is cube this argument represents destination texture cube face. For 3D texture this argument represents destination texture Z position.
- /// Source texture handle.
- /// Source texture mip level.
- /// Source texture X position.
- /// Source texture Y position.
- /// If texture is 2D this argument should be 0. If source texture is cube this argument represents source texture cube face. For 3D texture this argument represents source texture Z position.
- /// Width of region.
- /// Height of region.
- /// If texture is 3D this argument represents depth of region, otherwise it's unused.
+ /// Destination texture region.
+ /// Source texture region.
///
[DllImport(DllName, EntryPoint="bgfx_encoder_blit", CallingConvention = CallingConvention.Cdecl)]
- public static extern unsafe void encoder_blit(Encoder* _this, ushort _id, TextureHandle _dst, byte _dstMip, ushort _dstX, ushort _dstY, ushort _dstZ, TextureHandle _src, byte _srcMip, ushort _srcX, ushort _srcY, ushort _srcZ, ushort _width, ushort _height, ushort _depth);
+ public static extern unsafe void encoder_blit(Encoder* _this, ushort _id, TextureRegion* _dst, TextureRegion* _src);
+
+ ///
+ /// Blit buffer region between two buffers.
+ ///
+ /// @remarks
+ /// The source region gives the number of bytes copied, and the destination
+ /// region gives only the offset they land at. A zero `size` copies the rest of
+ /// the source buffer. `rowPitch` and `slicePitch` are unused.
+ ///
+ /// Buffer blit is performed on GPU, and it is ordered within the view, same as
+ /// texture blit. In views, all draw commands are executed after blit and compute
+ /// commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Source and destination buffer must be different.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source buffer region.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_encoder_blit_buffer", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe void encoder_blit_buffer(Encoder* _this, ushort _id, BufferRegion* _dst, BufferRegion* _src);
+
+ ///
+ /// Blit texture region into buffer.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ /// them tightly. `BufferRegion::init` fills in the layout the backend copies
+ /// fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source texture region.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_encoder_blit_to_buffer", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe void encoder_blit_to_buffer(Encoder* _this, ushort _id, BufferRegion* _dst, TextureRegion* _src);
+
+ ///
+ /// Blit buffer contents into texture region.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ /// them tightly packed. `BufferRegion::init` fills in the layout the backend
+ /// copies fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination texture region.
+ /// Source buffer region.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_encoder_blit_from_buffer", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe void encoder_blit_from_buffer(Encoder* _this, ushort _id, TextureRegion* _dst, BufferRegion* _src);
///
/// Request screen shot of window back buffer.
@@ -5588,7 +5761,15 @@ public static partial class bgfx
public static extern unsafe void discard(byte _flags);
///
- /// Blit 2D texture region between two 2D textures.
+ /// Blit texture region between two textures.
+ ///
+ /// @remarks
+ /// The copy covers the region the two sides have in common: each side gives
+ /// the origin it starts at, and the size is the smaller of the two extents.
+ /// A zero `width`, `height` or `depth` extends to the rest of that mip.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view. In views, all
+ /// draw commands are executed after blit and compute commands.
///
/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
@@ -5596,22 +5777,89 @@ public static partial class bgfx
///
///
/// View id.
- /// Destination texture handle.
- /// Destination texture mip level.
- /// Destination texture X position.
- /// Destination texture Y position.
- /// If texture is 2D this argument should be 0. If destination texture is cube this argument represents destination texture cube face. For 3D texture this argument represents destination texture Z position.
- /// Source texture handle.
- /// Source texture mip level.
- /// Source texture X position.
- /// Source texture Y position.
- /// If texture is 2D this argument should be 0. If source texture is cube this argument represents source texture cube face. For 3D texture this argument represents source texture Z position.
- /// Width of region.
- /// Height of region.
- /// If texture is 3D this argument represents depth of region, otherwise it's unused.
+ /// Destination texture region.
+ /// Source texture region.
///
[DllImport(DllName, EntryPoint="bgfx_blit", CallingConvention = CallingConvention.Cdecl)]
- public static extern unsafe void blit(ushort _id, TextureHandle _dst, byte _dstMip, ushort _dstX, ushort _dstY, ushort _dstZ, TextureHandle _src, byte _srcMip, ushort _srcX, ushort _srcY, ushort _srcZ, ushort _width, ushort _height, ushort _depth);
+ public static extern unsafe void blit(ushort _id, TextureRegion* _dst, TextureRegion* _src);
+
+ ///
+ /// Blit buffer region between two buffers.
+ ///
+ /// @remarks
+ /// The source region gives the number of bytes copied, and the destination
+ /// region gives only the offset they land at. A zero `size` copies the rest of
+ /// the source buffer. `rowPitch` and `slicePitch` are unused.
+ ///
+ /// Buffer blit is performed on GPU, and it is ordered within the view, same as
+ /// texture blit. In views, all draw commands are executed after blit and compute
+ /// commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Source and destination buffer must be different.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source buffer region.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_blit_buffer", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe void blit_buffer(ushort _id, BufferRegion* _dst, BufferRegion* _src);
+
+ ///
+ /// Blit texture region into buffer.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ /// them tightly. `BufferRegion::init` fills in the layout the backend copies
+ /// fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source texture region.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_blit_to_buffer", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe void blit_to_buffer(ushort _id, BufferRegion* _dst, TextureRegion* _src);
+
+ ///
+ /// Blit buffer contents into texture region.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ /// them tightly packed. `BufferRegion::init` fills in the layout the backend
+ /// copies fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ ///
+ ///
+ /// View id.
+ /// Destination texture region.
+ /// Source buffer region.
+ ///
+ [DllImport(DllName, EntryPoint="bgfx_blit_from_buffer", CallingConvention = CallingConvention.Cdecl)]
+ public static extern unsafe void blit_from_buffer(ushort _id, TextureRegion* _dst, BufferRegion* _src);
}
}
diff --git a/bindings/d/package.d b/bindings/d/package.d
index 2db1b1d5a..90b2ee393 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 = 156;
+enum uint apiVersion = 157;
alias ViewID = ushort;
@@ -1003,6 +1003,15 @@ extern(C++, "bgfx") struct VertexLayoutHandle{
ushort idx;
}
+/**
+Tagged buffer handle. All buffer handle types implicitly convert to it, and the tag
+keeps track of which type the handle originally was.
+*/
+extern(C++, "bgfx") struct BufferHandle{
+ ushort idx;
+ ushort type;
+}
+
pragma(inline,true) nothrow @nogc{
/**
Allocate a buffer to pass to bgfx. Data will be freed inside bgfx.
@@ -1136,6 +1145,18 @@ extern(C++, "bgfx") struct Caps{
uint maxTransientVBSize; ///Maximum transient vertex buffer size.
uint maxTransientIBSize; ///Maximum transient index buffer size.
uint minUniformBufferSize; ///Mimimum uniform buffer size.
+
+ /**
+ Row pitch alignment, in bytes, that buffer to texture blit copies
+ natively. Any other `BufferRegion::rowPitch` is repacked internally.
+ */
+ uint blitRowPitchAlign;
+
+ /**
+ Offset alignment, in bytes, that buffer to texture blit copies
+ natively. Any other `BufferRegion::offset` is repacked internally.
+ */
+ uint blitOffsetAlign;
}
RendererType rendererType; ///Renderer backend type. See: `bgfx::RendererType`
@@ -1385,6 +1406,114 @@ extern(C++, "bgfx") struct InstanceDataBuffer{
VertexBufferHandle handle; ///Vertex buffer object handle.
}
+/**
+Region of a texture, used as the source or destination of a blit, or as
+the region handed to `bgfx::read`.
+
+Every field defaults to zero, and zero always means "the natural whole".
+`{ .handle = tex }` therefore addresses all of mip 0.
+*/
+extern(C++, "bgfx") struct TextureRegion{
+ TextureHandle handle; ///Texture handle.
+ ubyte mip; ///Mip level.
+ ushort x; ///X position of the region.
+ ushort y; ///Y position of the region.
+
+ /**
+ If texture is 2D this should be 0. If the texture is a cube map
+ this is the cube face, for a 2D array it is the layer, and for a
+ 3D texture it is the Z position.
+ */
+ ushort z;
+ ushort width; ///Width of the region. 0 uses the rest of the mip from `x`.
+ ushort height; ///Height of the region. 0 uses the rest of the mip from `y`.
+
+ /**
+ Depth of the region for a 3D texture, or the number of layers or
+ cube faces otherwise. 0 uses the rest from `z`.
+ */
+ ushort depth;
+ extern(D) mixin(joinFnBinds((){
+ FnBind[] ret = [
+ /**
+ Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+ at zero, which addresses mip 0 of the only slice a 2D texture has.
+ Params:
+ handle = Texture handle.
+ x = X position of the region.
+ y = Y position of the region.
+ width = Width of the region. 0 uses the rest of the mip from `_x`.
+ height = Height of the region. 0 uses the rest of the mip from `_y`.
+ */
+ {q{void}, q{init}, q{TextureHandle handle, ushort x=0, ushort y=0, ushort width=0, ushort height=0}, ext: `C++`},
+ ];
+ return ret;
+ }()));
+}
+
+/**
+Region of a buffer, used as the source or destination of a blit, or as the
+region handed to `bgfx::read`.
+
+`rowPitch` and `slicePitch` describe how texture data is laid out in the
+buffer, and are ignored when the other end of the blit is also a buffer.
+Both are in bytes, and 0 selects the tightly packed layout: a row pitch of
+the region width in blocks multiplied by the block size, and a slice pitch
+of that row pitch multiplied by the region height in blocks.
+
+A pitch the backend cannot copy natively is repacked by bgfx, which costs
+an extra pass over the data. `Caps::Limits::blitRowPitchAlign` and
+`blitOffsetAlign` report what the backend copies directly, and
+`BufferRegion::init` fills in a layout that matches them.
+*/
+extern(C++, "bgfx") struct BufferRegion{
+ BufferHandle handle; ///Buffer handle.
+ uint offset; ///Byte offset into the buffer.
+
+ /**
+ Number of bytes. Only used when both ends of a blit are
+ buffers, or by `bgfx::read`. 0 uses the rest of the buffer.
+ */
+ uint size;
+
+ /**
+ Distance in bytes between the start of two consecutive rows
+ of blocks. 0 is tightly packed.
+ */
+ uint rowPitch;
+
+ /**
+ Distance in bytes between the start of two consecutive
+ slices, layers or cube faces. 0 is tightly packed.
+ */
+ uint slicePitch;
+ extern(D) mixin(joinFnBinds((){
+ FnBind[] ret = [
+ /**
+ Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+ fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+ `handle` is left untouched, so `size` can be used to create the buffer the
+ region will point at.
+ Params:
+ texture = Texture region the buffer is copied to or from.
+ */
+ {q{void}, q{init}, q{ref const TextureRegion texture}, ext: `C++`},
+
+ /**
+ Fill in the region a blit between two buffers copies. `rowPitch` and
+ `slicePitch` are left at zero, since neither end of such a blit is a
+ texture.
+ Params:
+ handle = Buffer handle.
+ offset = Byte offset into the buffer.
+ size = Number of bytes. 0 uses the rest of the buffer.
+ */
+ {q{void}, q{init}, q{BufferHandle handle, uint offset=0, uint size=0}, ext: `C++`},
+ ];
+ return ret;
+ }()));
+}
+
///Texture info.
extern(C++, "bgfx") struct TextureInfo{
TextureFormat format; ///Texture format.
@@ -1540,6 +1669,13 @@ extern(C++, "bgfx") struct Stats{
uint numCompute; ///Number of compute calls submitted.
uint numBlit; ///Number of blit calls submitted.
+ /**
+ Number of buffer to texture blit calls that had to be repacked,
+ because `BufferRegion::rowPitch` or `offset` didn't match
+ `Caps::Limits::blitRowPitchAlign` or `blitOffsetAlign`.
+ */
+ uint numBlitRepack;
+
/**
Highest number of draw+compute calls requested in a single
frame so far (peak demand, before any were dropped). Useful
@@ -2141,52 +2277,97 @@ extern(C++, "bgfx") struct Encoder{
{q{void}, q{discard}, q{ubyte flags=Discard.all}, ext: `C++`},
/**
- Blit 2D texture region between two 2D textures.
+ Blit texture region between two textures.
+
+ Remarks:
+ The copy covers the region the two sides have in common: each side gives
+ the origin it starts at, and the size is the smaller of the two extents.
+ A zero `width`, `height` or `depth` extends to the rest of that mip.
+
+ Blit is performed on GPU, and it is ordered within the view. In views, all
+ draw commands are executed after blit and compute commands.
Attention: Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
Attention: Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
Params:
id = View id.
- dst = Destination texture handle.
- dstX = Destination texture X position.
- dstY = Destination texture Y position.
- src = Source texture handle.
- srcX = Source texture X position.
- srcY = Source texture Y position.
- width = Width of region.
- height = Height of region.
+ dst = Destination texture region.
+ src = Source texture region.
*/
- {q{void}, q{blit}, q{ViewID id, TextureHandle dst, ushort dstX, ushort dstY, TextureHandle src, ushort srcX=0, ushort srcY=0, ushort width=ushort.max, ushort height=ushort.max}, ext: `C++`},
+ {q{void}, q{blit}, q{ViewID id, ref const TextureRegion dst, ref const TextureRegion src}, ext: `C++`},
/**
- Blit 2D texture region between two 2D textures.
+ Blit buffer region between two buffers.
+ Remarks:
+ The source region gives the number of bytes copied, and the destination
+ region gives only the offset they land at. A zero `size` copies the rest of
+ the source buffer. `rowPitch` and `slicePitch` are unused.
+
+ Buffer blit is performed on GPU, and it is ordered within the view, same as
+ texture blit. In views, all draw commands are executed after blit and compute
+ commands.
+
+ Attention: Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ Attention: Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ Attention: Source and destination buffer must be different.
+
+ Params:
+ id = View id.
+ dst = Destination buffer region.
+ src = Source buffer region.
+ */
+ {q{void}, q{blit}, q{ViewID id, ref const BufferRegion dst, ref const BufferRegion src}, ext: `C++`},
+
+ /**
+ Blit texture region into buffer.
+
+ Remarks:
+ The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ them tightly. `BufferRegion::init` fills in the layout the backend copies
+ fastest, and bgfx repacks internally for any other layout.
+
+ Blit is performed on GPU, and it is ordered within the view, same as texture
+ blit. In views, all draw commands are executed after blit and compute commands.
+
+ Attention: Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ Attention: Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+
+ Params:
+ id = View id.
+ dst = Destination buffer region.
+ src = Source texture region.
+ */
+ {q{void}, q{blit}, q{ViewID id, ref const BufferRegion dst, ref const TextureRegion src}, ext: `C++`},
+
+ /**
+ Blit buffer contents into texture region.
+
+ Remarks:
+ The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ them tightly packed. `BufferRegion::init` fills in the layout the backend
+ copies fastest, and bgfx repacks internally for any other layout.
+
+ Blit is performed on GPU, and it is ordered within the view, same as texture
+ blit. In views, all draw commands are executed after blit and compute commands.
+
+ Attention: Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ `BGFX_BUFFER_DRAW_INDIRECT` flags.
Attention: Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
Attention: Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
Params:
id = View id.
- dst = Destination texture handle.
- dstMIP = Destination texture mip level.
- dstX = Destination texture X position.
- dstY = Destination texture Y position.
- dstZ = If texture is 2D this argument should be 0. If destination texture is cube
- this argument represents destination texture cube face. For 3D texture this argument
- represents destination texture Z position.
- src = Source texture handle.
- srcMIP = Source texture mip level.
- srcX = Source texture X position.
- srcY = Source texture Y position.
- srcZ = If texture is 2D this argument should be 0. If source texture is cube
- this argument represents source texture cube face. For 3D texture this argument
- represents source texture Z position.
- width = Width of region.
- height = Height of region.
- depth = If texture is 3D this argument represents depth of region, otherwise it's
- unused.
+ dst = Destination texture region.
+ src = Source buffer region.
*/
- {q{void}, q{blit}, q{ViewID id, TextureHandle dst, ubyte dstMIP, ushort dstX, ushort dstY, ushort dstZ, TextureHandle src, ubyte srcMIP=0, ushort srcX=0, ushort srcY=0, ushort srcZ=0, ushort width=ushort.max, ushort height=ushort.max, ushort depth=ushort.max}, ext: `C++`},
+ {q{void}, q{blit}, q{ViewID id, ref const TextureRegion dst, ref const BufferRegion src}, ext: `C++`},
];
return ret;
}()));
@@ -2471,6 +2652,27 @@ mixin(joinFnBinds((){
*/
{q{IndexBufferHandle}, q{createIndexBuffer}, q{const(Memory)* mem, ushort flags=Buffer.none}, ext: `C++, "bgfx"`},
+ /**
+ * Read back contents of buffer.
+ *
+ * Remarks:
+ * Read back is asynchronous, and the result is available at the returned frame.
+ * A zero `size` reads the rest of the buffer. `rowPitch` and `slicePitch` are
+ * unused.
+ *
+ * Read back is intended for reading GPU written (compute, or draw indirect) buffers
+ * back to the CPU. It's not intended to be used in the main render loop, since it
+ * stalls the GPU.
+ *
+ * Attention: Buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ *
+ Params:
+ src = Source buffer region.
+ data = Destination buffer.
+ */
+ {q{uint}, q{read}, q{ref const BufferRegion src, void* data}, ext: `C++, "bgfx"`},
+
/**
* Set static index buffer debug name.
Params:
@@ -3041,18 +3243,24 @@ mixin(joinFnBinds((){
/**
* Read back texture content.
*
+ * Remarks:
+ * Read back is asynchronous, and the result is available at the returned frame.
+ * `TextureRegion::z` selects cube face, 3D slice, or array layer. The region must
+ * cover the whole mip.
+ *
+ * Read back is not intended to be used in the main render loop, since it stalls
+ * the GPU.
+ *
* Attention: Texture must be created with `BGFX_TEXTURE_READ_BACK` flag.
* It's a texture for CPU readback, and can't be a GPU resource
* at the same time. See `examples/30-picking`.
* Attention: Availability depends on: `BGFX_CAPS_TEXTURE_READ_BACK`.
*
Params:
- handle = Texture handle.
+ src = Source texture region.
data = Destination buffer.
- layer = Texture layer.
- mip = Mip level.
*/
- {q{uint}, q{readTexture}, q{TextureHandle handle, void* data, ushort layer=0, ubyte mip=0}, ext: `C++, "bgfx"`},
+ {q{uint}, q{read}, q{ref const TextureRegion src, void* data}, ext: `C++, "bgfx"`},
/**
* Set texture debug name.
@@ -4160,56 +4368,101 @@ mixin(joinFnBinds((){
{q{void}, q{discard}, q{ubyte flags=Discard.all}, ext: `C++, "bgfx"`},
/**
- * Blit 2D texture region between two 2D textures.
+ * Blit texture region between two textures.
+ *
+ * Remarks:
+ * The copy covers the region the two sides have in common: each side gives
+ * the origin it starts at, and the size is the smaller of the two extents.
+ * A zero `width`, `height` or `depth` extends to the rest of that mip.
+ *
+ * Blit is performed on GPU, and it is ordered within the view. In views, all
+ * draw commands are executed after blit and compute commands.
*
* Attention: Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
* Attention: Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
*
Params:
id = View id.
- dst = Destination texture handle.
- dstX = Destination texture X position.
- dstY = Destination texture Y position.
- src = Source texture handle.
- srcX = Source texture X position.
- srcY = Source texture Y position.
- width = Width of region.
- height = Height of region.
+ dst = Destination texture region.
+ src = Source texture region.
*/
- {q{void}, q{blit}, q{ViewID id, TextureHandle dst, ushort dstX, ushort dstY, TextureHandle src, ushort srcX=0, ushort srcY=0, ushort width=ushort.max, ushort height=ushort.max}, ext: `C++, "bgfx"`},
+ {q{void}, q{blit}, q{ViewID id, ref const TextureRegion dst, ref const TextureRegion src}, ext: `C++, "bgfx"`},
/**
- * Blit 2D texture region between two 2D textures.
+ * Blit buffer region between two buffers.
*
+ * Remarks:
+ * The source region gives the number of bytes copied, and the destination
+ * region gives only the offset they land at. A zero `size` copies the rest of
+ * the source buffer. `rowPitch` and `slicePitch` are unused.
+ *
+ * Buffer blit is performed on GPU, and it is ordered within the view, same as
+ * texture blit. In views, all draw commands are executed after blit and compute
+ * commands.
+ *
+ * Attention: Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ * Attention: Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ * Attention: Source and destination buffer must be different.
+ *
+ Params:
+ id = View id.
+ dst = Destination buffer region.
+ src = Source buffer region.
+ */
+ {q{void}, q{blit}, q{ViewID id, ref const BufferRegion dst, ref const BufferRegion src}, ext: `C++, "bgfx"`},
+
+ /**
+ * Blit texture region into buffer.
+ *
+ * Remarks:
+ * The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ * `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ * them tightly. `BufferRegion::init` fills in the layout the backend copies
+ * fastest, and bgfx repacks internally for any other layout.
+ *
+ * Blit is performed on GPU, and it is ordered within the view, same as texture
+ * blit. In views, all draw commands are executed after blit and compute commands.
+ *
+ * Attention: Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ * Attention: Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ *
+ Params:
+ id = View id.
+ dst = Destination buffer region.
+ src = Source texture region.
+ */
+ {q{void}, q{blit}, q{ViewID id, ref const BufferRegion dst, ref const TextureRegion src}, ext: `C++, "bgfx"`},
+
+ /**
+ * Blit buffer contents into texture region.
+ *
+ * Remarks:
+ * The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ * `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ * them tightly packed. `BufferRegion::init` fills in the layout the backend
+ * copies fastest, and bgfx repacks internally for any other layout.
+ *
+ * Blit is performed on GPU, and it is ordered within the view, same as texture
+ * blit. In views, all draw commands are executed after blit and compute commands.
+ *
+ * Attention: Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flags.
* Attention: Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
* Attention: Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
*
Params:
id = View id.
- dst = Destination texture handle.
- dstMIP = Destination texture mip level.
- dstX = Destination texture X position.
- dstY = Destination texture Y position.
- dstZ = If texture is 2D this argument should be 0. If destination texture is cube
- this argument represents destination texture cube face. For 3D texture this argument
- represents destination texture Z position.
- src = Source texture handle.
- srcMIP = Source texture mip level.
- srcX = Source texture X position.
- srcY = Source texture Y position.
- srcZ = If texture is 2D this argument should be 0. If source texture is cube
- this argument represents source texture cube face. For 3D texture this argument
- represents source texture Z position.
- width = Width of region.
- height = Height of region.
- depth = If texture is 3D this argument represents depth of region, otherwise it's
- unused.
+ dst = Destination texture region.
+ src = Source buffer region.
*/
- {q{void}, q{blit}, q{ViewID id, TextureHandle dst, ubyte dstMIP, ushort dstX, ushort dstY, ushort dstZ, TextureHandle src, ubyte srcMIP=0, ushort srcX=0, ushort srcY=0, ushort srcZ=0, ushort width=ushort.max, ushort height=ushort.max, ushort depth=ushort.max}, ext: `C++, "bgfx"`},
+ {q{void}, q{blit}, q{ViewID id, ref const TextureRegion dst, ref const BufferRegion src}, ext: `C++, "bgfx"`},
];
return ret;
-}(), "Resolution, Init.Limits, Init, Attachment, VertexLayout, Encoder, "));
+}(), "Resolution, Init.Limits, Init, TextureRegion, BufferRegion, Attachment, VertexLayout, Encoder, "));
static if(!staticBinding):
import bindbc.loader;
diff --git a/bindings/py/bgfx.py b/bindings/py/bgfx.py
index cda202c4e..71570b160 100644
--- a/bindings/py/bgfx.py
+++ b/bindings/py/bgfx.py
@@ -679,6 +679,12 @@ class TransientVertexBuffer(ctypes.Structure):
class InstanceDataBuffer(ctypes.Structure):
pass
+class TextureRegion(ctypes.Structure):
+ pass
+
+class BufferRegion(ctypes.Structure):
+ pass
+
class TextureInfo(ctypes.Structure):
pass
@@ -799,6 +805,13 @@ class VertexLayoutHandle(ctypes.Structure):
def valid(self):
return self.idx != 0xffff
+class BufferHandle(ctypes.Structure):
+ _fields_ = [("idx", ctypes.c_uint16), ("type", ctypes.c_uint16)]
+
+ @property
+ def valid(self):
+ return self.idx != 0xffff
+
ReleaseFn = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p)
CapsGPU._fields_ = [
@@ -834,6 +847,8 @@ CapsLimits._fields_ = [
("maxTransientVbSize", ctypes.c_uint32),
("maxTransientIbSize", ctypes.c_uint32),
("minUniformBufferSize", ctypes.c_uint32),
+ ("blitRowPitchAlign", ctypes.c_uint32),
+ ("blitOffsetAlign", ctypes.c_uint32),
]
Caps._fields_ = [
@@ -933,6 +948,25 @@ InstanceDataBuffer._fields_ = [
("handle", VertexBufferHandle),
]
+TextureRegion._fields_ = [
+ ("handle", TextureHandle),
+ ("mip", ctypes.c_uint8),
+ ("x", ctypes.c_uint16),
+ ("y", ctypes.c_uint16),
+ ("z", ctypes.c_uint16),
+ ("width", ctypes.c_uint16),
+ ("height", ctypes.c_uint16),
+ ("depth", ctypes.c_uint16),
+]
+
+BufferRegion._fields_ = [
+ ("handle", BufferHandle),
+ ("offset", ctypes.c_uint32),
+ ("size", ctypes.c_uint32),
+ ("rowPitch", ctypes.c_uint32),
+ ("slicePitch", ctypes.c_uint32),
+]
+
TextureInfo._fields_ = [
("format", ctypes.c_int),
("storageSize", ctypes.c_uint32),
@@ -1016,6 +1050,7 @@ Stats._fields_ = [
("numDraw", ctypes.c_uint32),
("numCompute", ctypes.c_uint32),
("numBlit", ctypes.c_uint32),
+ ("numBlitRepack", ctypes.c_uint32),
("numDrawCallsPeak", ctypes.c_uint32),
("maxGpuLatency", ctypes.c_uint32),
("gpuFrameNum", ctypes.c_uint32),
@@ -1063,6 +1098,18 @@ def load(path):
return _lib
def _bind(lib):
+ global bgfx_texture_region_init
+ bgfx_texture_region_init = lib.bgfx_texture_region_init
+ bgfx_texture_region_init.argtypes = [ctypes.POINTER(TextureRegion), TextureHandle, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16]
+ bgfx_texture_region_init.restype = None
+ global bgfx_buffer_region_init_texture
+ bgfx_buffer_region_init_texture = lib.bgfx_buffer_region_init_texture
+ bgfx_buffer_region_init_texture.argtypes = [ctypes.POINTER(BufferRegion), ctypes.POINTER(TextureRegion)]
+ bgfx_buffer_region_init_texture.restype = None
+ global bgfx_buffer_region_init_buffer
+ bgfx_buffer_region_init_buffer = lib.bgfx_buffer_region_init_buffer
+ bgfx_buffer_region_init_buffer.argtypes = [ctypes.POINTER(BufferRegion), BufferHandle, ctypes.c_uint32, ctypes.c_uint32]
+ bgfx_buffer_region_init_buffer.restype = None
global bgfx_attachment_init
bgfx_attachment_init = lib.bgfx_attachment_init
bgfx_attachment_init.argtypes = [ctypes.POINTER(Attachment), TextureHandle, ctypes.c_int, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint8]
@@ -1183,6 +1230,10 @@ def _bind(lib):
bgfx_create_index_buffer = lib.bgfx_create_index_buffer
bgfx_create_index_buffer.argtypes = [ctypes.POINTER(Memory), ctypes.c_uint16]
bgfx_create_index_buffer.restype = IndexBufferHandle
+ global bgfx_read_buffer
+ bgfx_read_buffer = lib.bgfx_read_buffer
+ bgfx_read_buffer.argtypes = [ctypes.POINTER(BufferRegion), ctypes.c_void_p]
+ bgfx_read_buffer.restype = ctypes.c_uint32
global bgfx_set_index_buffer_name
bgfx_set_index_buffer_name = lib.bgfx_set_index_buffer_name
bgfx_set_index_buffer_name.argtypes = [IndexBufferHandle, ctypes.c_char_p, ctypes.c_int32]
@@ -1361,7 +1412,7 @@ def _bind(lib):
bgfx_clear_texture.restype = None
global bgfx_read_texture
bgfx_read_texture = lib.bgfx_read_texture
- bgfx_read_texture.argtypes = [TextureHandle, ctypes.c_void_p, ctypes.c_uint16, ctypes.c_uint8]
+ bgfx_read_texture.argtypes = [ctypes.POINTER(TextureRegion), ctypes.c_void_p]
bgfx_read_texture.restype = ctypes.c_uint32
global bgfx_set_texture_name
bgfx_set_texture_name = lib.bgfx_set_texture_name
@@ -1677,8 +1728,20 @@ def _bind(lib):
bgfx_encoder_discard.restype = None
global bgfx_encoder_blit
bgfx_encoder_blit = lib.bgfx_encoder_blit
- bgfx_encoder_blit.argtypes = [ctypes.POINTER(Encoder), ctypes.c_uint16, TextureHandle, ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, TextureHandle, ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16]
+ bgfx_encoder_blit.argtypes = [ctypes.POINTER(Encoder), ctypes.c_uint16, ctypes.POINTER(TextureRegion), ctypes.POINTER(TextureRegion)]
bgfx_encoder_blit.restype = None
+ global bgfx_encoder_blit_buffer
+ bgfx_encoder_blit_buffer = lib.bgfx_encoder_blit_buffer
+ bgfx_encoder_blit_buffer.argtypes = [ctypes.POINTER(Encoder), ctypes.c_uint16, ctypes.POINTER(BufferRegion), ctypes.POINTER(BufferRegion)]
+ bgfx_encoder_blit_buffer.restype = None
+ global bgfx_encoder_blit_to_buffer
+ bgfx_encoder_blit_to_buffer = lib.bgfx_encoder_blit_to_buffer
+ bgfx_encoder_blit_to_buffer.argtypes = [ctypes.POINTER(Encoder), ctypes.c_uint16, ctypes.POINTER(BufferRegion), ctypes.POINTER(TextureRegion)]
+ bgfx_encoder_blit_to_buffer.restype = None
+ global bgfx_encoder_blit_from_buffer
+ bgfx_encoder_blit_from_buffer = lib.bgfx_encoder_blit_from_buffer
+ bgfx_encoder_blit_from_buffer.argtypes = [ctypes.POINTER(Encoder), ctypes.c_uint16, ctypes.POINTER(TextureRegion), ctypes.POINTER(BufferRegion)]
+ bgfx_encoder_blit_from_buffer.restype = None
global bgfx_request_screen_shot
bgfx_request_screen_shot = lib.bgfx_request_screen_shot
bgfx_request_screen_shot.argtypes = [FrameBufferHandle, ctypes.c_char_p]
@@ -1869,5 +1932,17 @@ def _bind(lib):
bgfx_discard.restype = None
global bgfx_blit
bgfx_blit = lib.bgfx_blit
- bgfx_blit.argtypes = [ctypes.c_uint16, TextureHandle, ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, TextureHandle, ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint16]
+ bgfx_blit.argtypes = [ctypes.c_uint16, ctypes.POINTER(TextureRegion), ctypes.POINTER(TextureRegion)]
bgfx_blit.restype = None
+ global bgfx_blit_buffer
+ bgfx_blit_buffer = lib.bgfx_blit_buffer
+ bgfx_blit_buffer.argtypes = [ctypes.c_uint16, ctypes.POINTER(BufferRegion), ctypes.POINTER(BufferRegion)]
+ bgfx_blit_buffer.restype = None
+ global bgfx_blit_to_buffer
+ bgfx_blit_to_buffer = lib.bgfx_blit_to_buffer
+ bgfx_blit_to_buffer.argtypes = [ctypes.c_uint16, ctypes.POINTER(BufferRegion), ctypes.POINTER(TextureRegion)]
+ bgfx_blit_to_buffer.restype = None
+ global bgfx_blit_from_buffer
+ bgfx_blit_from_buffer = lib.bgfx_blit_from_buffer
+ bgfx_blit_from_buffer.argtypes = [ctypes.c_uint16, ctypes.POINTER(TextureRegion), ctypes.POINTER(BufferRegion)]
+ bgfx_blit_from_buffer.restype = None
diff --git a/bindings/py/bgfx.pyi b/bindings/py/bgfx.pyi
index 50b6558b6..750b6b851 100644
--- a/bindings/py/bgfx.pyi
+++ b/bindings/py/bgfx.pyi
@@ -1242,6 +1242,12 @@ class CapsLimits(ctypes.Structure):
maxTransientIbSize: int
# Mimimum uniform buffer size.
minUniformBufferSize: int
+ # Row pitch alignment, in bytes, that buffer to texture blit copies
+ # natively. Any other `BufferRegion::rowPitch` is repacked internally.
+ blitRowPitchAlign: int
+ # Offset alignment, in bytes, that buffer to texture blit copies
+ # natively. Any other `BufferRegion::offset` is repacked internally.
+ blitOffsetAlign: int
# Renderer capabilities.
class Caps(ctypes.Structure):
@@ -1474,6 +1480,60 @@ class InstanceDataBuffer(ctypes.Structure):
# Vertex buffer object handle.
handle: VertexBufferHandle
+# Region of a texture, used as the source or destination of a blit, or as
+# the region handed to `bgfx::read`.
+#
+# Every field defaults to zero, and zero always means "the natural whole".
+# `{ .handle = tex }` therefore addresses all of mip 0.
+class TextureRegion(ctypes.Structure):
+ # Texture handle.
+ handle: TextureHandle
+ # Mip level.
+ mip: int
+ # X position of the region.
+ x: int
+ # Y position of the region.
+ y: int
+ # If texture is 2D this should be 0. If the texture is a cube map
+ # this is the cube face, for a 2D array it is the layer, and for a
+ # 3D texture it is the Z position.
+ z: int
+ # Width of the region. 0 uses the rest of the mip from `x`.
+ width: int
+ # Height of the region. 0 uses the rest of the mip from `y`.
+ height: int
+ # Depth of the region for a 3D texture, or the number of layers or
+ # cube faces otherwise. 0 uses the rest from `z`.
+ depth: int
+
+# Region of a buffer, used as the source or destination of a blit, or as the
+# region handed to `bgfx::read`.
+#
+# `rowPitch` and `slicePitch` describe how texture data is laid out in the
+# buffer, and are ignored when the other end of the blit is also a buffer.
+# Both are in bytes, and 0 selects the tightly packed layout: a row pitch of
+# the region width in blocks multiplied by the block size, and a slice pitch
+# of that row pitch multiplied by the region height in blocks.
+#
+# A pitch the backend cannot copy natively is repacked by bgfx, which costs
+# an extra pass over the data. `Caps::Limits::blitRowPitchAlign` and
+# `blitOffsetAlign` report what the backend copies directly, and
+# `BufferRegion::init` fills in a layout that matches them.
+class BufferRegion(ctypes.Structure):
+ # Buffer handle.
+ handle: BufferHandle
+ # Byte offset into the buffer.
+ offset: int
+ # Number of bytes. Only used when both ends of a blit are
+ # buffers, or by `bgfx::read`. 0 uses the rest of the buffer.
+ size: int
+ # Distance in bytes between the start of two consecutive rows
+ # of blocks. 0 is tightly packed.
+ rowPitch: int
+ # Distance in bytes between the start of two consecutive
+ # slices, layers or cube faces. 0 is tightly packed.
+ slicePitch: int
+
# Texture info.
class TextureInfo(ctypes.Structure):
# Texture format.
@@ -1642,6 +1702,10 @@ class Stats(ctypes.Structure):
numCompute: int
# Number of blit calls submitted.
numBlit: int
+ # Number of buffer to texture blit calls that had to be repacked,
+ # because `BufferRegion::rowPitch` or `offset` didn't match
+ # `Caps::Limits::blitRowPitchAlign` or `blitOffsetAlign`.
+ numBlitRepack: int
# Highest number of draw+compute calls requested in a single
# frame so far (peak demand, before any were dropped). Useful
# to tune `Init::Limits::numDrawCalls`.
@@ -1791,11 +1855,41 @@ class VertexLayoutHandle(ctypes.Structure):
@property
def valid(self) -> bool: ...
+class BufferHandle(ctypes.Structure):
+ idx: int
+ type: int
+
+ @property
+ def valid(self) -> bool: ...
+
# Memory release callback.
ReleaseFn: Any
def load(path: Union[str, bytes]) -> ctypes.CDLL: ...
+# Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+# at zero, which addresses mip 0 of the only slice a 2D texture has.
+def bgfx_texture_region_init(
+ _this: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]],
+ _handle: TextureHandle,
+ _x: int,
+ _y: int,
+ _width: int,
+ _height: int,
+ /,
+) -> None: ...
+
+# Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+# fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+# `handle` is left untouched, so `size` can be used to create the buffer the
+# region will point at.
+def bgfx_buffer_region_init_texture(_this: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], _texture: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], /) -> None: ...
+
+# Fill in the region a blit between two buffers copies. `rowPitch` and
+# `slicePitch` are left at zero, since neither end of such a blit is a
+# texture.
+def bgfx_buffer_region_init_buffer(_this: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], _handle: BufferHandle, _offset: int, _size: int, /) -> None: ...
+
# Init attachment.
def bgfx_attachment_init(
_this: Optional[Union[Attachment, _Pointer[Attachment], ctypes.Array]],
@@ -2004,6 +2098,22 @@ def bgfx_dbg_text_image(
# Create static index buffer.
def bgfx_create_index_buffer(_mem: Optional[Union[Memory, _Pointer[Memory], ctypes.Array]], _flags: int, /) -> IndexBufferHandle: ...
+# Read back contents of buffer.
+#
+# @remarks
+# Read back is asynchronous, and the result is available at the returned frame.
+# A zero `size` reads the rest of the buffer. `rowPitch` and `slicePitch` are
+# unused.
+#
+# Read back is intended for reading GPU written (compute, or draw indirect) buffers
+# back to the CPU. It's not intended to be used in the main render loop, since it
+# stalls the GPU.
+#
+# @attention Buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+# `BGFX_BUFFER_DRAW_INDIRECT` flags.
+#
+def bgfx_read_buffer(_src: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], _data: Any, /) -> int: ...
+
# Set static index buffer debug name.
def bgfx_set_index_buffer_name(_handle: IndexBufferHandle, _name: Optional[bytes], _len: int, /) -> None: ...
@@ -2258,12 +2368,20 @@ def bgfx_clear_texture(_handle: TextureHandle, _mip: int, _numMips: int, _layer:
# Read back texture content.
#
+# @remarks
+# Read back is asynchronous, and the result is available at the returned frame.
+# `TextureRegion::z` selects cube face, 3D slice, or array layer. The region must
+# cover the whole mip.
+#
+# Read back is not intended to be used in the main render loop, since it stalls
+# the GPU.
+#
# @attention Texture must be created with `BGFX_TEXTURE_READ_BACK` flag.
# It's a texture for CPU readback, and can't be a GPU resource
# at the same time. See `examples/30-picking`.
# @attention Availability depends on: `BGFX_CAPS_TEXTURE_READ_BACK`.
#
-def bgfx_read_texture(_handle: TextureHandle, _data: Any, _layer: int, _mip: int, /) -> int: ...
+def bgfx_read_texture(_src: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], _data: Any, /) -> int: ...
# Set texture debug name.
def bgfx_set_texture_name(_handle: TextureHandle, _name: Optional[bytes], _len: int, /) -> None: ...
@@ -2798,29 +2916,74 @@ def bgfx_encoder_dispatch_indirect(
# Discard previously set state for draw or compute call.
def bgfx_encoder_discard(_this: Optional[Union[Encoder, _Pointer[Encoder], ctypes.Array]], _flags: int, /) -> None: ...
-# Blit 2D texture region between two 2D textures.
+# Blit texture region between two textures.
+#
+# @remarks
+# The copy covers the region the two sides have in common: each side gives
+# the origin it starts at, and the size is the smaller of the two extents.
+# A zero `width`, `height` or `depth` extends to the rest of that mip.
+#
+# Blit is performed on GPU, and it is ordered within the view. In views, all
+# draw commands are executed after blit and compute commands.
#
# @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
# @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
#
-def bgfx_encoder_blit(
- _this: Optional[Union[Encoder, _Pointer[Encoder], ctypes.Array]],
- _id: int,
- _dst: TextureHandle,
- _dstMip: int,
- _dstX: int,
- _dstY: int,
- _dstZ: int,
- _src: TextureHandle,
- _srcMip: int,
- _srcX: int,
- _srcY: int,
- _srcZ: int,
- _width: int,
- _height: int,
- _depth: int,
- /,
-) -> None: ...
+def bgfx_encoder_blit(_this: Optional[Union[Encoder, _Pointer[Encoder], ctypes.Array]], _id: int, _dst: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], _src: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], /) -> None: ...
+
+# Blit buffer region between two buffers.
+#
+# @remarks
+# The source region gives the number of bytes copied, and the destination
+# region gives only the offset they land at. A zero `size` copies the rest of
+# the source buffer. `rowPitch` and `slicePitch` are unused.
+#
+# Buffer blit is performed on GPU, and it is ordered within the view, same as
+# texture blit. In views, all draw commands are executed after blit and compute
+# commands.
+#
+# @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+# `BGFX_BUFFER_DRAW_INDIRECT` flags.
+# @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+# `BGFX_BUFFER_DRAW_INDIRECT` flag.
+# @attention Source and destination buffer must be different.
+#
+def bgfx_encoder_blit_buffer(_this: Optional[Union[Encoder, _Pointer[Encoder], ctypes.Array]], _id: int, _dst: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], _src: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], /) -> None: ...
+
+# Blit texture region into buffer.
+#
+# @remarks
+# The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+# `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+# them tightly. `BufferRegion::init` fills in the layout the backend copies
+# fastest, and bgfx repacks internally for any other layout.
+#
+# Blit is performed on GPU, and it is ordered within the view, same as texture
+# blit. In views, all draw commands are executed after blit and compute commands.
+#
+# @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+# `BGFX_BUFFER_DRAW_INDIRECT` flag.
+# @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+#
+def bgfx_encoder_blit_to_buffer(_this: Optional[Union[Encoder, _Pointer[Encoder], ctypes.Array]], _id: int, _dst: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], _src: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], /) -> None: ...
+
+# Blit buffer contents into texture region.
+#
+# @remarks
+# The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+# `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+# them tightly packed. `BufferRegion::init` fills in the layout the backend
+# copies fastest, and bgfx repacks internally for any other layout.
+#
+# Blit is performed on GPU, and it is ordered within the view, same as texture
+# blit. In views, all draw commands are executed after blit and compute commands.
+#
+# @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+# `BGFX_BUFFER_DRAW_INDIRECT` flags.
+# @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+# @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+#
+def bgfx_encoder_blit_from_buffer(_this: Optional[Union[Encoder, _Pointer[Encoder], ctypes.Array]], _id: int, _dst: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], _src: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], /) -> None: ...
# Request screen shot of window back buffer.
#
@@ -3142,25 +3305,71 @@ def bgfx_dispatch_indirect(
# Discard previously set state for draw or compute call.
def bgfx_discard(_flags: int, /) -> None: ...
-# Blit 2D texture region between two 2D textures.
+# Blit texture region between two textures.
+#
+# @remarks
+# The copy covers the region the two sides have in common: each side gives
+# the origin it starts at, and the size is the smaller of the two extents.
+# A zero `width`, `height` or `depth` extends to the rest of that mip.
+#
+# Blit is performed on GPU, and it is ordered within the view. In views, all
+# draw commands are executed after blit and compute commands.
#
# @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
# @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
#
-def bgfx_blit(
- _id: int,
- _dst: TextureHandle,
- _dstMip: int,
- _dstX: int,
- _dstY: int,
- _dstZ: int,
- _src: TextureHandle,
- _srcMip: int,
- _srcX: int,
- _srcY: int,
- _srcZ: int,
- _width: int,
- _height: int,
- _depth: int,
- /,
-) -> None: ...
+def bgfx_blit(_id: int, _dst: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], _src: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], /) -> None: ...
+
+# Blit buffer region between two buffers.
+#
+# @remarks
+# The source region gives the number of bytes copied, and the destination
+# region gives only the offset they land at. A zero `size` copies the rest of
+# the source buffer. `rowPitch` and `slicePitch` are unused.
+#
+# Buffer blit is performed on GPU, and it is ordered within the view, same as
+# texture blit. In views, all draw commands are executed after blit and compute
+# commands.
+#
+# @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+# `BGFX_BUFFER_DRAW_INDIRECT` flags.
+# @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+# `BGFX_BUFFER_DRAW_INDIRECT` flag.
+# @attention Source and destination buffer must be different.
+#
+def bgfx_blit_buffer(_id: int, _dst: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], _src: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], /) -> None: ...
+
+# Blit texture region into buffer.
+#
+# @remarks
+# The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+# `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+# them tightly. `BufferRegion::init` fills in the layout the backend copies
+# fastest, and bgfx repacks internally for any other layout.
+#
+# Blit is performed on GPU, and it is ordered within the view, same as texture
+# blit. In views, all draw commands are executed after blit and compute commands.
+#
+# @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+# `BGFX_BUFFER_DRAW_INDIRECT` flag.
+# @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+#
+def bgfx_blit_to_buffer(_id: int, _dst: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], _src: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], /) -> None: ...
+
+# Blit buffer contents into texture region.
+#
+# @remarks
+# The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+# `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+# them tightly packed. `BufferRegion::init` fills in the layout the backend
+# copies fastest, and bgfx repacks internally for any other layout.
+#
+# Blit is performed on GPU, and it is ordered within the view, same as texture
+# blit. In views, all draw commands are executed after blit and compute commands.
+#
+# @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+# `BGFX_BUFFER_DRAW_INDIRECT` flags.
+# @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+# @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+#
+def bgfx_blit_from_buffer(_id: int, _dst: Optional[Union[TextureRegion, _Pointer[TextureRegion], ctypes.Array]], _src: Optional[Union[BufferRegion, _Pointer[BufferRegion], ctypes.Array]], /) -> None: ...
diff --git a/bindings/zig/bgfx.zig b/bindings/zig/bgfx.zig
index c3b23f07f..fa268ec90 100644
--- a/bindings/zig/bgfx.zig
+++ b/bindings/zig/bgfx.zig
@@ -1607,6 +1607,8 @@ pub const Caps = extern struct {
maxTransientVbSize: u32,
maxTransientIbSize: u32,
minUniformBufferSize: u32,
+ blitRowPitchAlign: u32,
+ blitOffsetAlign: u32,
};
rendererType: RendererType,
@@ -1705,6 +1707,52 @@ pub const Init = extern struct {
handle: VertexBufferHandle,
};
+ pub const TextureRegion = extern struct {
+ handle: TextureHandle,
+ mip: u8,
+ x: u16,
+ y: u16,
+ z: u16,
+ width: u16,
+ height: u16,
+ depth: u16,
+ /// Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+ /// at zero, which addresses mip 0 of the only slice a 2D texture has.
+ /// Texture handle.
+ /// X position of the region.
+ /// Y position of the region.
+ /// Width of the region. 0 uses the rest of the mip from `_x`.
+ /// Height of the region. 0 uses the rest of the mip from `_y`.
+ pub inline fn init(self: *TextureRegion, _handle: TextureHandle, _x: u16, _y: u16, _width: u16, _height: u16) void {
+ return bgfx_texture_region_init(self, _handle, _x, _y, _width, _height);
+ }
+ };
+
+ pub const BufferRegion = extern struct {
+ handle: BufferHandle,
+ offset: u32,
+ size: u32,
+ rowPitch: u32,
+ slicePitch: u32,
+ /// Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+ /// fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+ /// `handle` is left untouched, so `size` can be used to create the buffer the
+ /// region will point at.
+ /// Texture region the buffer is copied to or from.
+ pub inline fn initTexture(self: *BufferRegion, _texture: [*c]const TextureRegion) void {
+ return bgfx_buffer_region_init_texture(self, _texture);
+ }
+ /// Fill in the region a blit between two buffers copies. `rowPitch` and
+ /// `slicePitch` are left at zero, since neither end of such a blit is a
+ /// texture.
+ /// Buffer handle.
+ /// Byte offset into the buffer.
+ /// Number of bytes. 0 uses the rest of the buffer.
+ pub inline fn initBuffer(self: *BufferRegion, _handle: BufferHandle, _offset: u32, _size: u32) void {
+ return bgfx_buffer_region_init_buffer(self, _handle, _offset, _size);
+ }
+ };
+
pub const TextureInfo = extern struct {
format: TextureFormat,
storageSize: u32,
@@ -1798,6 +1846,7 @@ pub const Init = extern struct {
numDraw: u32,
numCompute: u32,
numBlit: u32,
+ numBlitRepack: u32,
numDrawCallsPeak: u32,
maxGpuLatency: u32,
gpuFrameNum: u32,
@@ -2233,27 +2282,90 @@ pub const Init = extern struct {
pub inline fn discard(self: ?*Encoder, _flags: u8) void {
return bgfx_encoder_discard(self, _flags);
}
- /// Blit 2D texture region between two 2D textures.
+ /// Blit texture region between two textures.
+ ///
+ /// @remarks
+ /// The copy covers the region the two sides have in common: each side gives
+ /// the origin it starts at, and the size is the smaller of the two extents.
+ /// A zero `width`, `height` or `depth` extends to the rest of that mip.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view. In views, all
+ /// draw commands are executed after blit and compute commands.
///
/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
///
/// View id.
- /// Destination texture handle.
- /// Destination texture mip level.
- /// Destination texture X position.
- /// Destination texture Y position.
- /// If texture is 2D this argument should be 0. If destination texture is cube this argument represents destination texture cube face. For 3D texture this argument represents destination texture Z position.
- /// Source texture handle.
- /// Source texture mip level.
- /// Source texture X position.
- /// Source texture Y position.
- /// If texture is 2D this argument should be 0. If source texture is cube this argument represents source texture cube face. For 3D texture this argument represents source texture Z position.
- /// Width of region.
- /// Height of region.
- /// If texture is 3D this argument represents depth of region, otherwise it's unused.
- pub inline fn blit(self: ?*Encoder, _id: ViewId, _dst: TextureHandle, _dstMip: u8, _dstX: u16, _dstY: u16, _dstZ: u16, _src: TextureHandle, _srcMip: u8, _srcX: u16, _srcY: u16, _srcZ: u16, _width: u16, _height: u16, _depth: u16) void {
- return bgfx_encoder_blit(self, _id, _dst, _dstMip, _dstX, _dstY, _dstZ, _src, _srcMip, _srcX, _srcY, _srcZ, _width, _height, _depth);
+ /// Destination texture region.
+ /// Source texture region.
+ pub inline fn blit(self: ?*Encoder, _id: ViewId, _dst: [*c]const TextureRegion, _src: [*c]const TextureRegion) void {
+ return bgfx_encoder_blit(self, _id, _dst, _src);
+ }
+ /// Blit buffer region between two buffers.
+ ///
+ /// @remarks
+ /// The source region gives the number of bytes copied, and the destination
+ /// region gives only the offset they land at. A zero `size` copies the rest of
+ /// the source buffer. `rowPitch` and `slicePitch` are unused.
+ ///
+ /// Buffer blit is performed on GPU, and it is ordered within the view, same as
+ /// texture blit. In views, all draw commands are executed after blit and compute
+ /// commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Source and destination buffer must be different.
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source buffer region.
+ pub inline fn blitBuffer(self: ?*Encoder, _id: ViewId, _dst: [*c]const BufferRegion, _src: [*c]const BufferRegion) void {
+ return bgfx_encoder_blit_buffer(self, _id, _dst, _src);
+ }
+ /// Blit texture region into buffer.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ /// them tightly. `BufferRegion::init` fills in the layout the backend copies
+ /// fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ /// View id.
+ /// Destination buffer region.
+ /// Source texture region.
+ pub inline fn blitToBuffer(self: ?*Encoder, _id: ViewId, _dst: [*c]const BufferRegion, _src: [*c]const TextureRegion) void {
+ return bgfx_encoder_blit_to_buffer(self, _id, _dst, _src);
+ }
+ /// Blit buffer contents into texture region.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ /// them tightly packed. `BufferRegion::init` fills in the layout the backend
+ /// copies fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ /// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ /// View id.
+ /// Destination texture region.
+ /// Source buffer region.
+ pub inline fn blitFromBuffer(self: ?*Encoder, _id: ViewId, _dst: [*c]const TextureRegion, _src: [*c]const BufferRegion) void {
+ return bgfx_encoder_blit_from_buffer(self, _id, _dst, _src);
}
};
@@ -2305,6 +2417,35 @@ pub const VertexLayoutHandle = extern struct {
idx: c_ushort,
};
+pub const BufferHandle = extern struct {
+ idx: c_ushort,
+ type: c_ushort,
+};
+
+
+/// Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+/// at zero, which addresses mip 0 of the only slice a 2D texture has.
+/// Texture handle.
+/// X position of the region.
+/// Y position of the region.
+/// Width of the region. 0 uses the rest of the mip from `_x`.
+/// Height of the region. 0 uses the rest of the mip from `_y`.
+extern fn bgfx_texture_region_init(self: [*c]TextureRegion, _handle: TextureHandle, _x: u16, _y: u16, _width: u16, _height: u16) void;
+
+/// Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+/// fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+/// `handle` is left untouched, so `size` can be used to create the buffer the
+/// region will point at.
+/// Texture region the buffer is copied to or from.
+extern fn bgfx_buffer_region_init_texture(self: [*c]BufferRegion, _texture: [*c]const TextureRegion) void;
+
+/// Fill in the region a blit between two buffers copies. `rowPitch` and
+/// `slicePitch` are left at zero, since neither end of such a blit is a
+/// texture.
+/// Buffer handle.
+/// Byte offset into the buffer.
+/// Number of bytes. 0 uses the rest of the buffer.
+extern fn bgfx_buffer_region_init_buffer(self: [*c]BufferRegion, _handle: BufferHandle, _offset: u32, _size: u32) void;
/// Init attachment.
/// Render target texture handle.
@@ -2599,6 +2740,27 @@ pub inline fn createIndexBuffer(_mem: [*c]const Memory, _flags: u16) IndexBuffer
}
extern fn bgfx_create_index_buffer(_mem: [*c]const Memory, _flags: u16) IndexBufferHandle;
+/// Read back contents of buffer.
+///
+/// @remarks
+/// Read back is asynchronous, and the result is available at the returned frame.
+/// A zero `size` reads the rest of the buffer. `rowPitch` and `slicePitch` are
+/// unused.
+///
+/// Read back is intended for reading GPU written (compute, or draw indirect) buffers
+/// back to the CPU. It's not intended to be used in the main render loop, since it
+/// stalls the GPU.
+///
+/// @attention Buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+/// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+///
+/// Source buffer region.
+/// Destination buffer.
+pub inline fn readBuffer(_src: [*c]const BufferRegion, _data: ?*anyopaque) u32 {
+ return bgfx_read_buffer(_src, _data);
+}
+extern fn bgfx_read_buffer(_src: [*c]const BufferRegion, _data: ?*anyopaque) u32;
+
/// Set static index buffer debug name.
/// Static index buffer handle.
/// Static index buffer name.
@@ -3050,19 +3212,25 @@ extern fn bgfx_clear_texture(_handle: TextureHandle, _mip: u8, _numMips: u8, _la
/// Read back texture content.
///
+/// @remarks
+/// Read back is asynchronous, and the result is available at the returned frame.
+/// `TextureRegion::z` selects cube face, 3D slice, or array layer. The region must
+/// cover the whole mip.
+///
+/// Read back is not intended to be used in the main render loop, since it stalls
+/// the GPU.
+///
/// @attention Texture must be created with `BGFX_TEXTURE_READ_BACK` flag.
/// It's a texture for CPU readback, and can't be a GPU resource
/// at the same time. See `examples/30-picking`.
/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_READ_BACK`.
///
-/// Texture handle.
+/// Source texture region.
/// Destination buffer.
-/// Texture layer.
-/// Mip level.
-pub inline fn readTexture(_handle: TextureHandle, _data: ?*anyopaque, _layer: u16, _mip: u8) u32 {
- return bgfx_read_texture(_handle, _data, _layer, _mip);
+pub inline fn readTexture(_src: [*c]const TextureRegion, _data: ?*anyopaque) u32 {
+ return bgfx_read_texture(_src, _data);
}
-extern fn bgfx_read_texture(_handle: TextureHandle, _data: ?*anyopaque, _layer: u16, _mip: u8) u32;
+extern fn bgfx_read_texture(_src: [*c]const TextureRegion, _data: ?*anyopaque) u32;
/// Set texture debug name.
/// Texture handle.
@@ -3846,26 +4014,86 @@ extern fn bgfx_encoder_dispatch_indirect(self: ?*Encoder, _id: ViewId, _program:
/// Discard or preserve states. See `BGFX_DISCARD_*`.
extern fn bgfx_encoder_discard(self: ?*Encoder, _flags: u8) void;
-/// Blit 2D texture region between two 2D textures.
+/// Blit texture region between two textures.
+///
+/// @remarks
+/// The copy covers the region the two sides have in common: each side gives
+/// the origin it starts at, and the size is the smaller of the two extents.
+/// A zero `width`, `height` or `depth` extends to the rest of that mip.
+///
+/// Blit is performed on GPU, and it is ordered within the view. In views, all
+/// draw commands are executed after blit and compute commands.
///
/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
///
/// View id.
-/// Destination texture handle.
-/// Destination texture mip level.
-/// Destination texture X position.
-/// Destination texture Y position.
-/// If texture is 2D this argument should be 0. If destination texture is cube this argument represents destination texture cube face. For 3D texture this argument represents destination texture Z position.
-/// Source texture handle.
-/// Source texture mip level.
-/// Source texture X position.
-/// Source texture Y position.
-/// If texture is 2D this argument should be 0. If source texture is cube this argument represents source texture cube face. For 3D texture this argument represents source texture Z position.
-/// Width of region.
-/// Height of region.
-/// If texture is 3D this argument represents depth of region, otherwise it's unused.
-extern fn bgfx_encoder_blit(self: ?*Encoder, _id: ViewId, _dst: TextureHandle, _dstMip: u8, _dstX: u16, _dstY: u16, _dstZ: u16, _src: TextureHandle, _srcMip: u8, _srcX: u16, _srcY: u16, _srcZ: u16, _width: u16, _height: u16, _depth: u16) void;
+/// Destination texture region.
+/// Source texture region.
+extern fn bgfx_encoder_blit(self: ?*Encoder, _id: ViewId, _dst: [*c]const TextureRegion, _src: [*c]const TextureRegion) void;
+
+/// Blit buffer region between two buffers.
+///
+/// @remarks
+/// The source region gives the number of bytes copied, and the destination
+/// region gives only the offset they land at. A zero `size` copies the rest of
+/// the source buffer. `rowPitch` and `slicePitch` are unused.
+///
+/// Buffer blit is performed on GPU, and it is ordered within the view, same as
+/// texture blit. In views, all draw commands are executed after blit and compute
+/// commands.
+///
+/// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+/// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+/// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+/// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+/// @attention Source and destination buffer must be different.
+///
+/// View id.
+/// Destination buffer region.
+/// Source buffer region.
+extern fn bgfx_encoder_blit_buffer(self: ?*Encoder, _id: ViewId, _dst: [*c]const BufferRegion, _src: [*c]const BufferRegion) void;
+
+/// Blit texture region into buffer.
+///
+/// @remarks
+/// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+/// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+/// them tightly. `BufferRegion::init` fills in the layout the backend copies
+/// fastest, and bgfx repacks internally for any other layout.
+///
+/// Blit is performed on GPU, and it is ordered within the view, same as texture
+/// blit. In views, all draw commands are executed after blit and compute commands.
+///
+/// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+/// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+///
+/// View id.
+/// Destination buffer region.
+/// Source texture region.
+extern fn bgfx_encoder_blit_to_buffer(self: ?*Encoder, _id: ViewId, _dst: [*c]const BufferRegion, _src: [*c]const TextureRegion) void;
+
+/// Blit buffer contents into texture region.
+///
+/// @remarks
+/// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+/// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+/// them tightly packed. `BufferRegion::init` fills in the layout the backend
+/// copies fastest, and bgfx repacks internally for any other layout.
+///
+/// Blit is performed on GPU, and it is ordered within the view, same as texture
+/// blit. In views, all draw commands are executed after blit and compute commands.
+///
+/// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+/// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+///
+/// View id.
+/// Destination texture region.
+/// Source buffer region.
+extern fn bgfx_encoder_blit_from_buffer(self: ?*Encoder, _id: ViewId, _dst: [*c]const TextureRegion, _src: [*c]const BufferRegion) void;
/// Request screen shot of window back buffer.
///
@@ -4425,28 +4653,97 @@ pub inline fn discard(_flags: u8) void {
}
extern fn bgfx_discard(_flags: u8) void;
-/// Blit 2D texture region between two 2D textures.
+/// Blit texture region between two textures.
+///
+/// @remarks
+/// The copy covers the region the two sides have in common: each side gives
+/// the origin it starts at, and the size is the smaller of the two extents.
+/// A zero `width`, `height` or `depth` extends to the rest of that mip.
+///
+/// Blit is performed on GPU, and it is ordered within the view. In views, all
+/// draw commands are executed after blit and compute commands.
///
/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
///
/// View id.
-/// Destination texture handle.
-/// Destination texture mip level.
-/// Destination texture X position.
-/// Destination texture Y position.
-/// If texture is 2D this argument should be 0. If destination texture is cube this argument represents destination texture cube face. For 3D texture this argument represents destination texture Z position.
-/// Source texture handle.
-/// Source texture mip level.
-/// Source texture X position.
-/// Source texture Y position.
-/// If texture is 2D this argument should be 0. If source texture is cube this argument represents source texture cube face. For 3D texture this argument represents source texture Z position.
-/// Width of region.
-/// Height of region.
-/// If texture is 3D this argument represents depth of region, otherwise it's unused.
-pub inline fn blit(_id: ViewId, _dst: TextureHandle, _dstMip: u8, _dstX: u16, _dstY: u16, _dstZ: u16, _src: TextureHandle, _srcMip: u8, _srcX: u16, _srcY: u16, _srcZ: u16, _width: u16, _height: u16, _depth: u16) void {
- return bgfx_blit(_id, _dst, _dstMip, _dstX, _dstY, _dstZ, _src, _srcMip, _srcX, _srcY, _srcZ, _width, _height, _depth);
+/// Destination texture region.
+/// Source texture region.
+pub inline fn blit(_id: ViewId, _dst: [*c]const TextureRegion, _src: [*c]const TextureRegion) void {
+ return bgfx_blit(_id, _dst, _src);
}
-extern fn bgfx_blit(_id: ViewId, _dst: TextureHandle, _dstMip: u8, _dstX: u16, _dstY: u16, _dstZ: u16, _src: TextureHandle, _srcMip: u8, _srcX: u16, _srcY: u16, _srcZ: u16, _width: u16, _height: u16, _depth: u16) void;
+extern fn bgfx_blit(_id: ViewId, _dst: [*c]const TextureRegion, _src: [*c]const TextureRegion) void;
+
+/// Blit buffer region between two buffers.
+///
+/// @remarks
+/// The source region gives the number of bytes copied, and the destination
+/// region gives only the offset they land at. A zero `size` copies the rest of
+/// the source buffer. `rowPitch` and `slicePitch` are unused.
+///
+/// Buffer blit is performed on GPU, and it is ordered within the view, same as
+/// texture blit. In views, all draw commands are executed after blit and compute
+/// commands.
+///
+/// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+/// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+/// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+/// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+/// @attention Source and destination buffer must be different.
+///
+/// View id.
+/// Destination buffer region.
+/// Source buffer region.
+pub inline fn blitBuffer(_id: ViewId, _dst: [*c]const BufferRegion, _src: [*c]const BufferRegion) void {
+ return bgfx_blit_buffer(_id, _dst, _src);
+}
+extern fn bgfx_blit_buffer(_id: ViewId, _dst: [*c]const BufferRegion, _src: [*c]const BufferRegion) void;
+
+/// Blit texture region into buffer.
+///
+/// @remarks
+/// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+/// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+/// them tightly. `BufferRegion::init` fills in the layout the backend copies
+/// fastest, and bgfx repacks internally for any other layout.
+///
+/// Blit is performed on GPU, and it is ordered within the view, same as texture
+/// blit. In views, all draw commands are executed after blit and compute commands.
+///
+/// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+/// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+///
+/// View id.
+/// Destination buffer region.
+/// Source texture region.
+pub inline fn blitToBuffer(_id: ViewId, _dst: [*c]const BufferRegion, _src: [*c]const TextureRegion) void {
+ return bgfx_blit_to_buffer(_id, _dst, _src);
+}
+extern fn bgfx_blit_to_buffer(_id: ViewId, _dst: [*c]const BufferRegion, _src: [*c]const TextureRegion) void;
+
+/// Blit buffer contents into texture region.
+///
+/// @remarks
+/// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+/// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+/// them tightly packed. `BufferRegion::init` fills in the layout the backend
+/// copies fastest, and bgfx repacks internally for any other layout.
+///
+/// Blit is performed on GPU, and it is ordered within the view, same as texture
+/// blit. In views, all draw commands are executed after blit and compute commands.
+///
+/// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+/// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+/// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+///
+/// View id.
+/// Destination texture region.
+/// Source buffer region.
+pub inline fn blitFromBuffer(_id: ViewId, _dst: [*c]const TextureRegion, _src: [*c]const BufferRegion) void {
+ return bgfx_blit_from_buffer(_id, _dst, _src);
+}
+extern fn bgfx_blit_from_buffer(_id: ViewId, _dst: [*c]const TextureRegion, _src: [*c]const BufferRegion) void;
diff --git a/docs/bgfx.rst b/docs/bgfx.rst
index c450d8551..232f64dff 100644
--- a/docs/bgfx.rst
+++ b/docs/bgfx.rst
@@ -434,6 +434,9 @@ Set vertex, index, and instance data buffers for draw calls.
.. doxygenstruct:: bgfx::InstanceDataBuffer
:members:
+.. doxygenstruct:: bgfx::BufferRegion
+ :members:
+
.. doxygenfunction:: bgfx::setIndexBuffer(IndexBufferHandle _handle)
.. doxygenfunction:: bgfx::setIndexBuffer(IndexBufferHandle _handle, uint32_t _firstIndex, uint32_t _numIndices)
.. doxygenfunction:: bgfx::setIndexBuffer(DynamicIndexBufferHandle _handle)
@@ -490,6 +493,7 @@ Bind buffers to compute stages.
.. doxygenstruct:: bgfx::Access
:members:
+.. doxygenfunction:: bgfx::read(const BufferRegion & _src, void* _data)
.. doxygenfunction:: bgfx::setBuffer(uint8_t _stage, IndexBufferHandle _handle, Access::Enum _access)
.. doxygenfunction:: bgfx::setBuffer(uint8_t _stage, VertexBufferHandle _handle, Access::Enum _access)
.. doxygenfunction:: bgfx::setBuffer(uint8_t _stage, DynamicIndexBufferHandle _handle, Access::Enum _access)
@@ -517,8 +521,10 @@ Blit
In Views, all draw commands are executed **after** blit and compute commands.
-.. doxygenfunction:: bgfx::blit(ViewId _id, TextureHandle _dst, uint16_t _dstX, uint16_t _dstY, TextureHandle _src, uint16_t _srcX = 0, uint16_t _srcY = 0, uint16_t _width = UINT16_MAX, uint16_t _height = UINT16_MAX)
-.. doxygenfunction:: bgfx::blit(ViewId _id, TextureHandle _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, TextureHandle _src, uint8_t _srcMip = 0, uint16_t _srcX = 0, uint16_t _srcY = 0, uint16_t _srcZ = 0, uint16_t _width = UINT16_MAX, uint16_t _height = UINT16_MAX, uint16_t _depth = UINT16_MAX)
+.. doxygenfunction:: bgfx::blit(ViewId _id, const TextureRegion & _dst, const TextureRegion & _src)
+.. doxygenfunction:: bgfx::blit(ViewId _id, const BufferRegion & _dst, const BufferRegion & _src)
+.. doxygenfunction:: bgfx::blit(ViewId _id, const BufferRegion & _dst, const TextureRegion & _src)
+.. doxygenfunction:: bgfx::blit(ViewId _id, const TextureRegion & _dst, const BufferRegion & _src)
Resources
---------
@@ -608,6 +614,9 @@ Textures
.. doxygenstruct:: bgfx::TextureFormat
:members:
+.. doxygenstruct:: bgfx::TextureRegion
+ :members:
+
.. doxygenstruct:: bgfx::TextureInfo
:members:
@@ -632,7 +641,7 @@ Textures
.. doxygenfunction:: bgfx::updateTexture3D
.. doxygenfunction:: bgfx::updateTextureCube
.. doxygenfunction:: bgfx::clear
-.. doxygenfunction:: bgfx::readTexture
+.. doxygenfunction:: bgfx::read(const TextureRegion & _src, void* _data)
.. doxygenfunction:: bgfx::getDirectAccessPtr
.. doxygenfunction:: bgfx::destroy(TextureHandle _handle)
diff --git a/examples/08-update/update.cpp b/examples/08-update/update.cpp
index 67344b555..6952bede2 100644
--- a/examples/08-update/update.cpp
+++ b/examples/08-update/update.cpp
@@ -657,18 +657,8 @@ public:
{
bgfx::blit(
0
- , m_textureCube[1]
- , 0
- , rect.m_x
- , rect.m_y
- , face.m_side
- , m_textureCube[0]
- , 0
- , rect.m_x
- , rect.m_y
- , face.m_side
- , rect.m_width
- , rect.m_height
+ , { .handle = m_textureCube[1], .x = rect.m_x, .y = rect.m_y, .z = face.m_side }
+ , { .handle = m_textureCube[0], .x = rect.m_x, .y = rect.m_y, .z = face.m_side, .width = rect.m_width, .height = rect.m_height }
);
}
@@ -690,18 +680,8 @@ public:
{
bgfx::blit(
0
- , m_textureCube[1]
- , 0
- , rect.m_x
- , rect.m_y
- , face.m_side
- , m_textureCube[0]
- , 0
- , rect.m_x
- , rect.m_y
- , face.m_side
- , rect.m_width
- , rect.m_height
+ , { .handle = m_textureCube[1], .x = rect.m_x, .y = rect.m_y, .z = face.m_side }
+ , { .handle = m_textureCube[0], .x = rect.m_x, .y = rect.m_y, .z = face.m_side, .width = rect.m_width, .height = rect.m_height }
);
}
@@ -1050,17 +1030,17 @@ public:
if (m_blitSupported)
{
- bgfx::blit(1, m_blitTestA, 0, 0, m_blitTestB, 0, 0);
- bgfx::blit(1, m_blitTestC, 0, 0, m_blitTestA, 0, 0);
+ bgfx::blit(1, { .handle = m_blitTestA }, { .handle = m_blitTestB });
+ bgfx::blit(1, { .handle = m_blitTestC }, { .handle = m_blitTestA });
- bgfx::blit(1, m_blitTestA, 0, 0, m_blitTestB, 0, 0);
- bgfx::blit(1, m_blitTestB, 0, 0, m_blitTestC, 0, 0);
+ bgfx::blit(1, { .handle = m_blitTestA }, { .handle = m_blitTestB });
+ bgfx::blit(1, { .handle = m_blitTestB }, { .handle = m_blitTestC });
- bgfx::blit(1, m_blitTestA, 0, 0, m_blitTestB, 0, 0);
- bgfx::blit(1, m_blitTestB, 0, 0, m_blitTestA, 0, 0);
+ bgfx::blit(1, { .handle = m_blitTestA }, { .handle = m_blitTestB });
+ bgfx::blit(1, { .handle = m_blitTestB }, { .handle = m_blitTestA });
- bgfx::blit(1, m_blitTestB, 0, 0, m_blitTestA, 0, 0);
- bgfx::blit(1, m_blitTestC, 0, 0, m_blitTestB, 0, 0);
+ bgfx::blit(1, { .handle = m_blitTestB }, { .handle = m_blitTestA });
+ bgfx::blit(1, { .handle = m_blitTestC }, { .handle = m_blitTestB });
}
imguiEndFrame();
diff --git a/examples/09-hdr/hdr.cpp b/examples/09-hdr/hdr.cpp
index 688805f6e..58d483536 100644
--- a/examples/09-hdr/hdr.cpp
+++ b/examples/09-hdr/hdr.cpp
@@ -600,8 +600,8 @@ public:
if (bgfx::isValid(m_rb) )
{
- bgfx::blit(hdrHBlurTonemap, m_rb, 0, 0, bgfx::getTexture(m_lum[4]) );
- bgfx::readTexture(m_rb, &m_lumBgra8);
+ bgfx::blit(hdrHBlurTonemap, { .handle = m_rb }, { .handle = bgfx::getTexture(m_lum[4]) });
+ bgfx::read({ .handle = m_rb }, &m_lumBgra8);
}
// Advance to next frame. Rendering thread will be kicked to
diff --git a/examples/30-picking/picking.cpp b/examples/30-picking/picking.cpp
index 48f52dff3..085b81d59 100644
--- a/examples/30-picking/picking.cpp
+++ b/examples/30-picking/picking.cpp
@@ -389,8 +389,8 @@ public:
)
{
// Blit and read
- bgfx::blit(RENDER_PASS_BLIT, m_blitTex, 0, 0, m_pickingRT);
- m_reading = bgfx::readTexture(m_blitTex, m_blitData);
+ bgfx::blit(RENDER_PASS_BLIT, { .handle = m_blitTex }, { .handle = m_pickingRT });
+ m_reading = bgfx::read({ .handle = m_blitTex }, m_blitData);
}
}
diff --git a/examples/40-svt/vt.cpp b/examples/40-svt/vt.cpp
index 54a62cda3..ceea2bc4e 100644
--- a/examples/40-svt/vt.cpp
+++ b/examples/40-svt/vt.cpp
@@ -489,7 +489,11 @@ void PageTable::update(bgfx::ViewId blitViewId)
auto stagingTexture = m_stagingTextures[i];
auto size = uint16_t(m_info->GetPageTableSize() >> i);
bgfx::updateTexture2D(stagingTexture, 0, 0, 0, 0, size, size, bgfx::copy(&m_images[i]->m_data[0], size * size * s_channelCount));
- bgfx::blit(blitViewId, m_texture, uint8_t(i), 0, 0, 0, stagingTexture, 0, 0, 0, 0, size, size);
+ bgfx::blit(
+ blitViewId
+ , { .handle = m_texture, .mip = uint8_t(i) }
+ , { .handle = stagingTexture, .width = size, .height = size }
+ );
}
}
@@ -748,7 +752,11 @@ void TextureAtlas::uploadPage(Point pt, uint8_t* data, bgfx::ViewId blitViewId)
// Copy the texture part to the actual atlas texture
auto xpos = uint16_t(pt.m_x * pagesize);
auto ypos = uint16_t(pt.m_y * pagesize);
- bgfx::blit(blitViewId, m_texture, 0, xpos, ypos, 0, writer, 0, 0, 0, 0, pagesize, pagesize);
+ bgfx::blit(
+ blitViewId
+ , { .handle = m_texture, .x = xpos, .y = ypos }
+ , { .handle = writer, .width = pagesize, .height = pagesize }
+ );
}
bgfx::TextureHandle TextureAtlas::getTexture()
@@ -799,7 +807,7 @@ void FeedbackBuffer::copy(bgfx::ViewId viewId)
{
m_lastStagingTexture = m_stagingPool.getTexture();
// Copy feedback buffer render target to staging texture
- bgfx::blit(viewId, m_lastStagingTexture, 0, 0, bgfx::getTexture(m_feedbackFrameBuffer));
+ bgfx::blit(viewId, { .handle = m_lastStagingTexture }, { .handle = bgfx::getTexture(m_feedbackFrameBuffer) });
m_stagingPool.next();
}
@@ -812,7 +820,7 @@ void FeedbackBuffer::download()
}
// Read the texture
- bgfx::readTexture(m_lastStagingTexture, &m_downloadBuffer[0]);
+ bgfx::read({ .handle = m_lastStagingTexture }, &m_downloadBuffer[0]);
// Loop through pixels and check if anything was written
auto data = &m_downloadBuffer[0];
auto colors = (Color*)data;
diff --git a/examples/50-headless/headless.cpp b/examples/50-headless/headless.cpp
index 8c17afb8c..1733e61b0 100644
--- a/examples/50-headless/headless.cpp
+++ b/examples/50-headless/headless.cpp
@@ -197,7 +197,7 @@ int _main_(int _argc, char** _argv)
}
}
- bgfx::blit(1, rb, 0, 0, bgfx::getTexture(fbh) );
+ bgfx::blit(1, { .handle = rb }, { .handle = bgfx::getTexture(fbh) });
currentFrame = bgfx::frame();
}
@@ -213,7 +213,7 @@ int _main_(int _argc, char** _argv)
uint8_t* data = (uint8_t*)bx::alloc(&allocator, kWidth*kHeight*4);
- uint32_t expectedFrame = bgfx::readTexture(rb, data);
+ uint32_t expectedFrame = bgfx::read({ .handle = rb }, data);
while (currentFrame < expectedFrame) // Make sure read texture is complete.
{
diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h
index 60198b888..b5b4ded36 100644
--- a/include/bgfx/bgfx.h
+++ b/include/bgfx/bgfx.h
@@ -532,6 +532,61 @@ namespace bgfx
BGFX_HANDLE(VertexBufferHandle)
BGFX_HANDLE(VertexLayoutHandle)
+ struct BufferHandle
+ {
+ enum Enum
+ {
+ DynamicIndexBuffer,
+ DynamicVertexBuffer,
+ IndexBuffer,
+ IndirectBuffer,
+ VertexBuffer,
+
+ Count
+ };
+
+ BufferHandle()
+ : idx(kInvalidHandle)
+ , type(Count)
+ {
+ }
+
+ BufferHandle(DynamicIndexBufferHandle _handle)
+ : idx(_handle.idx)
+ , type(DynamicIndexBuffer)
+ {
+ }
+
+ BufferHandle(DynamicVertexBufferHandle _handle)
+ : idx(_handle.idx)
+ , type(DynamicVertexBuffer)
+ {
+ }
+
+ BufferHandle(IndexBufferHandle _handle)
+ : idx(_handle.idx)
+ , type(IndexBuffer)
+ {
+ }
+
+ BufferHandle(IndirectBufferHandle _handle)
+ : idx(_handle.idx)
+ , type(IndirectBuffer)
+ {
+ }
+
+ BufferHandle(VertexBufferHandle _handle)
+ : idx(_handle.idx)
+ , type(VertexBuffer)
+ {
+ }
+
+ uint16_t idx;
+ uint16_t type;
+ };
+
+ inline bool isValid(BufferHandle _handle) { return bgfx::kInvalidHandle != _handle.idx; }
+
/// Renderer capabilities.
///
/// @attention C99's equivalent binding is `bgfx_caps_t`.
@@ -573,6 +628,10 @@ namespace bgfx
uint32_t maxTransientVbSize; //!< Maximum transient vertex buffer size.
uint32_t maxTransientIbSize; //!< Maximum transient index buffer size.
uint32_t minUniformBufferSize; //!< Mimimum uniform buffer size.
+ uint32_t blitRowPitchAlign; //!< Row pitch alignment, in bytes, that buffer to texture blit copies
+ /// natively. Any other `BufferRegion::rowPitch` is repacked internally.
+ uint32_t blitOffsetAlign; //!< Offset alignment, in bytes, that buffer to texture blit copies
+ /// natively. Any other `BufferRegion::offset` is repacked internally.
};
RendererType::Enum rendererType; //!< Renderer backend type. See: `bgfx::RendererType`
@@ -787,6 +846,103 @@ namespace bgfx
VertexBufferHandle handle; //!< Vertex buffer object handle.
};
+ /// Region of a texture, used as the source or destination of a blit, or as
+ /// the region handed to `bgfx::read`.
+ ///
+ /// Every field defaults to zero, and zero always means "the natural whole".
+ /// `{ .handle = tex }` therefore addresses all of mip 0.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_texture_region_t`.
+ ///
+ struct TextureRegion
+ {
+ /// Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+ /// at zero, which addresses mip 0 of the only slice a 2D texture has.
+ ///
+ /// @param[in] _handle Texture handle.
+ /// @param[in] _x X position of the region.
+ /// @param[in] _y Y position of the region.
+ /// @param[in] _width Width of the region. 0 uses the rest of the mip from `_x`.
+ /// @param[in] _height Height of the region. 0 uses the rest of the mip from `_y`.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_texture_region_init`.
+ ///
+ void init(
+ TextureHandle _handle
+ , uint16_t _x = 0
+ , uint16_t _y = 0
+ , uint16_t _width = 0
+ , uint16_t _height = 0
+ );
+
+ TextureHandle handle = BGFX_INVALID_HANDLE; //!< Texture handle.
+ uint8_t mip = 0; //!< Mip level.
+ uint16_t x = 0; //!< X position of the region.
+ uint16_t y = 0; //!< Y position of the region.
+ uint16_t z = 0; //!< If texture is 2D this should be 0. If the texture is a cube map
+ /// this is the cube face, for a 2D array it is the layer, and for a
+ /// 3D texture it is the Z position.
+ uint16_t width = 0; //!< Width of the region. 0 uses the rest of the mip from `x`.
+ uint16_t height = 0; //!< Height of the region. 0 uses the rest of the mip from `y`.
+ uint16_t depth = 0; //!< Depth of the region for a 3D texture, or the number of layers or
+ /// cube faces otherwise. 0 uses the rest from `z`.
+ };
+
+ /// Region of a buffer, used as the source or destination of a blit, or as the
+ /// region handed to `bgfx::read`.
+ ///
+ /// `rowPitch` and `slicePitch` describe how texture data is laid out in the
+ /// buffer, and are ignored when the other end of the blit is also a buffer.
+ /// Both are in bytes, and 0 selects the tightly packed layout: a row pitch of
+ /// the region width in blocks multiplied by the block size, and a slice pitch
+ /// of that row pitch multiplied by the region height in blocks.
+ ///
+ /// A pitch the backend cannot copy natively is repacked by bgfx, which costs
+ /// an extra pass over the data. `Caps::Limits::blitRowPitchAlign` and
+ /// `blitOffsetAlign` report what the backend copies directly, and
+ /// `BufferRegion::init` fills in a layout that matches them.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_buffer_region_t`.
+ ///
+ struct BufferRegion
+ {
+ /// Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+ /// fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+ /// `handle` is left untouched, so `size` can be used to create the buffer the
+ /// region will point at.
+ ///
+ /// @param[in] _texture Texture region the buffer is copied to or from.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_buffer_region_init_texture`.
+ ///
+ void init(const TextureRegion& _texture);
+
+ /// Fill in the region a blit between two buffers copies. `rowPitch` and
+ /// `slicePitch` are left at zero, since neither end of such a blit is a
+ /// texture.
+ ///
+ /// @param[in] _handle Buffer handle.
+ /// @param[in] _offset Byte offset into the buffer.
+ /// @param[in] _size Number of bytes. 0 uses the rest of the buffer.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_buffer_region_init_buffer`.
+ ///
+ void init(
+ BufferHandle _handle
+ , uint32_t _offset = 0
+ , uint32_t _size = 0
+ );
+
+ BufferHandle handle = {}; //!< Buffer handle.
+ uint32_t offset = 0; //!< Byte offset into the buffer.
+ uint32_t size = 0; //!< Number of bytes. Only used when both ends of a blit are
+ /// buffers, or by `bgfx::read`. 0 uses the rest of the buffer.
+ uint32_t rowPitch = 0; //!< Distance in bytes between the start of two consecutive rows
+ /// of blocks. 0 is tightly packed.
+ uint32_t slicePitch = 0; //!< Distance in bytes between the start of two consecutive
+ /// slices, layers or cube faces. 0 is tightly packed.
+ };
+
/// Texture info.
///
/// @attention C99's equivalent binding is `bgfx_texture_info_t`.
@@ -969,6 +1125,9 @@ namespace bgfx
uint32_t numDraw; //!< Number of draw calls submitted.
uint32_t numCompute; //!< Number of compute calls submitted.
uint32_t numBlit; //!< Number of blit calls submitted.
+ uint32_t numBlitRepack; //!< Number of buffer to texture blit calls that had to be repacked,
+ /// because `BufferRegion::rowPitch` or `offset` didn't match
+ /// `Caps::Limits::blitRowPitchAlign` or `blitOffsetAlign`.
uint32_t numDrawCallsPeak; //!< Highest number of draw+compute calls requested in a single
/// frame so far (peak demand, before any were dropped). Useful
/// to tune `Init::Limits::numDrawCalls`.
@@ -1819,55 +1978,19 @@ namespace bgfx
///
void discard(uint8_t _flags = BGFX_DISCARD_ALL);
- /// Blit 2D texture region between two 2D textures.
+ /// Blit texture region between two textures.
///
/// @param[in] _id View id.
- /// @param[in] _dst Destination texture handle.
- /// @param[in] _dstX Destination texture X position.
- /// @param[in] _dstY Destination texture Y position.
- /// @param[in] _src Source texture handle.
- /// @param[in] _srcX Source texture X position.
- /// @param[in] _srcY Source texture Y position.
- /// @param[in] _width Width of region.
- /// @param[in] _height Height of region.
+ /// @param[in] _dst Destination texture region.
+ /// @param[in] _src Source texture region.
///
- /// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ /// @remarks
+ /// The copy covers the region the two sides have in common: each side gives
+ /// the origin it starts at, and the size is the smaller of the two extents.
+ /// A zero `width`, `height` or `depth` extends to the rest of that mip.
///
- /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
- ///
- void blit(
- ViewId _id
- , TextureHandle _dst
- , uint16_t _dstX
- , uint16_t _dstY
- , TextureHandle _src
- , uint16_t _srcX = 0
- , uint16_t _srcY = 0
- , uint16_t _width = UINT16_MAX
- , uint16_t _height = UINT16_MAX
- );
-
- /// Blit 2D texture region between two 2D textures.
- ///
- /// @param[in] _id View id.
- /// @param[in] _dst Destination texture handle.
- /// @param[in] _dstMip Destination texture mip level.
- /// @param[in] _dstX Destination texture X position.
- /// @param[in] _dstY Destination texture Y position.
- /// @param[in] _dstZ If texture is 2D this argument should be 0. If destination texture is cube
- /// this argument represents destination texture cube face. For 3D texture this argument
- /// represents destination texture Z position.
- /// @param[in] _src Source texture handle.
- /// @param[in] _srcMip Source texture mip level.
- /// @param[in] _srcX Source texture X position.
- /// @param[in] _srcY Source texture Y position.
- /// @param[in] _srcZ If texture is 2D this argument should be 0. If source texture is cube
- /// this argument represents source texture cube face. For 3D texture this argument
- /// represents source texture Z position.
- /// @param[in] _width Width of region.
- /// @param[in] _height Height of region.
- /// @param[in] _depth If texture is 3D this argument represents depth of region, otherwise it's
- /// unused.
+ /// Blit is performed on GPU, and it is ordered within the view. In views, all
+ /// draw commands are executed after blit and compute commands.
///
/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
///
@@ -1877,19 +2000,97 @@ namespace bgfx
///
void blit(
ViewId _id
- , TextureHandle _dst
- , uint8_t _dstMip
- , uint16_t _dstX
- , uint16_t _dstY
- , uint16_t _dstZ
- , TextureHandle _src
- , uint8_t _srcMip = 0
- , uint16_t _srcX = 0
- , uint16_t _srcY = 0
- , uint16_t _srcZ = 0
- , uint16_t _width = UINT16_MAX
- , uint16_t _height = UINT16_MAX
- , uint16_t _depth = UINT16_MAX
+ , const TextureRegion& _dst
+ , const TextureRegion& _src
+ );
+
+ /// Blit buffer region between two buffers.
+ ///
+ /// @param[in] _id View id.
+ /// @param[in] _dst Destination buffer region.
+ /// @param[in] _src Source buffer region.
+ ///
+ /// @remarks
+ /// The source region gives the number of bytes copied, and the destination
+ /// region gives only the offset they land at. A zero `size` copies the rest of
+ /// the source buffer. `rowPitch` and `slicePitch` are unused.
+ ///
+ /// Buffer blit is performed on GPU, and it is ordered within the view, same as
+ /// texture blit. In views, all draw commands are executed after blit and compute
+ /// commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ ///
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ ///
+ /// @attention Source and destination buffer must be different.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_encoder_blit_buffer`.
+ ///
+ void blit(
+ ViewId _id
+ , const BufferRegion& _dst
+ , const BufferRegion& _src
+ );
+
+ /// Blit texture region into buffer.
+ ///
+ /// @param[in] _id View id.
+ /// @param[in] _dst Destination buffer region.
+ /// @param[in] _src Source texture region.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ /// them tightly. `BufferRegion::init` fills in the layout the backend copies
+ /// fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ ///
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_encoder_blit_to_buffer`.
+ ///
+ void blit(
+ ViewId _id
+ , const BufferRegion& _dst
+ , const TextureRegion& _src
+ );
+
+ /// Blit buffer contents into texture region.
+ ///
+ /// @param[in] _id View id.
+ /// @param[in] _dst Destination texture region.
+ /// @param[in] _src Source buffer region.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ /// them tightly packed. `BufferRegion::init` fills in the layout the backend
+ /// copies fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ ///
+ /// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ ///
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_encoder_blit_from_buffer`.
+ ///
+ void blit(
+ ViewId _id
+ , const TextureRegion& _dst
+ , const BufferRegion& _src
);
};
@@ -2523,6 +2724,32 @@ namespace bgfx
, uint16_t _flags = BGFX_BUFFER_NONE
);
+ /// Read back contents of buffer.
+ ///
+ /// @param[in] _src Source buffer region.
+ /// @param[in] _data Destination buffer.
+ ///
+ /// @returns Frame number when the result will be available. See: `bgfx::frame`.
+ ///
+ /// @remarks
+ /// Read back is asynchronous, and the result is available at the returned frame.
+ /// A zero `size` reads the rest of the buffer. `rowPitch` and `slicePitch` are
+ /// unused.
+ ///
+ /// Read back is intended for reading GPU written (compute, or draw indirect) buffers
+ /// back to the CPU. It's not intended to be used in the main render loop, since it
+ /// stalls the GPU.
+ ///
+ /// @attention Buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_read_buffer`.
+ ///
+ uint32_t read(
+ const BufferRegion& _src
+ , void* _data
+ );
+
/// Set static index buffer debug name.
///
/// @param[in] _handle Static index buffer handle.
@@ -3347,13 +3574,19 @@ namespace bgfx
/// Read back texture content.
///
- /// @param[in] _handle Texture handle.
+ /// @param[in] _src Source texture region.
/// @param[in] _data Destination buffer.
- /// @param[in] _layer Texture layer.
- /// @param[in] _mip Mip level.
///
/// @returns Frame number when the result will be available. See: `bgfx::frame`.
///
+ /// @remarks
+ /// Read back is asynchronous, and the result is available at the returned frame.
+ /// `TextureRegion::z` selects cube face, 3D slice, or array layer. The region must
+ /// cover the whole mip.
+ ///
+ /// Read back is not intended to be used in the main render loop, since it stalls
+ /// the GPU.
+ ///
/// @attention Texture must be created with `BGFX_TEXTURE_READ_BACK` flag.
/// It's a texture for CPU readback, and can't be a GPU resource
/// at the same time. See `examples/30-picking`.
@@ -3362,11 +3595,9 @@ namespace bgfx
///
/// @attention C99's equivalent binding is `bgfx_read_texture`.
///
- uint32_t readTexture(
- TextureHandle _handle
+ uint32_t read(
+ const TextureRegion& _src
, void* _data
- , uint16_t _layer = 0
- , uint8_t _mip = 0
);
/// Set texture debug name.
@@ -4878,55 +5109,19 @@ namespace bgfx
///
void discard(uint8_t _flags = BGFX_DISCARD_ALL);
- /// Blit 2D texture region between two 2D textures.
+ /// Blit texture region between two textures.
///
/// @param[in] _id View id.
- /// @param[in] _dst Destination texture handle.
- /// @param[in] _dstX Destination texture X position.
- /// @param[in] _dstY Destination texture Y position.
- /// @param[in] _src Source texture handle.
- /// @param[in] _srcX Source texture X position.
- /// @param[in] _srcY Source texture Y position.
- /// @param[in] _width Width of region.
- /// @param[in] _height Height of region.
+ /// @param[in] _dst Destination texture region.
+ /// @param[in] _src Source texture region.
///
- /// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ /// @remarks
+ /// The copy covers the region the two sides have in common: each side gives
+ /// the origin it starts at, and the size is the smaller of the two extents.
+ /// A zero `width`, `height` or `depth` extends to the rest of that mip.
///
- /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
- ///
- void blit(
- ViewId _id
- , TextureHandle _dst
- , uint16_t _dstX
- , uint16_t _dstY
- , TextureHandle _src
- , uint16_t _srcX = 0
- , uint16_t _srcY = 0
- , uint16_t _width = UINT16_MAX
- , uint16_t _height = UINT16_MAX
- );
-
- /// Blit 2D texture region between two 2D textures.
- ///
- /// @param[in] _id View id.
- /// @param[in] _dst Destination texture handle.
- /// @param[in] _dstMip Destination texture mip level.
- /// @param[in] _dstX Destination texture X position.
- /// @param[in] _dstY Destination texture Y position.
- /// @param[in] _dstZ If texture is 2D this argument should be 0. If destination texture is cube
- /// this argument represents destination texture cube face. For 3D texture this argument
- /// represents destination texture Z position.
- /// @param[in] _src Source texture handle.
- /// @param[in] _srcMip Source texture mip level.
- /// @param[in] _srcX Source texture X position.
- /// @param[in] _srcY Source texture Y position.
- /// @param[in] _srcZ If texture is 2D this argument should be 0. If source texture is cube
- /// this argument represents source texture cube face. For 3D texture this argument
- /// represents source texture Z position.
- /// @param[in] _width Width of region.
- /// @param[in] _height Height of region.
- /// @param[in] _depth If texture is 3D this argument represents depth of region, otherwise it's
- /// unused.
+ /// Blit is performed on GPU, and it is ordered within the view. In views, all
+ /// draw commands are executed after blit and compute commands.
///
/// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
///
@@ -4936,19 +5131,97 @@ namespace bgfx
///
void blit(
ViewId _id
- , TextureHandle _dst
- , uint8_t _dstMip
- , uint16_t _dstX
- , uint16_t _dstY
- , uint16_t _dstZ
- , TextureHandle _src
- , uint8_t _srcMip = 0
- , uint16_t _srcX = 0
- , uint16_t _srcY = 0
- , uint16_t _srcZ = 0
- , uint16_t _width = UINT16_MAX
- , uint16_t _height = UINT16_MAX
- , uint16_t _depth = UINT16_MAX
+ , const TextureRegion& _dst
+ , const TextureRegion& _src
+ );
+
+ /// Blit buffer region between two buffers.
+ ///
+ /// @param[in] _id View id.
+ /// @param[in] _dst Destination buffer region.
+ /// @param[in] _src Source buffer region.
+ ///
+ /// @remarks
+ /// The source region gives the number of bytes copied, and the destination
+ /// region gives only the offset they land at. A zero `size` copies the rest of
+ /// the source buffer. `rowPitch` and `slicePitch` are unused.
+ ///
+ /// Buffer blit is performed on GPU, and it is ordered within the view, same as
+ /// texture blit. In views, all draw commands are executed after blit and compute
+ /// commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ ///
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ ///
+ /// @attention Source and destination buffer must be different.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_blit_buffer`.
+ ///
+ void blit(
+ ViewId _id
+ , const BufferRegion& _dst
+ , const BufferRegion& _src
+ );
+
+ /// Blit texture region into buffer.
+ ///
+ /// @param[in] _id View id.
+ /// @param[in] _dst Destination buffer region.
+ /// @param[in] _src Source texture region.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ /// them tightly. `BufferRegion::init` fills in the layout the backend copies
+ /// fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ ///
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_blit_to_buffer`.
+ ///
+ void blit(
+ ViewId _id
+ , const BufferRegion& _dst
+ , const TextureRegion& _src
+ );
+
+ /// Blit buffer contents into texture region.
+ ///
+ /// @param[in] _id View id.
+ /// @param[in] _dst Destination texture region.
+ /// @param[in] _src Source buffer region.
+ ///
+ /// @remarks
+ /// The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ /// `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ /// them tightly packed. `BufferRegion::init` fills in the layout the backend
+ /// copies fastest, and bgfx repacks internally for any other layout.
+ ///
+ /// Blit is performed on GPU, and it is ordered within the view, same as texture
+ /// blit. In views, all draw commands are executed after blit and compute commands.
+ ///
+ /// @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ /// `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ ///
+ /// @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ ///
+ /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ ///
+ /// @attention C99's equivalent binding is `bgfx_blit_from_buffer`.
+ ///
+ void blit(
+ ViewId _id
+ , const TextureRegion& _dst
+ , const BufferRegion& _src
);
} // namespace bgfx
diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h
index a180ce6fc..84ad10d08 100644
--- a/include/bgfx/c99/bgfx.h
+++ b/include/bgfx/c99/bgfx.h
@@ -558,6 +558,70 @@ typedef struct bgfx_vertex_buffer_handle_s { uint16_t idx; } bgfx_vertex_buffer_
typedef struct bgfx_vertex_layout_handle_s { uint16_t idx; } bgfx_vertex_layout_handle_t;
+typedef struct bgfx_buffer_handle_s { uint16_t idx; uint16_t type; } bgfx_buffer_handle_t;
+
+typedef enum bgfx_buffer_handle_type
+{
+ BGFX_BUFFER_HANDLE_TYPE_DYNAMIC_INDEX_BUFFER,
+ BGFX_BUFFER_HANDLE_TYPE_DYNAMIC_VERTEX_BUFFER,
+ BGFX_BUFFER_HANDLE_TYPE_INDEX_BUFFER,
+ BGFX_BUFFER_HANDLE_TYPE_INDIRECT_BUFFER,
+ BGFX_BUFFER_HANDLE_TYPE_VERTEX_BUFFER,
+
+ BGFX_BUFFER_HANDLE_TYPE_COUNT
+
+} bgfx_buffer_handle_type_t;
+
+static inline bgfx_buffer_handle_t bgfx_buffer_from_dynamic_index_buffer(bgfx_dynamic_index_buffer_handle_t _handle)
+{
+ bgfx_buffer_handle_t handle;
+ handle.idx = _handle.idx;
+ handle.type = BGFX_BUFFER_HANDLE_TYPE_DYNAMIC_INDEX_BUFFER;
+ return handle;
+}
+
+static inline bgfx_buffer_handle_t bgfx_buffer_from_dynamic_vertex_buffer(bgfx_dynamic_vertex_buffer_handle_t _handle)
+{
+ bgfx_buffer_handle_t handle;
+ handle.idx = _handle.idx;
+ handle.type = BGFX_BUFFER_HANDLE_TYPE_DYNAMIC_VERTEX_BUFFER;
+ return handle;
+}
+
+static inline bgfx_buffer_handle_t bgfx_buffer_from_index_buffer(bgfx_index_buffer_handle_t _handle)
+{
+ bgfx_buffer_handle_t handle;
+ handle.idx = _handle.idx;
+ handle.type = BGFX_BUFFER_HANDLE_TYPE_INDEX_BUFFER;
+ return handle;
+}
+
+static inline bgfx_buffer_handle_t bgfx_buffer_from_indirect_buffer(bgfx_indirect_buffer_handle_t _handle)
+{
+ bgfx_buffer_handle_t handle;
+ handle.idx = _handle.idx;
+ handle.type = BGFX_BUFFER_HANDLE_TYPE_INDIRECT_BUFFER;
+ return handle;
+}
+
+static inline bgfx_buffer_handle_t bgfx_buffer_from_vertex_buffer(bgfx_vertex_buffer_handle_t _handle)
+{
+ bgfx_buffer_handle_t handle;
+ handle.idx = _handle.idx;
+ handle.type = BGFX_BUFFER_HANDLE_TYPE_VERTEX_BUFFER;
+ return handle;
+}
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#define BGFX_BUFFER_HANDLE(_handle) _Generic( (_handle) \
+ , bgfx_dynamic_index_buffer_handle_t : bgfx_buffer_from_dynamic_index_buffer \
+ , bgfx_dynamic_vertex_buffer_handle_t: bgfx_buffer_from_dynamic_vertex_buffer \
+ , bgfx_index_buffer_handle_t : bgfx_buffer_from_index_buffer \
+ , bgfx_indirect_buffer_handle_t : bgfx_buffer_from_indirect_buffer \
+ , bgfx_vertex_buffer_handle_t : bgfx_buffer_from_vertex_buffer \
+ )(_handle)
+#endif // defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+
#define BGFX_HANDLE_IS_VALID(h) ((h).idx != UINT16_MAX)
@@ -614,6 +678,18 @@ typedef struct bgfx_caps_limits_s
uint32_t maxTransientVbSize; /** Maximum transient vertex buffer size. */
uint32_t maxTransientIbSize; /** Maximum transient index buffer size. */
uint32_t minUniformBufferSize; /** Mimimum uniform buffer size. */
+
+ /**
+ * Row pitch alignment, in bytes, that buffer to texture blit copies
+ * natively. Any other `BufferRegion::rowPitch` is repacked internally.
+ */
+ uint32_t blitRowPitchAlign;
+
+ /**
+ * Offset alignment, in bytes, that buffer to texture blit copies
+ * natively. Any other `BufferRegion::offset` is repacked internally.
+ */
+ uint32_t blitOffsetAlign;
} bgfx_caps_limits_t;
@@ -897,6 +973,79 @@ typedef struct bgfx_instance_data_buffer_s
} bgfx_instance_data_buffer_t;
+/**
+ * Region of a texture, used as the source or destination of a blit, or as
+ * the region handed to `bgfx::read`.
+ *
+ * Every field defaults to zero, and zero always means "the natural whole".
+ * `{ .handle = tex }` therefore addresses all of mip 0.
+ *
+ */
+typedef struct bgfx_texture_region_s
+{
+ bgfx_texture_handle_t handle; /** Texture handle. */
+ uint8_t mip; /** Mip level. */
+ uint16_t x; /** X position of the region. */
+ uint16_t y; /** Y position of the region. */
+
+ /**
+ * If texture is 2D this should be 0. If the texture is a cube map
+ * this is the cube face, for a 2D array it is the layer, and for a
+ * 3D texture it is the Z position.
+ */
+ uint16_t z;
+ uint16_t width; /** Width of the region. 0 uses the rest of the mip from `x`. */
+ uint16_t height; /** Height of the region. 0 uses the rest of the mip from `y`. */
+
+ /**
+ * Depth of the region for a 3D texture, or the number of layers or
+ * cube faces otherwise. 0 uses the rest from `z`.
+ */
+ uint16_t depth;
+
+} bgfx_texture_region_t;
+
+/**
+ * Region of a buffer, used as the source or destination of a blit, or as the
+ * region handed to `bgfx::read`.
+ *
+ * `rowPitch` and `slicePitch` describe how texture data is laid out in the
+ * buffer, and are ignored when the other end of the blit is also a buffer.
+ * Both are in bytes, and 0 selects the tightly packed layout: a row pitch of
+ * the region width in blocks multiplied by the block size, and a slice pitch
+ * of that row pitch multiplied by the region height in blocks.
+ *
+ * A pitch the backend cannot copy natively is repacked by bgfx, which costs
+ * an extra pass over the data. `Caps::Limits::blitRowPitchAlign` and
+ * `blitOffsetAlign` report what the backend copies directly, and
+ * `BufferRegion::init` fills in a layout that matches them.
+ *
+ */
+typedef struct bgfx_buffer_region_s
+{
+ bgfx_buffer_handle_t handle; /** Buffer handle. */
+ uint32_t offset; /** Byte offset into the buffer. */
+
+ /**
+ * Number of bytes. Only used when both ends of a blit are
+ * buffers, or by `bgfx::read`. 0 uses the rest of the buffer.
+ */
+ uint32_t size;
+
+ /**
+ * Distance in bytes between the start of two consecutive rows
+ * of blocks. 0 is tightly packed.
+ */
+ uint32_t rowPitch;
+
+ /**
+ * Distance in bytes between the start of two consecutive
+ * slices, layers or cube faces. 0 is tightly packed.
+ */
+ uint32_t slicePitch;
+
+} bgfx_buffer_region_t;
+
/**
* Texture info.
*
@@ -1077,6 +1226,13 @@ typedef struct bgfx_stats_s
uint32_t numCompute; /** Number of compute calls submitted. */
uint32_t numBlit; /** Number of blit calls submitted. */
+ /**
+ * Number of buffer to texture blit calls that had to be repacked,
+ * because `BufferRegion::rowPitch` or `offset` didn't match
+ * `Caps::Limits::blitRowPitchAlign` or `blitOffsetAlign`.
+ */
+ uint32_t numBlitRepack;
+
/**
* Highest number of draw+compute calls requested in a single
* frame so far (peak demand, before any were dropped). Useful
@@ -1137,6 +1293,42 @@ typedef struct bgfx_encoder_s bgfx_encoder_t;
+/**
+ * Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+ * at zero, which addresses mip 0 of the only slice a 2D texture has.
+ *
+ * @param[in] _handle Texture handle.
+ * @param[in] _x X position of the region.
+ * @param[in] _y Y position of the region.
+ * @param[in] _width Width of the region. 0 uses the rest of the mip from `_x`.
+ * @param[in] _height Height of the region. 0 uses the rest of the mip from `_y`.
+ *
+ */
+BGFX_C_API void bgfx_texture_region_init(bgfx_texture_region_t* _this, bgfx_texture_handle_t _handle, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height);
+
+/**
+ * Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+ * fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+ * `handle` is left untouched, so `size` can be used to create the buffer the
+ * region will point at.
+ *
+ * @param[in] _texture Texture region the buffer is copied to or from.
+ *
+ */
+BGFX_C_API void bgfx_buffer_region_init_texture(bgfx_buffer_region_t* _this, const bgfx_texture_region_t * _texture);
+
+/**
+ * Fill in the region a blit between two buffers copies. `rowPitch` and
+ * `slicePitch` are left at zero, since neither end of such a blit is a
+ * texture.
+ *
+ * @param[in] _handle Buffer handle.
+ * @param[in] _offset Byte offset into the buffer.
+ * @param[in] _size Number of bytes. 0 uses the rest of the buffer.
+ *
+ */
+BGFX_C_API void bgfx_buffer_region_init_buffer(bgfx_buffer_region_t* _this, bgfx_buffer_handle_t _handle, uint32_t _offset, uint32_t _size);
+
/**
* Init attachment.
*
@@ -1599,6 +1791,29 @@ BGFX_C_API void bgfx_dbg_text_image(uint16_t _x, uint16_t _y, uint16_t _width, u
*/
BGFX_C_API bgfx_index_buffer_handle_t bgfx_create_index_buffer(const bgfx_memory_t* _mem, uint16_t _flags);
+/**
+ * Read back contents of buffer.
+ *
+ * @remarks
+ * Read back is asynchronous, and the result is available at the returned frame.
+ * A zero `size` reads the rest of the buffer. `rowPitch` and `slicePitch` are
+ * unused.
+ *
+ * Read back is intended for reading GPU written (compute, or draw indirect) buffers
+ * back to the CPU. It's not intended to be used in the main render loop, since it
+ * stalls the GPU.
+ *
+ * @attention Buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ *
+ * @param[in] _src Source buffer region.
+ * @param[in] _data Destination buffer.
+ *
+ * @returns Frame number when the result will be available. See: `bgfx::frame`.
+ *
+ */
+BGFX_C_API uint32_t bgfx_read_buffer(const bgfx_buffer_region_t * _src, void* _data);
+
/**
* Set static index buffer debug name.
*
@@ -2247,20 +2462,26 @@ BGFX_C_API void bgfx_clear_texture(bgfx_texture_handle_t _handle, uint8_t _mip,
/**
* Read back texture content.
*
+ * @remarks
+ * Read back is asynchronous, and the result is available at the returned frame.
+ * `TextureRegion::z` selects cube face, 3D slice, or array layer. The region must
+ * cover the whole mip.
+ *
+ * Read back is not intended to be used in the main render loop, since it stalls
+ * the GPU.
+ *
* @attention Texture must be created with `BGFX_TEXTURE_READ_BACK` flag.
* It's a texture for CPU readback, and can't be a GPU resource
* at the same time. See `examples/30-picking`.
* @attention Availability depends on: `BGFX_CAPS_TEXTURE_READ_BACK`.
*
- * @param[in] _handle Texture handle.
+ * @param[in] _src Source texture region.
* @param[in] _data Destination buffer.
- * @param[in] _layer Texture layer.
- * @param[in] _mip Mip level.
*
* @returns Frame number when the result will be available. See: `bgfx::frame`.
*
*/
-BGFX_C_API uint32_t bgfx_read_texture(bgfx_texture_handle_t _handle, void* _data, uint16_t _layer, uint8_t _mip);
+BGFX_C_API uint32_t bgfx_read_texture(const bgfx_texture_region_t * _src, void* _data);
/**
* Set texture debug name.
@@ -3314,33 +3535,97 @@ BGFX_C_API void bgfx_encoder_dispatch_indirect(bgfx_encoder_t* _this, bgfx_view_
BGFX_C_API void bgfx_encoder_discard(bgfx_encoder_t* _this, uint8_t _flags);
/**
- * Blit 2D texture region between two 2D textures.
+ * Blit texture region between two textures.
+ *
+ * @remarks
+ * The copy covers the region the two sides have in common: each side gives
+ * the origin it starts at, and the size is the smaller of the two extents.
+ * A zero `width`, `height` or `depth` extends to the rest of that mip.
+ *
+ * Blit is performed on GPU, and it is ordered within the view. In views, all
+ * draw commands are executed after blit and compute commands.
*
* @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
* @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
*
* @param[in] _id View id.
- * @param[in] _dst Destination texture handle.
- * @param[in] _dstMip Destination texture mip level.
- * @param[in] _dstX Destination texture X position.
- * @param[in] _dstY Destination texture Y position.
- * @param[in] _dstZ If texture is 2D this argument should be 0. If destination texture is cube
- * this argument represents destination texture cube face. For 3D texture this argument
- * represents destination texture Z position.
- * @param[in] _src Source texture handle.
- * @param[in] _srcMip Source texture mip level.
- * @param[in] _srcX Source texture X position.
- * @param[in] _srcY Source texture Y position.
- * @param[in] _srcZ If texture is 2D this argument should be 0. If source texture is cube
- * this argument represents source texture cube face. For 3D texture this argument
- * represents source texture Z position.
- * @param[in] _width Width of region.
- * @param[in] _height Height of region.
- * @param[in] _depth If texture is 3D this argument represents depth of region, otherwise it's
- * unused.
+ * @param[in] _dst Destination texture region.
+ * @param[in] _src Source texture region.
*
*/
-BGFX_C_API void bgfx_encoder_blit(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_texture_handle_t _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, bgfx_texture_handle_t _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth);
+BGFX_C_API void bgfx_encoder_blit(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_texture_region_t * _src);
+
+/**
+ * Blit buffer region between two buffers.
+ *
+ * @remarks
+ * The source region gives the number of bytes copied, and the destination
+ * region gives only the offset they land at. A zero `size` copies the rest of
+ * the source buffer. `rowPitch` and `slicePitch` are unused.
+ *
+ * Buffer blit is performed on GPU, and it is ordered within the view, same as
+ * texture blit. In views, all draw commands are executed after blit and compute
+ * commands.
+ *
+ * @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ * @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ * @attention Source and destination buffer must be different.
+ *
+ * @param[in] _id View id.
+ * @param[in] _dst Destination buffer region.
+ * @param[in] _src Source buffer region.
+ *
+ */
+BGFX_C_API void bgfx_encoder_blit_buffer(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_buffer_region_t * _src);
+
+/**
+ * Blit texture region into buffer.
+ *
+ * @remarks
+ * The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ * `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ * them tightly. `BufferRegion::init` fills in the layout the backend copies
+ * fastest, and bgfx repacks internally for any other layout.
+ *
+ * Blit is performed on GPU, and it is ordered within the view, same as texture
+ * blit. In views, all draw commands are executed after blit and compute commands.
+ *
+ * @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ * @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ *
+ * @param[in] _id View id.
+ * @param[in] _dst Destination buffer region.
+ * @param[in] _src Source texture region.
+ *
+ */
+BGFX_C_API void bgfx_encoder_blit_to_buffer(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_texture_region_t * _src);
+
+/**
+ * Blit buffer contents into texture region.
+ *
+ * @remarks
+ * The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ * `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ * them tightly packed. `BufferRegion::init` fills in the layout the backend
+ * copies fastest, and bgfx repacks internally for any other layout.
+ *
+ * Blit is performed on GPU, and it is ordered within the view, same as texture
+ * blit. In views, all draw commands are executed after blit and compute commands.
+ *
+ * @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ * @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ * @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ *
+ * @param[in] _id View id.
+ * @param[in] _dst Destination texture region.
+ * @param[in] _src Source buffer region.
+ *
+ */
+BGFX_C_API void bgfx_encoder_blit_from_buffer(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_buffer_region_t * _src);
/**
* Request screen shot of window back buffer.
@@ -3982,37 +4267,104 @@ BGFX_C_API void bgfx_dispatch_indirect(bgfx_view_id_t _id, bgfx_program_handle_t
BGFX_C_API void bgfx_discard(uint8_t _flags);
/**
- * Blit 2D texture region between two 2D textures.
+ * Blit texture region between two textures.
+ *
+ * @remarks
+ * The copy covers the region the two sides have in common: each side gives
+ * the origin it starts at, and the size is the smaller of the two extents.
+ * A zero `width`, `height` or `depth` extends to the rest of that mip.
+ *
+ * Blit is performed on GPU, and it is ordered within the view. In views, all
+ * draw commands are executed after blit and compute commands.
*
* @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
* @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
*
* @param[in] _id View id.
- * @param[in] _dst Destination texture handle.
- * @param[in] _dstMip Destination texture mip level.
- * @param[in] _dstX Destination texture X position.
- * @param[in] _dstY Destination texture Y position.
- * @param[in] _dstZ If texture is 2D this argument should be 0. If destination texture is cube
- * this argument represents destination texture cube face. For 3D texture this argument
- * represents destination texture Z position.
- * @param[in] _src Source texture handle.
- * @param[in] _srcMip Source texture mip level.
- * @param[in] _srcX Source texture X position.
- * @param[in] _srcY Source texture Y position.
- * @param[in] _srcZ If texture is 2D this argument should be 0. If source texture is cube
- * this argument represents source texture cube face. For 3D texture this argument
- * represents source texture Z position.
- * @param[in] _width Width of region.
- * @param[in] _height Height of region.
- * @param[in] _depth If texture is 3D this argument represents depth of region, otherwise it's
- * unused.
+ * @param[in] _dst Destination texture region.
+ * @param[in] _src Source texture region.
*
*/
-BGFX_C_API void bgfx_blit(bgfx_view_id_t _id, bgfx_texture_handle_t _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, bgfx_texture_handle_t _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth);
+BGFX_C_API void bgfx_blit(bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_texture_region_t * _src);
+
+/**
+ * Blit buffer region between two buffers.
+ *
+ * @remarks
+ * The source region gives the number of bytes copied, and the destination
+ * region gives only the offset they land at. A zero `size` copies the rest of
+ * the source buffer. `rowPitch` and `slicePitch` are unused.
+ *
+ * Buffer blit is performed on GPU, and it is ordered within the view, same as
+ * texture blit. In views, all draw commands are executed after blit and compute
+ * commands.
+ *
+ * @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ * @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ * @attention Source and destination buffer must be different.
+ *
+ * @param[in] _id View id.
+ * @param[in] _dst Destination buffer region.
+ * @param[in] _src Source buffer region.
+ *
+ */
+BGFX_C_API void bgfx_blit_buffer(bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_buffer_region_t * _src);
+
+/**
+ * Blit texture region into buffer.
+ *
+ * @remarks
+ * The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ * `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+ * them tightly. `BufferRegion::init` fills in the layout the backend copies
+ * fastest, and bgfx repacks internally for any other layout.
+ *
+ * Blit is performed on GPU, and it is ordered within the view, same as texture
+ * blit. In views, all draw commands are executed after blit and compute commands.
+ *
+ * @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flag.
+ * @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ *
+ * @param[in] _id View id.
+ * @param[in] _dst Destination buffer region.
+ * @param[in] _src Source texture region.
+ *
+ */
+BGFX_C_API void bgfx_blit_to_buffer(bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_texture_region_t * _src);
+
+/**
+ * Blit buffer contents into texture region.
+ *
+ * @remarks
+ * The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+ * `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+ * them tightly packed. `BufferRegion::init` fills in the layout the backend
+ * copies fastest, and bgfx repacks internally for any other layout.
+ *
+ * Blit is performed on GPU, and it is ordered within the view, same as texture
+ * blit. In views, all draw commands are executed after blit and compute commands.
+ *
+ * @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+ * `BGFX_BUFFER_DRAW_INDIRECT` flags.
+ * @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+ * @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+ *
+ * @param[in] _id View id.
+ * @param[in] _dst Destination texture region.
+ * @param[in] _src Source buffer region.
+ *
+ */
+BGFX_C_API void bgfx_blit_from_buffer(bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_buffer_region_t * _src);
/**/
typedef enum bgfx_function_id
{
+ BGFX_FUNCTION_ID_TEXTURE_REGION_INIT,
+ BGFX_FUNCTION_ID_BUFFER_REGION_INIT_TEXTURE,
+ BGFX_FUNCTION_ID_BUFFER_REGION_INIT_BUFFER,
BGFX_FUNCTION_ID_ATTACHMENT_INIT,
BGFX_FUNCTION_ID_VERTEX_LAYOUT_BEGIN,
BGFX_FUNCTION_ID_VERTEX_LAYOUT_ADD,
@@ -4048,6 +4400,7 @@ typedef enum bgfx_function_id
BGFX_FUNCTION_ID_DBG_TEXT_VPRINTF,
BGFX_FUNCTION_ID_DBG_TEXT_IMAGE,
BGFX_FUNCTION_ID_CREATE_INDEX_BUFFER,
+ BGFX_FUNCTION_ID_READ_BUFFER,
BGFX_FUNCTION_ID_SET_INDEX_BUFFER_NAME,
BGFX_FUNCTION_ID_DESTROY_INDEX_BUFFER,
BGFX_FUNCTION_ID_CREATE_VERTEX_LAYOUT,
@@ -4172,6 +4525,9 @@ typedef enum bgfx_function_id
BGFX_FUNCTION_ID_ENCODER_DISPATCH_INDIRECT,
BGFX_FUNCTION_ID_ENCODER_DISCARD,
BGFX_FUNCTION_ID_ENCODER_BLIT,
+ BGFX_FUNCTION_ID_ENCODER_BLIT_BUFFER,
+ BGFX_FUNCTION_ID_ENCODER_BLIT_TO_BUFFER,
+ BGFX_FUNCTION_ID_ENCODER_BLIT_FROM_BUFFER,
BGFX_FUNCTION_ID_REQUEST_SCREEN_SHOT,
BGFX_FUNCTION_ID_RENDER_FRAME,
BGFX_FUNCTION_ID_SET_PLATFORM_DATA,
@@ -4220,6 +4576,9 @@ typedef enum bgfx_function_id
BGFX_FUNCTION_ID_DISPATCH_INDIRECT,
BGFX_FUNCTION_ID_DISCARD,
BGFX_FUNCTION_ID_BLIT,
+ BGFX_FUNCTION_ID_BLIT_BUFFER,
+ BGFX_FUNCTION_ID_BLIT_TO_BUFFER,
+ BGFX_FUNCTION_ID_BLIT_FROM_BUFFER,
BGFX_FUNCTION_ID_COUNT
@@ -4228,6 +4587,9 @@ typedef enum bgfx_function_id
/**/
struct bgfx_interface_vtbl
{
+ void (*texture_region_init)(bgfx_texture_region_t* _this, bgfx_texture_handle_t _handle, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height);
+ void (*buffer_region_init_texture)(bgfx_buffer_region_t* _this, const bgfx_texture_region_t * _texture);
+ void (*buffer_region_init_buffer)(bgfx_buffer_region_t* _this, bgfx_buffer_handle_t _handle, uint32_t _offset, uint32_t _size);
void (*attachment_init)(bgfx_attachment_t* _this, bgfx_texture_handle_t _handle, bgfx_access_t _access, uint16_t _layer, uint16_t _numLayers, uint16_t _mip, uint8_t _resolve);
bgfx_vertex_layout_t* (*vertex_layout_begin)(bgfx_vertex_layout_t* _this, bgfx_renderer_type_t _rendererType);
bgfx_vertex_layout_t* (*vertex_layout_add)(bgfx_vertex_layout_t* _this, bgfx_attrib_t _attrib, uint8_t _num, bgfx_attrib_type_t _type, bool _normalized, bool _asInt);
@@ -4263,6 +4625,7 @@ struct bgfx_interface_vtbl
void (*dbg_text_vprintf)(uint16_t _x, uint16_t _y, uint8_t _attr, const char* _format, va_list _argList);
void (*dbg_text_image)(uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const void* _data, uint16_t _pitch);
bgfx_index_buffer_handle_t (*create_index_buffer)(const bgfx_memory_t* _mem, uint16_t _flags);
+ uint32_t (*read_buffer)(const bgfx_buffer_region_t * _src, void* _data);
void (*set_index_buffer_name)(bgfx_index_buffer_handle_t _handle, const char* _name, int32_t _len);
void (*destroy_index_buffer)(bgfx_index_buffer_handle_t _handle);
bgfx_vertex_layout_handle_t (*create_vertex_layout)(const bgfx_vertex_layout_t * _layout);
@@ -4307,7 +4670,7 @@ struct bgfx_interface_vtbl
void (*update_texture_3d)(bgfx_texture_handle_t _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _z, uint16_t _width, uint16_t _height, uint16_t _depth, const bgfx_memory_t* _mem);
void (*update_texture_cube)(bgfx_texture_handle_t _handle, uint16_t _layer, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const bgfx_memory_t* _mem, uint16_t _pitch);
void (*clear_texture)(bgfx_texture_handle_t _handle, uint8_t _mip, uint8_t _numMips, uint16_t _layer, uint16_t _numLayers);
- uint32_t (*read_texture)(bgfx_texture_handle_t _handle, void* _data, uint16_t _layer, uint8_t _mip);
+ uint32_t (*read_texture)(const bgfx_texture_region_t * _src, void* _data);
void (*set_texture_name)(bgfx_texture_handle_t _handle, const char* _name, int32_t _len);
void* (*get_direct_access_ptr)(bgfx_texture_handle_t _handle);
void (*destroy_texture)(bgfx_texture_handle_t _handle);
@@ -4386,7 +4749,10 @@ struct bgfx_interface_vtbl
void (*encoder_dispatch)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _numX, uint32_t _numY, uint32_t _numZ, uint8_t _flags);
void (*encoder_dispatch_indirect)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint32_t _start, uint32_t _num, uint8_t _flags);
void (*encoder_discard)(bgfx_encoder_t* _this, uint8_t _flags);
- void (*encoder_blit)(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_texture_handle_t _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, bgfx_texture_handle_t _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth);
+ void (*encoder_blit)(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_texture_region_t * _src);
+ void (*encoder_blit_buffer)(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_buffer_region_t * _src);
+ void (*encoder_blit_to_buffer)(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_texture_region_t * _src);
+ void (*encoder_blit_from_buffer)(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_buffer_region_t * _src);
void (*request_screen_shot)(bgfx_frame_buffer_handle_t _handle, const char* _filePath);
bgfx_render_frame_t (*render_frame)(int32_t _msecs);
void (*set_platform_data)(const bgfx_platform_data_t * _data);
@@ -4434,7 +4800,10 @@ struct bgfx_interface_vtbl
void (*dispatch)(bgfx_view_id_t _id, bgfx_program_handle_t _program, uint32_t _numX, uint32_t _numY, uint32_t _numZ, uint8_t _flags);
void (*dispatch_indirect)(bgfx_view_id_t _id, bgfx_program_handle_t _program, bgfx_indirect_buffer_handle_t _indirectHandle, uint32_t _start, uint32_t _num, uint8_t _flags);
void (*discard)(uint8_t _flags);
- void (*blit)(bgfx_view_id_t _id, bgfx_texture_handle_t _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, bgfx_texture_handle_t _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth);
+ void (*blit)(bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_texture_region_t * _src);
+ void (*blit_buffer)(bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_buffer_region_t * _src);
+ void (*blit_to_buffer)(bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_texture_region_t * _src);
+ void (*blit_from_buffer)(bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_buffer_region_t * _src);
};
/**/
diff --git a/include/bgfx/defines.h b/include/bgfx/defines.h
index f58fa4f71..8d7832ea0 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(156)
+#define BGFX_API_VERSION UINT32_C(157)
/**
* 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 3a5925748..bb68e7090 100644
--- a/scripts/bgfx.idl
+++ b/scripts/bgfx.idl
@@ -1,7 +1,7 @@
-- vim: syntax=lua
-- bgfx interface
-version(156)
+version(157)
typedef "bool"
typedef "char"
@@ -819,6 +819,10 @@ struct.Limits { namespace = "Caps" }
.maxTransientVbSize "uint32_t" --- Maximum transient vertex buffer size.
.maxTransientIbSize "uint32_t" --- Maximum transient index buffer size.
.minUniformBufferSize "uint32_t" --- Mimimum uniform buffer size.
+ .blitRowPitchAlign "uint32_t" --- Row pitch alignment, in bytes, that buffer to texture blit copies
+ --- natively. Any other `BufferRegion::rowPitch` is repacked internally.
+ .blitOffsetAlign "uint32_t" --- Offset alignment, in bytes, that buffer to texture blit copies
+ --- natively. Any other `BufferRegion::offset` is repacked internally.
--- Renderer capabilities.
struct.Caps { section = "Capabilities" }
@@ -994,6 +998,93 @@ struct.InstanceDataBuffer { section = "Draw/Buffers" }
.stride "uint16_t" --- Vertex buffer stride.
.handle "VertexBufferHandle" --- Vertex buffer object handle.
+--- Region of a texture, used as the source or destination of a blit, or as
+--- the region handed to `bgfx::read`.
+---
+--- Every field defaults to zero, and zero always means "the natural whole".
+--- `{ .handle = tex }` therefore addresses all of mip 0.
+struct.TextureRegion { shortname, section = "Textures" }
+ .handle "TextureHandle" --- Texture handle.
+ { default = "BGFX_INVALID_HANDLE" }
+ .mip "uint8_t" --- Mip level.
+ { default = 0 }
+ .x "uint16_t" --- X position of the region.
+ { default = 0 }
+ .y "uint16_t" --- Y position of the region.
+ { default = 0 }
+ .z "uint16_t" --- If texture is 2D this should be 0. If the texture is a cube map
+ --- this is the cube face, for a 2D array it is the layer, and for a
+ --- 3D texture it is the Z position.
+ { default = 0 }
+ .width "uint16_t" --- Width of the region. 0 uses the rest of the mip from `x`.
+ { default = 0 }
+ .height "uint16_t" --- Height of the region. 0 uses the rest of the mip from `y`.
+ { default = 0 }
+ .depth "uint16_t" --- Depth of the region for a 3D texture, or the number of layers or
+ --- cube faces otherwise. 0 uses the rest from `z`.
+ { default = 0 }
+
+--- Fill in the region of a plain 2D texture. `mip`, `z` and `depth` are left
+--- at zero, which addresses mip 0 of the only slice a 2D texture has.
+func.TextureRegion.init { section = "Textures" }
+ "void"
+ .handle "TextureHandle" --- Texture handle.
+ .x "uint16_t" --- X position of the region.
+ { default = 0 }
+ .y "uint16_t" --- Y position of the region.
+ { default = 0 }
+ .width "uint16_t" --- Width of the region. 0 uses the rest of the mip from `_x`.
+ { default = 0 }
+ .height "uint16_t" --- Height of the region. 0 uses the rest of the mip from `_y`.
+ { default = 0 }
+
+--- Region of a buffer, used as the source or destination of a blit, or as the
+--- region handed to `bgfx::read`.
+---
+--- `rowPitch` and `slicePitch` describe how texture data is laid out in the
+--- buffer, and are ignored when the other end of the blit is also a buffer.
+--- Both are in bytes, and 0 selects the tightly packed layout: a row pitch of
+--- the region width in blocks multiplied by the block size, and a slice pitch
+--- of that row pitch multiplied by the region height in blocks.
+---
+--- A pitch the backend cannot copy natively is repacked by bgfx, which costs
+--- an extra pass over the data. `Caps::Limits::blitRowPitchAlign` and
+--- `blitOffsetAlign` report what the backend copies directly, and
+--- `BufferRegion::init` fills in a layout that matches them.
+struct.BufferRegion { shortname, section = "Draw/Buffers" }
+ .handle "BufferHandle" --- Buffer handle.
+ { default = "{}" }
+ .offset "uint32_t" --- Byte offset into the buffer.
+ { default = 0 }
+ .size "uint32_t" --- Number of bytes. Only used when both ends of a blit are
+ --- buffers, or by `bgfx::read`. 0 uses the rest of the buffer.
+ { default = 0 }
+ .rowPitch "uint32_t" --- Distance in bytes between the start of two consecutive rows
+ --- of blocks. 0 is tightly packed.
+ { default = 0 }
+ .slicePitch "uint32_t" --- Distance in bytes between the start of two consecutive
+ --- slices, layers or cube faces. 0 is tightly packed.
+ { default = 0 }
+
+--- Fill `rowPitch`, `slicePitch` and `size` with the layout the backend copies
+--- fastest for `_texture`, and round `offset` up to `Caps::Limits::blitOffsetAlign`.
+--- `handle` is left untouched, so `size` can be used to create the buffer the
+--- region will point at.
+func.BufferRegion.init { cname = "init_texture", section = "Draw/Buffers" }
+ "void"
+ .texture "const TextureRegion &" --- Texture region the buffer is copied to or from.
+
+--- Fill in the region a blit between two buffers copies. `rowPitch` and
+--- `slicePitch` are left at zero, since neither end of such a blit is a
+--- texture.
+func.BufferRegion.init { cname = "init_buffer", section = "Draw/Buffers" }
+ "void"
+ .handle "BufferHandle" --- Buffer handle.
+ .offset "uint32_t" --- Byte offset into the buffer.
+ { default = 0 }
+ .size "uint32_t" --- Number of bytes. 0 uses the rest of the buffer.
+ { default = 0 }
+
--- Texture info.
struct.TextureInfo { section = "Textures" }
.format "TextureFormat::Enum" --- Texture format.
@@ -1125,6 +1216,9 @@ struct.Stats { section = "Statistics" }
.numDraw "uint32_t" --- Number of draw calls submitted.
.numCompute "uint32_t" --- Number of compute calls submitted.
.numBlit "uint32_t" --- Number of blit calls submitted.
+ .numBlitRepack "uint32_t" --- Number of buffer to texture blit calls that had to be repacked,
+ --- because `BufferRegion::rowPitch` or `offset` didn't match
+ --- `Caps::Limits::blitRowPitchAlign` or `blitOffsetAlign`.
.numDrawCallsPeak "uint32_t" --- Highest number of draw+compute calls requested in a single
--- frame so far (peak demand, before any were dropped). Useful
--- to tune `Init::Limits::numDrawCalls`.
@@ -1188,6 +1282,17 @@ handle "UniformHandle"
handle "VertexBufferHandle"
handle "VertexLayoutHandle"
+--- Tagged buffer handle. All buffer handle types implicitly convert to it, and the tag
+--- keeps track of which type the handle originally was.
+handle "BufferHandle"
+ { tagged = {
+ "DynamicIndexBufferHandle",
+ "DynamicVertexBufferHandle",
+ "IndexBufferHandle",
+ "IndirectBufferHandle",
+ "VertexBufferHandle",
+ } }
+
--- Start VertexLayout.
func.VertexLayout.begin
"VertexLayout&" --- Returns itself.
@@ -1530,6 +1635,25 @@ func.createIndexBuffer { section = "Index Buffers" }
--- - `BGFX_BUFFER_INDEX32` - Buffer is using 32-bit indices. This flag has effect only on
--- index buffers.
+--- Read back contents of buffer.
+---
+--- @remarks
+--- Read back is asynchronous, and the result is available at the returned frame.
+--- A zero `size` reads the rest of the buffer. `rowPitch` and `slicePitch` are
+--- unused.
+---
+--- Read back is intended for reading GPU written (compute, or draw indirect) buffers
+--- back to the CPU. It's not intended to be used in the main render loop, since it
+--- stalls the GPU.
+---
+--- @attention Buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+--- `BGFX_BUFFER_DRAW_INDIRECT` flags.
+---
+func.read { cname = "read_buffer", section = "Compute/Buffers" }
+ "uint32_t" --- Frame number when the result will be available. See: `bgfx::frame`.
+ .src "const BufferRegion &" --- Source buffer region.
+ .data "void*" --- Destination buffer.
+
--- Set static index buffer debug name.
func.setName { cname = "set_index_buffer_name", section = "Index Buffers" }
"void"
@@ -2034,19 +2158,23 @@ func.clear { cname = "clear_texture", section = "Textures" }
--- Read back texture content.
---
+--- @remarks
+--- Read back is asynchronous, and the result is available at the returned frame.
+--- `TextureRegion::z` selects cube face, 3D slice, or array layer. The region must
+--- cover the whole mip.
+---
+--- Read back is not intended to be used in the main render loop, since it stalls
+--- the GPU.
+---
--- @attention Texture must be created with `BGFX_TEXTURE_READ_BACK` flag.
--- It's a texture for CPU readback, and can't be a GPU resource
--- at the same time. See `examples/30-picking`.
--- @attention Availability depends on: `BGFX_CAPS_TEXTURE_READ_BACK`.
---
-func.readTexture { section = "Textures" }
- "uint32_t" --- Frame number when the result will be available. See: `bgfx::frame`.
- .handle "TextureHandle" --- Texture handle.
- .data "void*" --- Destination buffer.
- .layer "uint16_t" --- Texture layer.
- { default = 0 }
- .mip "uint8_t" --- Mip level.
- { default = 0 }
+func.read { cname = "read_texture", section = "Textures" }
+ "uint32_t" --- Frame number when the result will be available. See: `bgfx::frame`.
+ .src "const TextureRegion &" --- Source texture region.
+ .data "void*" --- Destination buffer.
--- Set texture debug name.
func.setName { cname = "set_texture_name", section = "Debug" }
@@ -2961,60 +3089,90 @@ func.Encoder.discard { section = "Miscellaneous" }
.flags "uint8_t" --- Discard or preserve states. See `BGFX_DISCARD_*`.
{ default = "BGFX_DISCARD_ALL" }
---- Blit 2D texture region between two 2D textures.
+--- Blit texture region between two textures.
---
---- @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
---- @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+--- @remarks
+--- The copy covers the region the two sides have in common: each side gives
+--- the origin it starts at, and the size is the smaller of the two extents.
+--- A zero `width`, `height` or `depth` extends to the rest of that mip.
---
-func.Encoder.blit { cpponly, section = "Blit" }
- "void"
- .id "ViewId" --- View id.
- .dst "TextureHandle" --- Destination texture handle.
- .dstX "uint16_t" --- Destination texture X position.
- .dstY "uint16_t" --- Destination texture Y position.
- .src "TextureHandle" --- Source texture handle.
- .srcX "uint16_t" --- Source texture X position.
- { default = 0 }
- .srcY "uint16_t" --- Source texture Y position.
- { default = 0 }
- .width "uint16_t" --- Width of region.
- { default = UINT16_MAX }
- .height "uint16_t" --- Height of region.
- { default = UINT16_MAX }
-
---- Blit 2D texture region between two 2D textures.
+--- Blit is performed on GPU, and it is ordered within the view. In views, all
+--- draw commands are executed after blit and compute commands.
---
--- @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
--- @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
---
func.Encoder.blit { section = "Blit" }
"void"
- .id "ViewId" --- View id.
- .dst "TextureHandle" --- Destination texture handle.
- .dstMip "uint8_t" --- Destination texture mip level.
- .dstX "uint16_t" --- Destination texture X position.
- .dstY "uint16_t" --- Destination texture Y position.
- .dstZ "uint16_t" --- If texture is 2D this argument should be 0. If destination texture is cube
- --- this argument represents destination texture cube face. For 3D texture this argument
- --- represents destination texture Z position.
- .src "TextureHandle" --- Source texture handle.
- .srcMip "uint8_t" --- Source texture mip level.
- { default = 0 }
- .srcX "uint16_t" --- Source texture X position.
- { default = 0 }
- .srcY "uint16_t" --- Source texture Y position.
- { default = 0 }
- .srcZ "uint16_t" --- If texture is 2D this argument should be 0. If source texture is cube
- --- this argument represents source texture cube face. For 3D texture this argument
- --- represents source texture Z position.
- { default = 0 }
- .width "uint16_t" --- Width of region.
- { default = UINT16_MAX }
- .height "uint16_t" --- Height of region.
- { default = UINT16_MAX }
- .depth "uint16_t" --- If texture is 3D this argument represents depth of region, otherwise it's
- --- unused.
- { default = UINT16_MAX }
+ .id "ViewId" --- View id.
+ .dst "const TextureRegion &" --- Destination texture region.
+ .src "const TextureRegion &" --- Source texture region.
+
+--- Blit buffer region between two buffers.
+---
+--- @remarks
+--- The source region gives the number of bytes copied, and the destination
+--- region gives only the offset they land at. A zero `size` copies the rest of
+--- the source buffer. `rowPitch` and `slicePitch` are unused.
+---
+--- Buffer blit is performed on GPU, and it is ordered within the view, same as
+--- texture blit. In views, all draw commands are executed after blit and compute
+--- commands.
+---
+--- @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+--- `BGFX_BUFFER_DRAW_INDIRECT` flags.
+--- @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+--- `BGFX_BUFFER_DRAW_INDIRECT` flag.
+--- @attention Source and destination buffer must be different.
+---
+func.Encoder.blit { cname = "blit_buffer", section = "Blit" }
+ "void"
+ .id "ViewId" --- View id.
+ .dst "const BufferRegion &" --- Destination buffer region.
+ .src "const BufferRegion &" --- Source buffer region.
+
+--- Blit texture region into buffer.
+---
+--- @remarks
+--- The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+--- `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+--- them tightly. `BufferRegion::init` fills in the layout the backend copies
+--- fastest, and bgfx repacks internally for any other layout.
+---
+--- Blit is performed on GPU, and it is ordered within the view, same as texture
+--- blit. In views, all draw commands are executed after blit and compute commands.
+---
+--- @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+--- `BGFX_BUFFER_DRAW_INDIRECT` flag.
+--- @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+---
+func.Encoder.blit { cname = "blit_to_buffer", section = "Blit" }
+ "void"
+ .id "ViewId" --- View id.
+ .dst "const BufferRegion &" --- Destination buffer region.
+ .src "const TextureRegion &" --- Source texture region.
+
+--- Blit buffer contents into texture region.
+---
+--- @remarks
+--- The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+--- `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+--- them tightly packed. `BufferRegion::init` fills in the layout the backend
+--- copies fastest, and bgfx repacks internally for any other layout.
+---
+--- Blit is performed on GPU, and it is ordered within the view, same as texture
+--- blit. In views, all draw commands are executed after blit and compute commands.
+---
+--- @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+--- `BGFX_BUFFER_DRAW_INDIRECT` flags.
+--- @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+--- @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+---
+func.Encoder.blit { cname = "blit_from_buffer", section = "Blit" }
+ "void"
+ .id "ViewId" --- View id.
+ .dst "const TextureRegion &" --- Destination texture region.
+ .src "const BufferRegion &" --- Source buffer region.
--- Request screen shot of window back buffer.
---
@@ -3593,60 +3751,90 @@ func.discard { section = "Miscellaneous" }
.flags "uint8_t" --- Draw/compute states to discard.
{ default = "BGFX_DISCARD_ALL" }
---- Blit 2D texture region between two 2D textures.
+--- Blit texture region between two textures.
---
---- @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
---- @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+--- @remarks
+--- The copy covers the region the two sides have in common: each side gives
+--- the origin it starts at, and the size is the smaller of the two extents.
+--- A zero `width`, `height` or `depth` extends to the rest of that mip.
---
-func.blit { cpponly, section = "Blit" }
- "void"
- .id "ViewId" --- View id.
- .dst "TextureHandle" --- Destination texture handle.
- .dstX "uint16_t" --- Destination texture X position.
- .dstY "uint16_t" --- Destination texture Y position.
- .src "TextureHandle" --- Source texture handle.
- .srcX "uint16_t" --- Source texture X position.
- { default = 0 }
- .srcY "uint16_t" --- Source texture Y position.
- { default = 0 }
- .width "uint16_t" --- Width of region.
- { default = UINT16_MAX }
- .height "uint16_t" --- Height of region.
- { default = UINT16_MAX }
-
---- Blit 2D texture region between two 2D textures.
+--- Blit is performed on GPU, and it is ordered within the view. In views, all
+--- draw commands are executed after blit and compute commands.
---
--- @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
--- @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
---
func.blit { section = "Blit" }
"void"
- .id "ViewId" --- View id.
- .dst "TextureHandle" --- Destination texture handle.
- .dstMip "uint8_t" --- Destination texture mip level.
- .dstX "uint16_t" --- Destination texture X position.
- .dstY "uint16_t" --- Destination texture Y position.
- .dstZ "uint16_t" --- If texture is 2D this argument should be 0. If destination texture is cube
- --- this argument represents destination texture cube face. For 3D texture this argument
- --- represents destination texture Z position.
- .src "TextureHandle" --- Source texture handle.
- .srcMip "uint8_t" --- Source texture mip level.
- { default = 0 }
- .srcX "uint16_t" --- Source texture X position.
- { default = 0 }
- .srcY "uint16_t" --- Source texture Y position.
- { default = 0 }
- .srcZ "uint16_t" --- If texture is 2D this argument should be 0. If source texture is cube
- --- this argument represents source texture cube face. For 3D texture this argument
- --- represents source texture Z position.
- { default = 0 }
- .width "uint16_t" --- Width of region.
- { default = UINT16_MAX }
- .height "uint16_t" --- Height of region.
- { default = UINT16_MAX }
- .depth "uint16_t" --- If texture is 3D this argument represents depth of region, otherwise it's
- --- unused.
- { default = UINT16_MAX }
+ .id "ViewId" --- View id.
+ .dst "const TextureRegion &" --- Destination texture region.
+ .src "const TextureRegion &" --- Source texture region.
+
+--- Blit buffer region between two buffers.
+---
+--- @remarks
+--- The source region gives the number of bytes copied, and the destination
+--- region gives only the offset they land at. A zero `size` copies the rest of
+--- the source buffer. `rowPitch` and `slicePitch` are unused.
+---
+--- Buffer blit is performed on GPU, and it is ordered within the view, same as
+--- texture blit. In views, all draw commands are executed after blit and compute
+--- commands.
+---
+--- @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+--- `BGFX_BUFFER_DRAW_INDIRECT` flags.
+--- @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+--- `BGFX_BUFFER_DRAW_INDIRECT` flag.
+--- @attention Source and destination buffer must be different.
+---
+func.blit { cname = "blit_buffer", section = "Blit" }
+ "void"
+ .id "ViewId" --- View id.
+ .dst "const BufferRegion &" --- Destination buffer region.
+ .src "const BufferRegion &" --- Source buffer region.
+
+--- Blit texture region into buffer.
+---
+--- @remarks
+--- The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+--- `slicePitch` choose how the texels are laid out in the buffer, and 0 packs
+--- them tightly. `BufferRegion::init` fills in the layout the backend copies
+--- fastest, and bgfx repacks internally for any other layout.
+---
+--- Blit is performed on GPU, and it is ordered within the view, same as texture
+--- blit. In views, all draw commands are executed after blit and compute commands.
+---
+--- @attention Destination buffer must be created with `BGFX_BUFFER_COMPUTE_WRITE`, or
+--- `BGFX_BUFFER_DRAW_INDIRECT` flag.
+--- @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+---
+func.blit { cname = "blit_to_buffer", section = "Blit" }
+ "void"
+ .id "ViewId" --- View id.
+ .dst "const BufferRegion &" --- Destination buffer region.
+ .src "const TextureRegion &" --- Source texture region.
+
+--- Blit buffer contents into texture region.
+---
+--- @remarks
+--- The texture region gives the size of the copy. `BufferRegion::rowPitch` and
+--- `slicePitch` describe how the texels are laid out in the buffer, and 0 reads
+--- them tightly packed. `BufferRegion::init` fills in the layout the backend
+--- copies fastest, and bgfx repacks internally for any other layout.
+---
+--- Blit is performed on GPU, and it is ordered within the view, same as texture
+--- blit. In views, all draw commands are executed after blit and compute commands.
+---
+--- @attention Source buffer must be created with one of `BGFX_BUFFER_COMPUTE_*`, or
+--- `BGFX_BUFFER_DRAW_INDIRECT` flags.
+--- @attention Destination texture must be created with `BGFX_TEXTURE_BLIT_DST` flag.
+--- @attention Availability depends on: `BGFX_CAPS_TEXTURE_BLIT`.
+---
+func.blit { cname = "blit_from_buffer", section = "Blit" }
+ "void"
+ .id "ViewId" --- View id.
+ .dst "const TextureRegion &" --- Destination texture region.
+ .src "const BufferRegion &" --- Source buffer region.
--------------------------------------------------------------------------------
-- Documentation sections for RST generation
diff --git a/scripts/bindings-bf.lua b/scripts/bindings-bf.lua
index 54e9fa319..69a069d61 100644
--- a/scripts/bindings-bf.lua
+++ b/scripts/bindings-bf.lua
@@ -46,29 +46,33 @@ local function hasSuffix(str, suffix)
return suffix == "" or str:sub(-#suffix) == suffix
end
+local function hasTypePrefix(ctype, prefix)
+ return hasPrefix( (ctype:gsub("^const%s+", "") ), prefix)
+end
+
local function convert_type_0(arg)
- if hasPrefix(arg.ctype, "uint64_t") then
+ if hasTypePrefix(arg.ctype, "uint64_t") then
return arg.ctype:gsub("uint64_t", "uint64")
- elseif hasPrefix(arg.ctype, "int64_t") then
+ elseif hasTypePrefix(arg.ctype, "int64_t") then
return arg.ctype:gsub("int64_t", "int64")
- elseif hasPrefix(arg.ctype, "uint32_t") then
+ elseif hasTypePrefix(arg.ctype, "uint32_t") then
return arg.ctype:gsub("uint32_t", "uint32")
- elseif hasPrefix(arg.ctype, "int32_t") then
+ elseif hasTypePrefix(arg.ctype, "int32_t") then
return arg.ctype:gsub("int32_t", "int32")
- elseif hasPrefix(arg.ctype, "uint16_t") then
+ elseif hasTypePrefix(arg.ctype, "uint16_t") then
return arg.ctype:gsub("uint16_t", "uint16")
- elseif hasPrefix(arg.ctype, "int16_t") then
+ elseif hasTypePrefix(arg.ctype, "int16_t") then
return arg.ctype:gsub("int16_t", "int16")
- elseif hasPrefix(arg.ctype, "uint8_t") then
+ elseif hasTypePrefix(arg.ctype, "uint8_t") then
return arg.ctype:gsub("uint8_t", "uint8")
- elseif hasPrefix(arg.ctype, "uintptr_t") then
+ elseif hasTypePrefix(arg.ctype, "uintptr_t") then
return arg.ctype:gsub("uintptr_t", "void*")
elseif arg.ctype == "const char*" then
return "char8*"
- elseif hasPrefix(arg.ctype, "char") then
+ elseif hasTypePrefix(arg.ctype, "char") then
return arg.ctype:gsub("char", "char8")
- elseif hasPrefix(arg.ctype, "byte") then
+ elseif hasTypePrefix(arg.ctype, "byte") then
return arg.ctype:gsub("byte", "uint8")
elseif arg.ctype == "va_list"
or arg.fulltype == "bx::AllocatorI*"
@@ -91,7 +95,7 @@ end
local function convert_struct_type(arg)
local ctype = convert_type(arg)
- if hasPrefix(arg.ctype, "bool") then
+ if hasTypePrefix(arg.ctype, "bool") then
ctype = ctype:gsub("bool", "uint8")
end
return ctype
@@ -238,6 +242,9 @@ function converter.types(typ)
yield("[CRepr]")
yield("public struct " .. typ.name .. " {")
yield(" public uint16 idx;")
+ if typ.tagged then
+ yield(" public uint16 type;")
+ end
yield(" public bool Valid => idx != uint16.MaxValue;")
yield("}")
elseif hasSuffix(typ.name, "::Enum") then
diff --git a/scripts/bindings-c3.lua b/scripts/bindings-c3.lua
index 790a5e031..281e63595 100644
--- a/scripts/bindings-c3.lua
+++ b/scripts/bindings-c3.lua
@@ -26,25 +26,29 @@ local function hasSuffix(str, suffix)
return suffix == "" or str:sub(-#suffix) == suffix
end
+local function hasTypePrefix(ctype, prefix)
+ return hasPrefix( (ctype:gsub("^const%s+", "") ), prefix)
+end
+
local function convert_type_0(arg)
- if hasPrefix(arg.ctype, "uint64_t") then
+ if hasTypePrefix(arg.ctype, "uint64_t") then
return arg.ctype:gsub("uint64_t", "ulong")
- elseif hasPrefix(arg.ctype, "int64_t") then
+ elseif hasTypePrefix(arg.ctype, "int64_t") then
return arg.ctype:gsub("int64_t", "long")
- elseif hasPrefix(arg.ctype, "uint32_t") then
+ elseif hasTypePrefix(arg.ctype, "uint32_t") then
return arg.ctype:gsub("uint32_t", "uint")
- elseif hasPrefix(arg.ctype, "int32_t") then
+ elseif hasTypePrefix(arg.ctype, "int32_t") then
return arg.ctype:gsub("int32_t", "int")
- elseif hasPrefix(arg.ctype, "uint16_t") then
+ elseif hasTypePrefix(arg.ctype, "uint16_t") then
return arg.ctype:gsub("uint16_t", "ushort")
- elseif hasPrefix(arg.ctype, "int16_t") then
+ elseif hasTypePrefix(arg.ctype, "int16_t") then
return arg.ctype:gsub("int16_t", "short")
- elseif hasPrefix(arg.ctype, "bgfx_view_id_t") then
+ elseif hasTypePrefix(arg.ctype, "bgfx_view_id_t") then
return arg.ctype:gsub("bgfx_view_id_t", "ushort")
- elseif hasPrefix(arg.ctype, "uint8_t") then
+ elseif hasTypePrefix(arg.ctype, "uint8_t") then
return arg.ctype:gsub("uint8_t", "char")
- elseif hasPrefix(arg.ctype, "uintptr_t") then
+ elseif hasTypePrefix(arg.ctype, "uintptr_t") then
return arg.ctype:gsub("uintptr_t", "uptr")
elseif arg.ctype == "bgfx_caps_gpu_t" then
return arg.ctype:gsub("bgfx_caps_gpu_t", "uint")
@@ -213,6 +217,9 @@ function converter.types(typ)
yield("struct " .. typ.name .. " {")
yield(" ushort idx;")
+ if typ.tagged then
+ yield(" ushort type;")
+ end
yield("}")
elseif hasSuffix(typ.name, "::Enum") then
lastCombinedFlagBlock()
diff --git a/scripts/bindings-cs.lua b/scripts/bindings-cs.lua
index 4bee421cf..116d8ca2b 100644
--- a/scripts/bindings-cs.lua
+++ b/scripts/bindings-cs.lua
@@ -64,25 +64,29 @@ local function hasSuffix(str, suffix)
return suffix == "" or str:sub(-#suffix) == suffix
end
+local function hasTypePrefix(ctype, prefix)
+ return hasPrefix( (ctype:gsub("^const%s+", "") ), prefix)
+end
+
local function convert_type_0(arg)
- if hasPrefix(arg.ctype, "uint64_t") then
+ if hasTypePrefix(arg.ctype, "uint64_t") then
return arg.ctype:gsub("uint64_t", "ulong")
- elseif hasPrefix(arg.ctype, "int64_t") then
+ elseif hasTypePrefix(arg.ctype, "int64_t") then
return arg.ctype:gsub("int64_t", "long")
- elseif hasPrefix(arg.ctype, "uint32_t") then
+ elseif hasTypePrefix(arg.ctype, "uint32_t") then
return arg.ctype:gsub("uint32_t", "uint")
- elseif hasPrefix(arg.ctype, "int32_t") then
+ elseif hasTypePrefix(arg.ctype, "int32_t") then
return arg.ctype:gsub("int32_t", "int")
- elseif hasPrefix(arg.ctype, "uint16_t") then
+ elseif hasTypePrefix(arg.ctype, "uint16_t") then
return arg.ctype:gsub("uint16_t", "ushort")
- elseif hasPrefix(arg.ctype, "int16_t") then
+ elseif hasTypePrefix(arg.ctype, "int16_t") then
return arg.ctype:gsub("int16_t", "short")
- elseif hasPrefix(arg.ctype, "bgfx_view_id_t") then
+ elseif hasTypePrefix(arg.ctype, "bgfx_view_id_t") then
return arg.ctype:gsub("bgfx_view_id_t", "ushort")
- elseif hasPrefix(arg.ctype, "uint8_t") then
+ elseif hasTypePrefix(arg.ctype, "uint8_t") then
return arg.ctype:gsub("uint8_t", "byte")
- elseif hasPrefix(arg.ctype, "uintptr_t") then
+ elseif hasTypePrefix(arg.ctype, "uintptr_t") then
return arg.ctype:gsub("uintptr_t", "UIntPtr")
elseif arg.ctype == "bgfx_caps_gpu_t" then
return arg.ctype:gsub("bgfx_caps_gpu_t", "uint")
@@ -117,7 +121,7 @@ end
local function convert_struct_type(arg)
local ctype = convert_type(arg)
- if hasPrefix(arg.ctype, "bool") then
+ if hasTypePrefix(arg.ctype, "bool") then
ctype = ctype:gsub("bool", "byte")
end
return ctype
@@ -271,6 +275,9 @@ function converter.types(typ)
yield("public struct " .. typ.name .. " {")
yield(" public ushort idx;")
+ if typ.tagged then
+ yield(" public ushort type;")
+ end
yield(" public bool Valid => idx != UInt16.MaxValue;")
yield("}")
elseif hasSuffix(typ.name, "::Enum") then
diff --git a/scripts/bindings-d.lua b/scripts/bindings-d.lua
index 8ec28a9d1..5fa800684 100644
--- a/scripts/bindings-d.lua
+++ b/scripts/bindings-d.lua
@@ -599,6 +599,9 @@ function converter.types(typ)
if typ.handle then ---hnadle
yield("extern(C++, \"bgfx\") struct " .. typ.name .. "{")
yield("\tushort idx;")
+ if typ.tagged then
+ yield("\tushort type;")
+ end
yield("}")
--yield(typ.name .. " invalidHandle(){ return " .. typ.name .. "(ushort.max); }")
diff --git a/scripts/bindings-py.lua b/scripts/bindings-py.lua
index 87e6ae5fb..953332a1a 100644
--- a/scripts/bindings-py.lua
+++ b/scripts/bindings-py.lua
@@ -421,7 +421,9 @@ local function gen_struct_declarations(out, comments)
if typ.handle then
append(out,
"class " .. python_type_name(typ) .. "(ctypes.Structure):",
- "\t_fields_ = [(\"idx\", ctypes.c_uint16)]",
+ typ.tagged
+ and "\t_fields_ = [(\"idx\", ctypes.c_uint16), (\"type\", ctypes.c_uint16)]"
+ or "\t_fields_ = [(\"idx\", ctypes.c_uint16)]",
"",
"\t@property",
"\tdef valid(self):",
@@ -485,7 +487,14 @@ local function gen_stub_structs(out)
if typ.handle then
append(out,
"class " .. python_type_name(typ) .. "(ctypes.Structure):",
- "\tidx: int",
+ "\tidx: int"
+ )
+
+ if typ.tagged then
+ append(out, "\ttype: int")
+ end
+
+ append(out,
"",
"\t@property",
"\tdef valid(self) -> bool: ...",
diff --git a/scripts/bindings-zig.lua b/scripts/bindings-zig.lua
index ad59c54f7..e7dba8594 100644
--- a/scripts/bindings-zig.lua
+++ b/scripts/bindings-zig.lua
@@ -288,6 +288,9 @@ function converter.types(params)
yield("pub const " .. typ.name .. " = extern struct {")
yield(" idx: c_ushort,")
+ if typ.tagged then
+ yield(" type: c_ushort,")
+ end
yield("};")
elseif hasSuffix(typ.name, "::Enum") then
lastCombinedFlagBlock()
diff --git a/scripts/codegen.lua b/scripts/codegen.lua
index 91bae2110..edcae5033 100644
--- a/scripts/codegen.lua
+++ b/scripts/codegen.lua
@@ -958,7 +958,11 @@ local function text_with_comments(items, item, cstyle, is_classmember, name_alig
if is_classmember then
name = "m_" .. name
end
- local text = string.format("%s%s %s;", typename, namealign(typename, name_align or DEFAULT_NAME_ALIGN), name)
+ local default = ""
+ if not cstyle and item.default ~= nil then
+ default = " = " .. tostring(item.default)
+ end
+ local text = string.format("%s%s %s%s;", typename, namealign(typename, name_align or DEFAULT_NAME_ALIGN), name, default)
if item.comment then
if #item.comment > 1 then
if cstyle then
@@ -1016,6 +1020,9 @@ function codegen.gen_struct_define(struct, methods)
name = "m_" .. name
end
local text_len = #item.fulltype + 1 + #name + 1
+ if item.default ~= nil then
+ text_len = text_len + 3 + #tostring(item.default)
+ end
if text_len > max_text_len then
max_text_len = text_len
end
@@ -1095,15 +1102,138 @@ end
local chandle_temp = [[
typedef struct $NAME_s { uint16_t idx; } $NAME_t;
]]
+
+local tagged_chandle_temp = [[
+typedef struct $NAME_s { uint16_t idx; uint16_t type; } $NAME_t;
+
+typedef enum $NAME_type
+{
+$CENUMS
+ $UPPERNAME_TYPE_COUNT
+
+} $NAME_type_t;
+
+$CCONVERTERS
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#define $UPPERNAME(_handle) _Generic( (_handle)$CGENERIC \
+ )(_handle)
+#endif // defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+]]
+
+local cconverter_temp = [[
+static inline $NAME_t $CONVERTER($TAGGEDCNAME _handle)
+{
+ $NAME_t handle;
+ handle.idx = _handle.idx;
+ handle.type = $CTAG;
+ return handle;
+}
+]]
+
function codegen.gen_chandle(handle)
assert(handle.handle, "Not a handle")
- return (chandle_temp:gsub("$(%u+)", { NAME = handle.cname:match "(.-)_t$" }))
+
+ local name = handle.cname:match "(.-)_t$"
+
+ if not handle.tagged then
+ return (chandle_temp:gsub("$(%u+)", { NAME = name }))
+ end
+
+ local base = camelcase_to_underscorecase(assert(handle.name:match "(.-)Handle$"
+ , "Tagged handle name must end with `Handle`") )
+
+ local enums = {}
+ local converters = {}
+ local generic = {}
+ local align = 0
+
+ for _, taggedName in ipairs(handle.tagged) do
+ align = math.max(align, #camelcase_to_underscorecase(taggedName) + 7)
+ end
+
+ for _, taggedName in ipairs(handle.tagged) do
+ local tag = assert(taggedName:match "(.-)Handle$", "Tagged handle type must be a handle")
+ local ctag = name:upper() .. "_TYPE_" .. camelcase_to_underscorecase(tag):upper()
+ local converter = "bgfx_" .. base .. "_from_" .. camelcase_to_underscorecase(tag)
+ local ctagged = "bgfx_" .. camelcase_to_underscorecase(taggedName) .. "_t"
+
+ enums[#enums+1] = "\t" .. ctag .. ","
+ converters[#converters+1] = (cconverter_temp:gsub("$(%u+)", {
+ NAME = name,
+ CONVERTER = converter,
+ TAGGEDCNAME = ctagged,
+ CTAG = ctag,
+ }))
+ generic[#generic+1] = "\t, " .. ctagged .. string.rep(" ", align - #ctagged) .. ": " .. converter
+ end
+
+ return (tagged_chandle_temp:gsub("$(%u+)", {
+ NAME = name,
+ UPPERNAME = name:upper(),
+ CENUMS = table.concat(enums, "\n") .. "\n",
+ CCONVERTERS = table.concat(converters, "\n"),
+ CGENERIC = " \\\n" .. table.concat(generic, " \\\n"),
+ }))
end
local handle_temp = "BGFX_HANDLE($NAME)"
+
+local tagged_handle_temp = [[
+
+struct $NAME
+{
+ enum Enum
+ {
+$ENUMS
+ Count
+ };
+
+ $NAME()
+ : idx(kInvalidHandle)
+ , type(Count)
+ {
+ }
+
+$CTORS
+ uint16_t idx;
+ uint16_t type;
+};
+
+inline bool isValid($NAME _handle) { return bgfx::kInvalidHandle != _handle.idx; }]]
+
+local tagged_ctor_temp = [[
+ $NAME($TAGGEDNAME _handle)
+ : idx(_handle.idx)
+ , type($TAG)
+ {
+ }
+]]
+
function codegen.gen_handle(handle)
assert(handle.handle, "Not a handle")
- return (handle_temp:gsub("$(%u+)", { NAME = handle.name }))
+
+ if not handle.tagged then
+ return (handle_temp:gsub("$(%u+)", { NAME = handle.name }))
+ end
+
+ local enums = {}
+ local ctors = {}
+
+ for _, name in ipairs(handle.tagged) do
+ local tag = assert(name:match "(.-)Handle$", "Tagged handle type must be a handle")
+ enums[#enums+1] = "\t\t" .. tag .. ","
+ ctors[#ctors+1] = (tagged_ctor_temp:gsub("$(%u+)", {
+ NAME = handle.name,
+ TAGGEDNAME = name,
+ TAG = tag,
+ }))
+ end
+
+ return (tagged_handle_temp:gsub("$(%u+)", {
+ NAME = handle.name,
+ ENUMS = table.concat(enums, "\n") .. "\n",
+ CTORS = table.concat(ctors, "\n"),
+ }))
end
local idl = require "idl"
diff --git a/src/bgfx.cpp b/src/bgfx.cpp
index bad2976ab..b9a483d14 100644
--- a/src/bgfx.cpp
+++ b/src/bgfx.cpp
@@ -1659,7 +1659,7 @@ namespace bgfx
m_uniformBegin = m_uniformEnd;
}
- void EncoderImpl::blit(ViewId _id, TextureHandle _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, TextureHandle _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth)
+ void EncoderImpl::blit(ViewId _id, const BlitItem& _blit)
{
const uint32_t blitItemIdx = bx::atomicFetchAndAddsat(&m_frame->m_numBlitItems, 1, BGFX_CONFIG_MAX_BLIT_ITEMS);
@@ -1674,20 +1674,8 @@ namespace bgfx
}
BlitItem& bi = m_frame->m_blitItem[blitItemIdx];
- bi.m_srcX = _srcX;
- bi.m_srcY = _srcY;
- bi.m_srcZ = _srcZ;
- bi.m_dstX = _dstX;
- bi.m_dstY = _dstY;
- bi.m_dstZ = _dstZ;
- bi.m_width = _width;
- bi.m_height = _height;
- bi.m_depth = _depth;
- bi.m_srcMip = _srcMip;
- bi.m_dstMip = _dstMip;
- bi.m_src = _src;
- bi.m_dst = _dst;
- bi.m_view = _id;
+ bi = _blit;
+ bi.m_view = _id;
}
void Frame::sort()
@@ -2058,6 +2046,8 @@ namespace bgfx
LIMITS(maxTransientVbSize);
LIMITS(maxTransientIbSize);
LIMITS(minUniformBufferSize);
+ LIMITS(blitRowPitchAlign);
+ LIMITS(blitOffsetAlign);
#undef LIMITS
BX_TRACE("");
@@ -3798,6 +3788,26 @@ namespace bgfx
}
break;
+ case CommandBuffer::ReadBuffer:
+ {
+ BGFX_PROFILER_SCOPE("ReadBuffer", kColorResource);
+
+ Handle handle;
+ _cmdbuf.read(handle);
+
+ void* data;
+ _cmdbuf.read(data);
+
+ uint32_t offset;
+ _cmdbuf.read(offset);
+
+ uint32_t size;
+ _cmdbuf.read(size);
+
+ m_renderCtx->readBuffer(handle, data, offset, size);
+ }
+ break;
+
case CommandBuffer::ResizeTexture:
{
BGFX_PROFILER_SCOPE("ResizeTexture", kColorResource);
@@ -4155,6 +4165,8 @@ namespace bgfx
g_caps.limits.maxTransientVbSize = init.limits.maxTransientVbSize;
g_caps.limits.maxTransientIbSize = init.limits.maxTransientIbSize;
g_caps.limits.minUniformBufferSize = init.limits.minUniformBufferSize;
+ g_caps.limits.blitRowPitchAlign = 1;
+ g_caps.limits.blitOffsetAlign = 1;
g_caps.vendorId = init.vendorId;
g_caps.deviceId = init.deviceId;
@@ -4629,23 +4641,162 @@ namespace bgfx
BGFX_ENCODER(discard(_flags) );
}
- void Encoder::blit(ViewId _id, TextureHandle _dst, uint16_t _dstX, uint16_t _dstY, TextureHandle _src, uint16_t _srcX, uint16_t _srcY, uint16_t _width, uint16_t _height)
+ static void getTextureRegionDims(uint32_t& _width, uint32_t& _height, uint32_t& _depth, const TextureRef& _ref, uint8_t _mip)
{
- blit(_id, _dst, 0, _dstX, _dstY, 0, _src, 0, _srcX, _srcY, 0, _width, _height, 0);
+ _width = bx::max(1, _ref.m_width >> _mip);
+ _height = bx::max(1, _ref.m_height >> _mip);
+ _depth = _ref.isCubeMap()
+ ? 6 * _ref.m_numLayers
+ : _ref.m_numLayers > 1
+ ? _ref.m_numLayers
+ : bx::max(1, _ref.m_depth >> _mip)
+ ;
}
- void Encoder::blit(ViewId _id, TextureHandle _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, TextureHandle _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth)
+ static void alignTextureRegion(uint16_t& _width, uint16_t& _height, TextureFormat::Enum _format)
+ {
+ if (bimg::isCompressed(bimg::TextureFormat::Enum(_format) ) )
+ {
+ const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_format) );
+ const uint32_t blockW = bx::max(1, blockInfo.blockWidth);
+ const uint32_t blockH = bx::max(1, blockInfo.blockHeight);
+ _width = uint16_t( (uint32_t(_width + blockW - 1) / blockW) * blockW);
+ _height = uint16_t( (uint32_t(_height + blockH - 1) / blockH) * blockH);
+ }
+ }
+
+ static uint32_t clampRegionExtent(uint32_t _dim, uint16_t _origin, uint16_t _extent)
+ {
+ return 0 == _extent
+ ? _dim - _origin
+ : bx::min(_dim, _origin + _extent) - _origin
+ ;
+ }
+
+ struct BufferLayout
+ {
+ uint32_t m_rowPitch;
+ uint32_t m_slicePitch;
+ uint32_t m_size;
+ };
+
+ static BufferLayout resolveBufferLayout(const BufferRegion& _region, TextureFormat::Enum _format, uint16_t _width, uint16_t _height, uint16_t _depth)
+ {
+ const uint32_t blockSize = bimg::getBlockInfo(bimg::TextureFormat::Enum(_format) ).blockSize;
+ const uint32_t tightPitch = calcTextureRegionPitch(_format, _width);
+ const uint32_t numRows = calcTextureRegionNumRows(_format, _height);
+ const uint32_t numSlices = bx::max(1, _depth);
+
+ BufferLayout layout;
+ layout.m_rowPitch = 0 == _region.rowPitch ? tightPitch : _region.rowPitch;
+ layout.m_slicePitch = 0 == _region.slicePitch ? layout.m_rowPitch*numRows : _region.slicePitch;
+ layout.m_size = layout.m_slicePitch*(numSlices - 1) + layout.m_rowPitch*numRows;
+
+ BX_ASSERT(layout.m_rowPitch >= tightPitch
+ , "Blit buffer row pitch is too small (%d < %d)."
+ , layout.m_rowPitch
+ , tightPitch
+ );
+ BX_ASSERT(0 == layout.m_rowPitch % blockSize
+ , "Blit buffer row pitch (%d) must be multiple of texture format block size (%d)."
+ , layout.m_rowPitch
+ , blockSize
+ );
+ BX_ASSERT(layout.m_slicePitch >= layout.m_rowPitch*numRows
+ , "Blit buffer slice pitch is too small (%d < %d)."
+ , layout.m_slicePitch
+ , layout.m_rowPitch*numRows
+ );
+ BX_ASSERT(0 == layout.m_slicePitch % layout.m_rowPitch
+ , "Blit buffer slice pitch (%d) must be multiple of row pitch (%d)."
+ , layout.m_slicePitch
+ , layout.m_rowPitch
+ );
+
+ return layout;
+ }
+
+ static void checkBufferLayout(Frame* _frame, uint32_t _offset, const BufferLayout& _layout)
+ {
+ const Caps::Limits& limits = g_caps.limits;
+
+ if (0 != _offset % limits.blitOffsetAlign
+ || 0 != _layout.m_rowPitch % limits.blitRowPitchAlign)
+ {
+ bx::atomicFetchAndAdd(&_frame->m_numBlitRepack, 1);
+
+ BX_WARN(false
+ , "Blit buffer layout (offset %d, row pitch %d) is repacked by the renderer. "
+ "Use `BufferRegion::init` to match `Caps::Limits::blitOffsetAlign` (%d), and `blitRowPitchAlign` (%d)."
+ , _offset
+ , _layout.m_rowPitch
+ , limits.blitOffsetAlign
+ , limits.blitRowPitchAlign
+ );
+ }
+ }
+
+ void TextureRegion::init(TextureHandle _handle, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
+ {
+ handle = _handle;
+ mip = 0;
+ x = _x;
+ y = _y;
+ z = 0;
+ width = _width;
+ height = _height;
+ depth = 0;
+ }
+
+ void BufferRegion::init(BufferHandle _handle, uint32_t _offset, uint32_t _size)
+ {
+ handle = _handle;
+ offset = _offset;
+ size = _size;
+ rowPitch = 0;
+ slicePitch = 0;
+ }
+
+ void BufferRegion::init(const TextureRegion& _texture)
+ {
+ BGFX_CHECK_HANDLE("BufferRegion::init TextureHandle", s_ctx->m_textureHandle, _texture.handle);
+
+ const TextureRef& ref = s_ctx->m_textureRef[_texture.handle.idx];
+ const TextureFormat::Enum format = TextureFormat::Enum(ref.m_format);
+
+ BX_ASSERT(_texture.mip < ref.m_numMips, "Invalid mip (%d > %d)", _texture.mip, ref.m_numMips - 1);
+
+ uint32_t regionWidth, regionHeight, regionDepth;
+ getTextureRegionDims(regionWidth, regionHeight, regionDepth, ref, _texture.mip);
+
+ uint16_t width = uint16_t(clampRegionExtent(regionWidth, _texture.x, _texture.width ) );
+ uint16_t height = uint16_t(clampRegionExtent(regionHeight, _texture.y, _texture.height) );
+
+ alignTextureRegion(width, height, format);
+
+ const Caps::Limits& limits = g_caps.limits;
+
+ const uint32_t numRows = calcTextureRegionNumRows(format, height);
+ const uint32_t numSlices = bx::max(1, clampRegionExtent(regionDepth, _texture.z, _texture.depth) );
+
+ rowPitch = bx::alignUp(calcTextureRegionPitch(format, width), limits.blitRowPitchAlign);
+ slicePitch = bx::alignUp(rowPitch*numRows, bx::lcm(rowPitch, limits.blitOffsetAlign) );
+ offset = bx::alignUp(offset, limits.blitOffsetAlign);
+ size = slicePitch*(numSlices - 1) + rowPitch*numRows;
+ }
+
+ void Encoder::blit(ViewId _id, const TextureRegion& _dst, const TextureRegion& _src)
{
BGFX_CHECK_CAPS(BGFX_CAPS_TEXTURE_BLIT, "Texture blit is not supported!");
- BGFX_CHECK_HANDLE("blit/src TextureHandle", s_ctx->m_textureHandle, _src);
- BGFX_CHECK_HANDLE("blit/dst TextureHandle", s_ctx->m_textureHandle, _dst);
+ BGFX_CHECK_HANDLE("blit/src TextureHandle", s_ctx->m_textureHandle, _src.handle);
+ BGFX_CHECK_HANDLE("blit/dst TextureHandle", s_ctx->m_textureHandle, _dst.handle);
- const TextureRef& src = s_ctx->m_textureRef[_src.idx];
- const TextureRef& dst = s_ctx->m_textureRef[_dst.idx];
+ const TextureRef& src = s_ctx->m_textureRef[_src.handle.idx];
+ const TextureRef& dst = s_ctx->m_textureRef[_dst.handle.idx];
BX_ASSERT(dst.isBlitDst()
, "Blit destination texture (handle %d, '%S') is not created with `BGFX_TEXTURE_BLIT_DST` flag."
- , _dst.idx
+ , _dst.handle.idx
, &dst.m_name
);
@@ -4654,49 +4805,278 @@ namespace bgfx
, bimg::getName(bimg::TextureFormat::Enum(src.m_format) )
, bimg::getName(bimg::TextureFormat::Enum(dst.m_format) )
);
- BX_ASSERT(_srcMip < src.m_numMips, "Invalid blit src mip (%d > %d)", _srcMip, src.m_numMips - 1);
- BX_ASSERT(_dstMip < dst.m_numMips, "Invalid blit dst mip (%d > %d)", _dstMip, dst.m_numMips - 1);
+ BX_ASSERT(_src.mip < src.m_numMips, "Invalid blit src mip (%d > %d)", _src.mip, src.m_numMips - 1);
+ BX_ASSERT(_dst.mip < dst.m_numMips, "Invalid blit dst mip (%d > %d)", _dst.mip, dst.m_numMips - 1);
- uint32_t srcWidth = bx::max(1, src.m_width >> _srcMip);
- uint32_t srcHeight = bx::max(1, src.m_height >> _srcMip);
- uint32_t dstWidth = bx::max(1, dst.m_width >> _dstMip);
- uint32_t dstHeight = bx::max(1, dst.m_height >> _dstMip);
+ uint32_t srcWidth, srcHeight, srcDepth;
+ getTextureRegionDims(srcWidth, srcHeight, srcDepth, src, _src.mip);
- uint32_t srcDepth = src.isCubeMap() ? 6 * src.m_numLayers : src.m_numLayers > 1 ? src.m_numLayers : bx::max(1, src.m_depth >> _srcMip);
- uint32_t dstDepth = dst.isCubeMap() ? 6 * dst.m_numLayers : dst.m_numLayers > 1 ? dst.m_numLayers : bx::max(1, dst.m_depth >> _dstMip);
+ uint32_t dstWidth, dstHeight, dstDepth;
+ getTextureRegionDims(dstWidth, dstHeight, dstDepth, dst, _dst.mip);
- BX_ASSERT(_srcX < srcWidth && _srcY < srcHeight && _srcZ < srcDepth
+ BX_ASSERT(_src.x < srcWidth && _src.y < srcHeight && _src.z < srcDepth
, "Blit src coordinates out of range (%d, %d, %d) >= (%d, %d, %d)"
- , _srcX, _srcY, _srcZ
+ , _src.x, _src.y, _src.z
, srcWidth, srcHeight, srcDepth
);
- BX_ASSERT(_dstX < dstWidth && _dstY < dstHeight && _dstZ < dstDepth
+ BX_ASSERT(_dst.x < dstWidth && _dst.y < dstHeight && _dst.z < dstDepth
, "Blit dst coordinates out of range (%d, %d, %d) >= (%d, %d, %d)"
- , _dstX, _dstY, _dstZ
+ , _dst.x, _dst.y, _dst.z
, dstWidth, dstHeight, dstDepth
);
- srcWidth = bx::min(srcWidth, _srcX + _width ) - _srcX;
- srcHeight = bx::min(srcHeight, _srcY + _height) - _srcY;
- srcDepth = bx::min(srcDepth, _srcZ + _depth ) - _srcZ;
- dstWidth = bx::min(dstWidth, _dstX + _width ) - _dstX;
- dstHeight = bx::min(dstHeight, _dstY + _height) - _dstY;
- dstDepth = bx::min(dstDepth, _dstZ + _depth ) - _dstZ;
+ srcWidth = clampRegionExtent(srcWidth, _src.x, _src.width );
+ srcHeight = clampRegionExtent(srcHeight, _src.y, _src.height);
+ srcDepth = clampRegionExtent(srcDepth, _src.z, _src.depth );
+ dstWidth = clampRegionExtent(dstWidth, _dst.x, _dst.width );
+ dstHeight = clampRegionExtent(dstHeight, _dst.y, _dst.height);
+ dstDepth = clampRegionExtent(dstDepth, _dst.z, _dst.depth );
uint16_t width = uint16_t(bx::min(srcWidth, dstWidth ) );
uint16_t height = uint16_t(bx::min(srcHeight, dstHeight) );
- const uint16_t depth = uint16_t(bx::min(srcDepth, dstDepth ) );
+ const uint16_t depth = uint16_t(bx::min(srcDepth, dstDepth) );
- if (bimg::isCompressed(bimg::TextureFormat::Enum(src.m_format) ) )
+ alignTextureRegion(width, height, TextureFormat::Enum(src.m_format) );
+
+ const BlitItem item =
{
- const bimg::ImageBlockInfo& bi = bimg::getBlockInfo(bimg::TextureFormat::Enum(src.m_format) );
- const uint32_t blockW = bx::max(1, bi.blockWidth);
- const uint32_t blockH = bx::max(1, bi.blockHeight);
- width = uint16_t( (uint32_t(width + blockW - 1) / blockW) * blockW);
- height = uint16_t( (uint32_t(height + blockH - 1) / blockH) * blockH);
+ .m_srcX = _src.x,
+ .m_srcY = _src.y,
+ .m_srcZ = _src.z,
+ .m_dstX = _dst.x,
+ .m_dstY = _dst.y,
+ .m_dstZ = _dst.z,
+ .m_width = width,
+ .m_height = height,
+ .m_depth = depth,
+ .m_srcMip = _src.mip,
+ .m_dstMip = _dst.mip,
+ .m_src = _src.handle,
+ .m_dst = _dst.handle,
+ };
+
+ BGFX_ENCODER(blit(_id, item) );
+ }
+
+ void Encoder::blit(ViewId _id, const BufferRegion& _dst, const BufferRegion& _src)
+ {
+ const BufferRef src = s_ctx->getBufferRef("blit/src", _src.handle);
+ const BufferRef dst = s_ctx->getBufferRef("blit/dst", _dst.handle);
+
+ BX_ASSERT(isBufferReadable(src.m_flags)
+ , "Blit source buffer (handle %d, '%S') is not created with any of `BGFX_BUFFER_COMPUTE_*`, or `BGFX_BUFFER_DRAW_INDIRECT` flags."
+ , _src.handle.idx
+ , src.m_name
+ );
+ BX_ASSERT(isBufferWritable(dst.m_flags)
+ , "Blit destination buffer (handle %d, '%S') is not created with `BGFX_BUFFER_COMPUTE_WRITE`, or `BGFX_BUFFER_DRAW_INDIRECT` flag."
+ , _dst.handle.idx
+ , dst.m_name
+ );
+
+ BX_ASSERT(_src.offset <= src.m_size
+ , "Blit src offset out of range (%d > %d)."
+ , _src.offset
+ , src.m_size
+ );
+ BX_ASSERT(_dst.offset <= dst.m_size
+ , "Blit dst offset out of range (%d > %d)."
+ , _dst.offset
+ , dst.m_size
+ );
+
+ const uint32_t maxSize = bx::min(src.m_size - _src.offset, dst.m_size - _dst.offset);
+ const uint32_t size = 0 == _src.size ? maxSize : bx::min(_src.size, maxSize);
+
+ BX_WARN(size == _src.size || 0 == _src.size
+ , "Blit buffer size truncated (%d -> %d)."
+ , _src.size
+ , size
+ );
+
+ BX_ASSERT(src.m_handle.idx != dst.m_handle.idx
+ || src.m_handle.type != dst.m_handle.type
+ , "Blit source and destination buffer must be different."
+ );
+
+ if (0 == size)
+ {
+ return;
}
- BGFX_ENCODER(blit(_id, _dst, _dstMip, _dstX, _dstY, _dstZ, _src, _srcMip, _srcX, _srcY, _srcZ, width, height, depth) );
+ const uint32_t srcOffset = src.m_offset + _src.offset;
+ const uint32_t dstOffset = dst.m_offset + _dst.offset;
+
+ BX_ASSERT(0 == (srcOffset|dstOffset|size) % 4
+ , "Blit between buffers must be 4 byte aligned (src offset %d, dst offset %d, size %d)."
+ , srcOffset
+ , dstOffset
+ , size
+ );
+
+ const BlitItem item =
+ {
+ .m_srcOffset = srcOffset,
+ .m_dstOffset = dstOffset,
+ .m_size = size,
+ .m_src = src.m_handle,
+ .m_dst = dst.m_handle,
+ };
+
+ BGFX_ENCODER(blit(_id, item) );
+ }
+
+ void Encoder::blit(ViewId _id, const BufferRegion& _dst, const TextureRegion& _src)
+ {
+ BGFX_CHECK_CAPS(BGFX_CAPS_TEXTURE_BLIT, "Texture blit is not supported!");
+ BGFX_CHECK_HANDLE("blit/src TextureHandle", s_ctx->m_textureHandle, _src.handle);
+
+ const TextureRef& src = s_ctx->m_textureRef[_src.handle.idx];
+ const BufferRef dst = s_ctx->getBufferRef("blit/dst", _dst.handle);
+
+ BX_ASSERT(isBufferWritable(dst.m_flags)
+ , "Blit destination buffer (handle %d, '%S') is not created with `BGFX_BUFFER_COMPUTE_WRITE`, or `BGFX_BUFFER_DRAW_INDIRECT` flag."
+ , _dst.handle.idx
+ , dst.m_name
+ );
+
+ BX_ASSERT(_src.mip < src.m_numMips, "Invalid blit src mip (%d > %d)", _src.mip, src.m_numMips - 1);
+
+ uint32_t srcWidth, srcHeight, srcDepth;
+ getTextureRegionDims(srcWidth, srcHeight, srcDepth, src, _src.mip);
+
+ BX_ASSERT(_src.x < srcWidth && _src.y < srcHeight && _src.z < srcDepth
+ , "Blit src coordinates out of range (%d, %d, %d) >= (%d, %d, %d)"
+ , _src.x, _src.y, _src.z
+ , srcWidth, srcHeight, srcDepth
+ );
+
+ uint16_t width = uint16_t(clampRegionExtent(srcWidth, _src.x, _src.width ) );
+ uint16_t height = uint16_t(clampRegionExtent(srcHeight, _src.y, _src.height) );
+ const uint16_t depth = uint16_t(clampRegionExtent(srcDepth, _src.z, _src.depth) );
+
+ alignTextureRegion(width, height, TextureFormat::Enum(src.m_format) );
+
+ const BufferLayout layout = resolveBufferLayout(_dst, TextureFormat::Enum(src.m_format), width, height, depth);
+
+ BX_ASSERT(_dst.offset <= dst.m_size
+ , "Blit dst offset out of range (%d > %d)."
+ , _dst.offset
+ , dst.m_size
+ );
+ BX_ASSERT(_dst.offset + layout.m_size <= dst.m_size
+ , "Blit destination buffer (handle %d, '%S') is too small (%d > %d)."
+ , _dst.handle.idx
+ , dst.m_name
+ , _dst.offset + layout.m_size
+ , dst.m_size
+ );
+
+ if (0 == layout.m_size)
+ {
+ return;
+ }
+
+ const uint32_t dstOffset = dst.m_offset + _dst.offset;
+ checkBufferLayout(BGFX_ENCODER(m_frame), dstOffset, layout);
+
+ const BlitItem item =
+ {
+ .m_srcX = _src.x,
+ .m_srcY = _src.y,
+ .m_srcZ = _src.z,
+ .m_width = width,
+ .m_height = height,
+ .m_depth = depth,
+ .m_srcMip = _src.mip,
+ .m_dstOffset = dstOffset,
+ .m_size = layout.m_size,
+ .m_rowPitch = layout.m_rowPitch,
+ .m_slicePitch = layout.m_slicePitch,
+ .m_src = _src.handle,
+ .m_dst = dst.m_handle,
+ };
+
+ BGFX_ENCODER(blit(_id, item) );
+ }
+
+ void Encoder::blit(ViewId _id, const TextureRegion& _dst, const BufferRegion& _src)
+ {
+ BGFX_CHECK_CAPS(BGFX_CAPS_TEXTURE_BLIT, "Texture blit is not supported!");
+ BGFX_CHECK_HANDLE("blit/dst TextureHandle", s_ctx->m_textureHandle, _dst.handle);
+
+ const TextureRef& dst = s_ctx->m_textureRef[_dst.handle.idx];
+ const BufferRef src = s_ctx->getBufferRef("blit/src", _src.handle);
+
+ BX_ASSERT(isBufferReadable(src.m_flags)
+ , "Blit source buffer (handle %d, '%S') is not created with any of `BGFX_BUFFER_COMPUTE_*`, or `BGFX_BUFFER_DRAW_INDIRECT` flags."
+ , _src.handle.idx
+ , src.m_name
+ );
+ BX_ASSERT(dst.isBlitDst()
+ , "Blit destination texture (handle %d, '%S') is not created with `BGFX_TEXTURE_BLIT_DST` flag."
+ , _dst.handle.idx
+ , &dst.m_name
+ );
+
+ BX_ASSERT(_dst.mip < dst.m_numMips, "Invalid blit dst mip (%d > %d)", _dst.mip, dst.m_numMips - 1);
+
+ uint32_t dstWidth, dstHeight, dstDepth;
+ getTextureRegionDims(dstWidth, dstHeight, dstDepth, dst, _dst.mip);
+
+ BX_ASSERT(_dst.x < dstWidth && _dst.y < dstHeight && _dst.z < dstDepth
+ , "Blit dst coordinates out of range (%d, %d, %d) >= (%d, %d, %d)"
+ , _dst.x, _dst.y, _dst.z
+ , dstWidth, dstHeight, dstDepth
+ );
+
+ uint16_t width = uint16_t(clampRegionExtent(dstWidth, _dst.x, _dst.width ) );
+ uint16_t height = uint16_t(clampRegionExtent(dstHeight, _dst.y, _dst.height) );
+ const uint16_t depth = uint16_t(clampRegionExtent(dstDepth, _dst.z, _dst.depth) );
+
+ alignTextureRegion(width, height, TextureFormat::Enum(dst.m_format) );
+
+ const BufferLayout layout = resolveBufferLayout(_src, TextureFormat::Enum(dst.m_format), width, height, depth);
+
+ BX_ASSERT(_src.offset <= src.m_size
+ , "Blit src offset out of range (%d > %d)."
+ , _src.offset
+ , src.m_size
+ );
+ BX_ASSERT(_src.offset + layout.m_size <= src.m_size
+ , "Blit source buffer (handle %d, '%S') is too small (%d > %d)."
+ , _src.handle.idx
+ , src.m_name
+ , _src.offset + layout.m_size
+ , src.m_size
+ );
+
+ if (0 == layout.m_size)
+ {
+ return;
+ }
+
+ const uint32_t srcOffset = src.m_offset + _src.offset;
+ checkBufferLayout(BGFX_ENCODER(m_frame), srcOffset, layout);
+
+ const BlitItem item =
+ {
+ .m_dstX = _dst.x,
+ .m_dstY = _dst.y,
+ .m_dstZ = _dst.z,
+ .m_width = width,
+ .m_height = height,
+ .m_depth = depth,
+ .m_dstMip = _dst.mip,
+ .m_srcOffset = srcOffset,
+ .m_size = layout.m_size,
+ .m_rowPitch = layout.m_rowPitch,
+ .m_slicePitch = layout.m_slicePitch,
+ .m_src = src.m_handle,
+ .m_dst = _dst.handle,
+ };
+
+ BGFX_ENCODER(blit(_id, item) );
}
#undef BGFX_ENCODER
@@ -5927,11 +6307,32 @@ namespace bgfx
}
}
- uint32_t readTexture(TextureHandle _handle, void* _data, uint16_t _layer, uint8_t _mip)
+ uint32_t read(const TextureRegion& _src, void* _data)
{
BX_ASSERT(NULL != _data, "_data can't be NULL");
BGFX_CHECK_CAPS(BGFX_CAPS_TEXTURE_READ_BACK, "Texture read-back is not supported!");
- return s_ctx->readTexture(_handle, _data, _layer, _mip);
+ BGFX_CHECK_HANDLE("read TextureHandle", s_ctx->m_textureHandle, _src.handle);
+
+ const TextureRef& src = s_ctx->m_textureRef[_src.handle.idx];
+
+ BX_ASSERT(_src.mip < src.m_numMips, "Invalid read src mip (%d > %d)", _src.mip, src.m_numMips - 1);
+
+ uint32_t srcWidth, srcHeight, srcDepth;
+ getTextureRegionDims(srcWidth, srcHeight, srcDepth, src, _src.mip);
+
+ BX_ASSERT(0 == _src.x
+ && 0 == _src.y
+ && (0 == _src.width || srcWidth == _src.width )
+ && (0 == _src.height || srcHeight == _src.height)
+ && (0 == _src.depth || 1 == _src.depth)
+ , "Texture read-back region must cover the whole mip (%dx%d)."
+ , srcWidth
+ , srcHeight
+ );
+
+ BX_UNUSED(src, srcWidth, srcHeight, srcDepth);
+
+ return s_ctx->readTexture(_src.handle, _data, _src.z, _src.mip);
}
void clear(TextureHandle _handle, uint8_t _mip, uint8_t _numMips, uint16_t _layer, uint16_t _numLayers)
@@ -5961,6 +6362,12 @@ namespace bgfx
s_ctx->clearTexture(_handle, _mip, _numMips, _layer, _numLayers);
}
+ uint32_t read(const BufferRegion& _src, void* _data)
+ {
+ BX_ASSERT(NULL != _data, "_data can't be NULL");
+ return s_ctx->readBuffer(_src.handle, _data, _src.offset, 0 == _src.size ? UINT32_MAX : _src.size);
+ }
+
FrameBufferHandle createFrameBuffer(uint16_t _width, uint16_t _height, TextureFormat::Enum _format, uint64_t _textureFlags)
{
_textureFlags |= _textureFlags&BGFX_TEXTURE_RT_MSAA_MASK ? 0 : BGFX_TEXTURE_RT;
@@ -6520,16 +6927,28 @@ namespace bgfx
s_ctx->m_encoder0->discard(_flags);
}
- void blit(ViewId _id, TextureHandle _dst, uint16_t _dstX, uint16_t _dstY, TextureHandle _src, uint16_t _srcX, uint16_t _srcY, uint16_t _width, uint16_t _height)
+ void blit(ViewId _id, const TextureRegion& _dst, const TextureRegion& _src)
{
BGFX_CHECK_ENCODER0();
- s_ctx->m_encoder0->blit(_id, _dst, _dstX, _dstY, _src, _srcX, _srcY, _width, _height);
+ s_ctx->m_encoder0->blit(_id, _dst, _src);
}
- void blit(ViewId _id, TextureHandle _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, TextureHandle _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth)
+ void blit(ViewId _id, const BufferRegion& _dst, const BufferRegion& _src)
{
BGFX_CHECK_ENCODER0();
- s_ctx->m_encoder0->blit(_id, _dst, _dstMip, _dstX, _dstY, _dstZ, _src, _srcMip, _srcX, _srcY, _srcZ, _width, _height, _depth);
+ s_ctx->m_encoder0->blit(_id, _dst, _src);
+ }
+
+ void blit(ViewId _id, const BufferRegion& _dst, const TextureRegion& _src)
+ {
+ BGFX_CHECK_ENCODER0();
+ s_ctx->m_encoder0->blit(_id, _dst, _src);
+ }
+
+ void blit(ViewId _id, const TextureRegion& _dst, const BufferRegion& _src)
+ {
+ BGFX_CHECK_ENCODER0();
+ s_ctx->m_encoder0->blit(_id, _dst, _src);
}
void requestScreenShot(FrameBufferHandle _handle, const char* _filePath)
diff --git a/src/bgfx.idl.inl b/src/bgfx.idl.inl
index b71aea4f1..5e861eb3f 100644
--- a/src/bgfx.idl.inl
+++ b/src/bgfx.idl.inl
@@ -52,6 +52,27 @@ BGFX_C99_STRUCT_SIZE_CHECK(bgfx::InternalData, bgfx_internal_data_t);
#if BGFX_CONFIG_C99_API
+BGFX_C_API void bgfx_texture_region_init(bgfx_texture_region_t* _this, bgfx_texture_handle_t _handle, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
+{
+ bgfx::TextureRegion* This = (bgfx::TextureRegion*)_this;
+ union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } handle = { _handle };
+ This->init(handle.cpp, _x, _y, _width, _height);
+}
+
+BGFX_C_API void bgfx_buffer_region_init_texture(bgfx_buffer_region_t* _this, const bgfx_texture_region_t * _texture)
+{
+ bgfx::BufferRegion* This = (bgfx::BufferRegion*)_this;
+ const bgfx::TextureRegion & texture = *(const bgfx::TextureRegion *)_texture;
+ This->init(texture);
+}
+
+BGFX_C_API void bgfx_buffer_region_init_buffer(bgfx_buffer_region_t* _this, bgfx_buffer_handle_t _handle, uint32_t _offset, uint32_t _size)
+{
+ bgfx::BufferRegion* This = (bgfx::BufferRegion*)_this;
+ union { bgfx_buffer_handle_t c; bgfx::BufferHandle cpp; } handle = { _handle };
+ This->init(handle.cpp, _offset, _size);
+}
+
BGFX_C_API void bgfx_attachment_init(bgfx_attachment_t* _this, bgfx_texture_handle_t _handle, bgfx_access_t _access, uint16_t _layer, uint16_t _numLayers, uint16_t _mip, uint8_t _resolve)
{
bgfx::Attachment* This = (bgfx::Attachment*)_this;
@@ -243,6 +264,12 @@ BGFX_C_API bgfx_index_buffer_handle_t bgfx_create_index_buffer(const bgfx_memory
return handle_ret.c;
}
+BGFX_C_API uint32_t bgfx_read_buffer(const bgfx_buffer_region_t * _src, void* _data)
+{
+ const bgfx::BufferRegion & src = *(const bgfx::BufferRegion *)_src;
+ return bgfx::read(src, _data);
+}
+
BGFX_C_API void bgfx_set_index_buffer_name(bgfx_index_buffer_handle_t _handle, const char* _name, int32_t _len)
{
union { bgfx_index_buffer_handle_t c; bgfx::IndexBufferHandle cpp; } handle = { _handle };
@@ -522,10 +549,10 @@ BGFX_C_API void bgfx_clear_texture(bgfx_texture_handle_t _handle, uint8_t _mip,
bgfx::clear(handle.cpp, _mip, _numMips, _layer, _numLayers);
}
-BGFX_C_API uint32_t bgfx_read_texture(bgfx_texture_handle_t _handle, void* _data, uint16_t _layer, uint8_t _mip)
+BGFX_C_API uint32_t bgfx_read_texture(const bgfx_texture_region_t * _src, void* _data)
{
- union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } handle = { _handle };
- return bgfx::readTexture(handle.cpp, _data, _layer, _mip);
+ const bgfx::TextureRegion & src = *(const bgfx::TextureRegion *)_src;
+ return bgfx::read(src, _data);
}
BGFX_C_API void bgfx_set_texture_name(bgfx_texture_handle_t _handle, const char* _name, int32_t _len)
@@ -1026,12 +1053,36 @@ BGFX_C_API void bgfx_encoder_discard(bgfx_encoder_t* _this, uint8_t _flags)
This->discard(_flags);
}
-BGFX_C_API void bgfx_encoder_blit(bgfx_encoder_t* _this, bgfx_view_id_t _id, bgfx_texture_handle_t _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, bgfx_texture_handle_t _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth)
+BGFX_C_API void bgfx_encoder_blit(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_texture_region_t * _src)
{
bgfx::Encoder* This = (bgfx::Encoder*)_this;
- union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } dst = { _dst };
- union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } src = { _src };
- This->blit((bgfx::ViewId)_id, dst.cpp, _dstMip, _dstX, _dstY, _dstZ, src.cpp, _srcMip, _srcX, _srcY, _srcZ, _width, _height, _depth);
+ const bgfx::TextureRegion & dst = *(const bgfx::TextureRegion *)_dst;
+ const bgfx::TextureRegion & src = *(const bgfx::TextureRegion *)_src;
+ This->blit((bgfx::ViewId)_id, dst, src);
+}
+
+BGFX_C_API void bgfx_encoder_blit_buffer(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_buffer_region_t * _src)
+{
+ bgfx::Encoder* This = (bgfx::Encoder*)_this;
+ const bgfx::BufferRegion & dst = *(const bgfx::BufferRegion *)_dst;
+ const bgfx::BufferRegion & src = *(const bgfx::BufferRegion *)_src;
+ This->blit((bgfx::ViewId)_id, dst, src);
+}
+
+BGFX_C_API void bgfx_encoder_blit_to_buffer(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_texture_region_t * _src)
+{
+ bgfx::Encoder* This = (bgfx::Encoder*)_this;
+ const bgfx::BufferRegion & dst = *(const bgfx::BufferRegion *)_dst;
+ const bgfx::TextureRegion & src = *(const bgfx::TextureRegion *)_src;
+ This->blit((bgfx::ViewId)_id, dst, src);
+}
+
+BGFX_C_API void bgfx_encoder_blit_from_buffer(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_buffer_region_t * _src)
+{
+ bgfx::Encoder* This = (bgfx::Encoder*)_this;
+ const bgfx::TextureRegion & dst = *(const bgfx::TextureRegion *)_dst;
+ const bgfx::BufferRegion & src = *(const bgfx::BufferRegion *)_src;
+ This->blit((bgfx::ViewId)_id, dst, src);
}
BGFX_C_API void bgfx_request_screen_shot(bgfx_frame_buffer_handle_t _handle, const char* _filePath)
@@ -1308,11 +1359,32 @@ BGFX_C_API void bgfx_discard(uint8_t _flags)
bgfx::discard(_flags);
}
-BGFX_C_API void bgfx_blit(bgfx_view_id_t _id, bgfx_texture_handle_t _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, bgfx_texture_handle_t _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth)
+BGFX_C_API void bgfx_blit(bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_texture_region_t * _src)
{
- union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } dst = { _dst };
- union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } src = { _src };
- bgfx::blit((bgfx::ViewId)_id, dst.cpp, _dstMip, _dstX, _dstY, _dstZ, src.cpp, _srcMip, _srcX, _srcY, _srcZ, _width, _height, _depth);
+ const bgfx::TextureRegion & dst = *(const bgfx::TextureRegion *)_dst;
+ const bgfx::TextureRegion & src = *(const bgfx::TextureRegion *)_src;
+ bgfx::blit((bgfx::ViewId)_id, dst, src);
+}
+
+BGFX_C_API void bgfx_blit_buffer(bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_buffer_region_t * _src)
+{
+ const bgfx::BufferRegion & dst = *(const bgfx::BufferRegion *)_dst;
+ const bgfx::BufferRegion & src = *(const bgfx::BufferRegion *)_src;
+ bgfx::blit((bgfx::ViewId)_id, dst, src);
+}
+
+BGFX_C_API void bgfx_blit_to_buffer(bgfx_view_id_t _id, const bgfx_buffer_region_t * _dst, const bgfx_texture_region_t * _src)
+{
+ const bgfx::BufferRegion & dst = *(const bgfx::BufferRegion *)_dst;
+ const bgfx::TextureRegion & src = *(const bgfx::TextureRegion *)_src;
+ bgfx::blit((bgfx::ViewId)_id, dst, src);
+}
+
+BGFX_C_API void bgfx_blit_from_buffer(bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_buffer_region_t * _src)
+{
+ const bgfx::TextureRegion & dst = *(const bgfx::TextureRegion *)_dst;
+ const bgfx::BufferRegion & src = *(const bgfx::BufferRegion *)_src;
+ bgfx::blit((bgfx::ViewId)_id, dst, src);
}
@@ -1355,6 +1427,9 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version)
{
static bgfx_interface_vtbl_t s_bgfx_interface =
{
+ bgfx_texture_region_init,
+ bgfx_buffer_region_init_texture,
+ bgfx_buffer_region_init_buffer,
bgfx_attachment_init,
bgfx_vertex_layout_begin,
bgfx_vertex_layout_add,
@@ -1390,6 +1465,7 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version)
bgfx_dbg_text_vprintf,
bgfx_dbg_text_image,
bgfx_create_index_buffer,
+ bgfx_read_buffer,
bgfx_set_index_buffer_name,
bgfx_destroy_index_buffer,
bgfx_create_vertex_layout,
@@ -1514,6 +1590,9 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version)
bgfx_encoder_dispatch_indirect,
bgfx_encoder_discard,
bgfx_encoder_blit,
+ bgfx_encoder_blit_buffer,
+ bgfx_encoder_blit_to_buffer,
+ bgfx_encoder_blit_from_buffer,
bgfx_request_screen_shot,
bgfx_render_frame,
bgfx_set_platform_data,
@@ -1561,7 +1640,10 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version)
bgfx_dispatch,
bgfx_dispatch_indirect,
bgfx_discard,
- bgfx_blit
+ bgfx_blit,
+ bgfx_blit_buffer,
+ bgfx_blit_to_buffer,
+ bgfx_blit_from_buffer
};
return &s_bgfx_interface;
diff --git a/src/bgfx_p.h b/src/bgfx_p.h
index bf4d3b2e2..27d7591cd 100644
--- a/src/bgfx_p.h
+++ b/src/bgfx_p.h
@@ -377,22 +377,36 @@ namespace bgfx
return getTypeName(getType() );
}
- bool isBuffer() const
- {
- return false
- || type == DynamicIndexBuffer
- || type == DynamicVertexBuffer
- || type == IndexBuffer
- || type == IndirectBuffer
- || type == VertexBuffer
- ;
- }
-
bool isTexture() const
{
return type == Texture;
}
+ bool isBuffer() const
+ {
+ return false
+ || isIndexBuffer()
+ || isVertexBuffer()
+ ;
+ }
+
+ bool isIndexBuffer() const
+ {
+ return false
+ || type == IndexBuffer
+ || type == DynamicIndexBuffer
+ ;
+ }
+
+ bool isVertexBuffer() const
+ {
+ return false
+ || type == VertexBuffer
+ || type == DynamicVertexBuffer
+ || type == IndirectBuffer
+ ;
+ }
+
uint16_t idx;
uint16_t type;
};
@@ -1082,6 +1096,7 @@ namespace bgfx
DestroyFrameBuffer,
DestroyUniform,
ReadTexture,
+ ReadBuffer,
};
void resize(uint32_t _capacity = 0)
@@ -2479,20 +2494,25 @@ namespace bgfx
BX_ALIGN_DECL_CACHE_LINE(struct) BlitItem
{
- uint16_t m_srcX;
- uint16_t m_srcY;
- uint16_t m_srcZ;
- uint16_t m_dstX;
- uint16_t m_dstY;
- uint16_t m_dstZ;
- uint16_t m_width;
- uint16_t m_height;
- uint16_t m_depth;
- uint8_t m_srcMip;
- uint8_t m_dstMip;
- Handle m_src;
- Handle m_dst;
- ViewId m_view;
+ uint16_t m_srcX = 0;
+ uint16_t m_srcY = 0;
+ uint16_t m_srcZ = 0;
+ uint16_t m_dstX = 0;
+ uint16_t m_dstY = 0;
+ uint16_t m_dstZ = 0;
+ uint16_t m_width = 0;
+ uint16_t m_height = 0;
+ uint16_t m_depth = 0;
+ uint8_t m_srcMip = 0;
+ uint8_t m_dstMip = 0;
+ uint32_t m_srcOffset = 0;
+ uint32_t m_dstOffset = 0;
+ uint32_t m_size = 0;
+ uint32_t m_rowPitch = 0;
+ uint32_t m_slicePitch = 0;
+ Handle m_src = {};
+ Handle m_dst = {};
+ ViewId m_view = 0;
};
struct IndexBuffer
@@ -2507,8 +2527,60 @@ namespace bgfx
bx::FixedString64 m_name;
uint32_t m_size;
uint16_t m_stride;
+ uint16_t m_flags;
};
+ struct BufferRef
+ {
+ Handle m_handle;
+ uint32_t m_offset;
+ uint32_t m_size;
+ uint16_t m_flags;
+ const bx::FixedString64* m_name;
+ };
+
+ inline bool isBufferReadable(uint16_t _flags)
+ {
+ return 0 != (_flags & (BGFX_BUFFER_COMPUTE_READ_WRITE|BGFX_BUFFER_DRAW_INDIRECT) );
+ }
+
+ inline bool isBufferWritable(uint16_t _flags)
+ {
+ return 0 != (_flags & (BGFX_BUFFER_COMPUTE_WRITE|BGFX_BUFFER_DRAW_INDIRECT) );
+ }
+
+ inline uint32_t calcTextureRegionPitch(TextureFormat::Enum _format, uint32_t _width)
+ {
+ const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_format) );
+ const uint32_t blockWidth = bx::max(1, blockInfo.blockWidth);
+
+ return ( (_width + blockWidth - 1) / blockWidth) * blockInfo.blockSize;
+ }
+
+ inline uint32_t calcTextureRegionNumRows(TextureFormat::Enum _format, uint32_t _height)
+ {
+ const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_format) );
+ const uint32_t blockHeight = bx::max(1, blockInfo.blockHeight);
+
+ return (_height + blockHeight - 1) / blockHeight;
+ }
+
+ inline uint32_t calcTextureRegionSize(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _depth)
+ {
+ return calcTextureRegionPitch(_format, _width)
+ * calcTextureRegionNumRows(_format, _height)
+ * bx::max(1, _depth)
+ ;
+ }
+
+ inline void calcTextureRegionTexelPitch(uint32_t& _rowLength, uint32_t& _imageHeight, TextureFormat::Enum _format, uint32_t _rowPitch, uint32_t _slicePitch)
+ {
+ const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_format) );
+
+ _rowLength = (_rowPitch / blockInfo.blockSize) * bx::max(1, blockInfo.blockWidth);
+ _imageHeight = (_slicePitch / _rowPitch) * bx::max(1, blockInfo.blockHeight);
+ }
+
struct DynamicIndexBuffer
{
void reset()
@@ -3164,6 +3236,7 @@ namespace bgfx
m_numRenderItems = 0;
m_numRenderBinds = 0;
m_numBlitItems = 0;
+ m_numBlitRepack = 0;
m_iboffset = 0;
m_vboffset = 0;
m_cmdPre.start();
@@ -3305,6 +3378,7 @@ namespace bgfx
uint32_t m_numRenderItems;
uint32_t m_numRenderBinds;
uint32_t m_numBlitItems;
+ uint32_t m_numBlitRepack;
uint32_t m_iboffset;
uint32_t m_vboffset;
@@ -3877,7 +3951,7 @@ namespace bgfx
dispatch(_id, _handle, 0, 0, 0, _flags);
}
- void blit(ViewId _id, TextureHandle _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, TextureHandle _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth);
+ void blit(ViewId _id, const BlitItem& _blit);
Frame* m_frame;
@@ -4530,6 +4604,7 @@ namespace bgfx
virtual void updateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) = 0;
virtual void clearTexture(TextureHandle _handle, uint8_t _mip, uint8_t _numMips, uint16_t _layer, uint16_t _numLayers) = 0;
virtual void readTexture(TextureHandle _handle, void* _data, uint16_t _layer, uint8_t _mip) = 0;
+ virtual void readBuffer(Handle _handle, void* _data, uint32_t _offset, uint32_t _size) = 0;
virtual void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) = 0;
virtual void overrideInternal(TextureHandle _handle, uintptr_t _ptr, uint16_t _layerIndex) = 0;
virtual uintptr_t getInternal(TextureHandle _handle) = 0;
@@ -4921,6 +4996,7 @@ namespace bgfx
VertexBuffer& vb = m_vertexBuffers[handle.idx];
vb.m_size = _mem->size;
vb.m_stride = _layout.m_stride;
+ vb.m_flags = _flags;
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateVertexBuffer);
cmdbuf.write(handle);
@@ -4994,7 +5070,8 @@ namespace bgfx
const uint32_t allocSize = bx::max(BGFX_CONFIG_DYNAMIC_INDEX_BUFFER_SIZE, bx::alignUp(_size, 1<<20) );
IndexBuffer& ib = m_indexBuffers[indexBufferHandle.idx];
- ib.m_size = allocSize;
+ ib.m_size = allocSize;
+ ib.m_flags = _flags;
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicIndexBuffer);
cmdbuf.write(indexBufferHandle);
@@ -5018,7 +5095,8 @@ namespace bgfx
}
IndexBuffer& ib = m_indexBuffers[indexBufferHandle.idx];
- ib.m_size = _size;
+ ib.m_size = _size;
+ ib.m_flags = _flags;
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicIndexBuffer);
cmdbuf.write(indexBufferHandle);
@@ -5179,6 +5257,7 @@ namespace bgfx
VertexBuffer& vb = m_vertexBuffers[vertexBufferHandle.idx];
vb.m_size = allocSize;
vb.m_stride = 0;
+ vb.m_flags = _flags;
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicVertexBuffer);
cmdbuf.write(vertexBufferHandle);
@@ -5205,6 +5284,7 @@ namespace bgfx
VertexBuffer& vb = m_vertexBuffers[vertexBufferHandle.idx];
vb.m_size = _size;
vb.m_stride = 0;
+ vb.m_flags = _flags;
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicVertexBuffer);
cmdbuf.write(vertexBufferHandle);
@@ -5538,6 +5618,11 @@ namespace bgfx
const uint32_t size = _num * BGFX_CONFIG_DRAW_INDIRECT_STRIDE;
const uint16_t flags = BGFX_BUFFER_DRAW_INDIRECT;
+ VertexBuffer& vb = m_vertexBuffers[handle.idx];
+ vb.m_size = size;
+ vb.m_stride = BGFX_CONFIG_DRAW_INDIRECT_STRIDE;
+ vb.m_flags = flags;
+
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateDynamicVertexBuffer);
cmdbuf.write(handle);
cmdbuf.write(size);
@@ -6166,6 +6251,113 @@ namespace bgfx
return m_submit->m_frameNum + 2;
}
+ BufferRef getBufferRef(const char* _desc, BufferHandle _handle)
+ {
+ BX_UNUSED(_desc);
+
+ BufferRef result;
+
+ switch (_handle.type)
+ {
+ case BufferHandle::DynamicIndexBuffer:
+ {
+ BGFX_CHECK_HANDLE(_desc, m_dynamicIndexBufferHandle, _handle);
+ const DynamicIndexBuffer& dib = m_dynamicIndexBuffers[_handle.idx];
+ result.m_handle = Handle(dib.m_handle);
+ result.m_offset = dib.m_offset;
+ result.m_size = dib.m_size;
+ result.m_flags = dib.m_flags;
+ result.m_name = &m_indexBuffers[dib.m_handle.idx].m_name;
+ }
+ break;
+
+ case BufferHandle::DynamicVertexBuffer:
+ {
+ BGFX_CHECK_HANDLE(_desc, m_dynamicVertexBufferHandle, _handle);
+ const DynamicVertexBuffer& dvb = m_dynamicVertexBuffers[_handle.idx];
+ result.m_handle = Handle(dvb.m_handle);
+ result.m_offset = dvb.m_offset;
+ result.m_size = dvb.m_size;
+ result.m_flags = dvb.m_flags;
+ result.m_name = &m_vertexBuffers[dvb.m_handle.idx].m_name;
+ }
+ break;
+
+ case BufferHandle::IndexBuffer:
+ {
+ BGFX_CHECK_HANDLE(_desc, m_indexBufferHandle, _handle);
+ const IndexBuffer& ib = m_indexBuffers[_handle.idx];
+ result.m_handle = Handle(IndexBufferHandle{ _handle.idx });
+ result.m_offset = 0;
+ result.m_size = ib.m_size;
+ result.m_flags = ib.m_flags;
+ result.m_name = &ib.m_name;
+ }
+ break;
+
+ case BufferHandle::IndirectBuffer:
+ case BufferHandle::VertexBuffer:
+ {
+ BGFX_CHECK_HANDLE(_desc, m_vertexBufferHandle, _handle);
+ const VertexBuffer& vb = m_vertexBuffers[_handle.idx];
+ result.m_handle = Handle(VertexBufferHandle{ _handle.idx });
+ result.m_offset = 0;
+ result.m_size = vb.m_size;
+ result.m_flags = vb.m_flags;
+ result.m_name = &vb.m_name;
+ }
+ break;
+
+ default:
+ BX_ASSERT(false, "%s - Invalid buffer handle type %d.", _desc, _handle.type);
+ result.m_handle = Handle();
+ result.m_offset = 0;
+ result.m_size = 0;
+ result.m_flags = 0;
+ result.m_name = NULL;
+ break;
+ }
+
+ return result;
+ }
+
+ BGFX_API_FUNC(uint32_t readBuffer(BufferHandle _handle, void* _data, uint32_t _offset, uint32_t _size) )
+ {
+ BGFX_MUTEX_SCOPE(m_resourceApiLock);
+
+ const BufferRef ref = getBufferRef("readBuffer", _handle);
+
+ BX_ASSERT(isBufferReadable(ref.m_flags)
+ , "Can't read from buffer (handle %d, '%S') which was not created with any of `BGFX_BUFFER_COMPUTE_*`, or `BGFX_BUFFER_DRAW_INDIRECT` flags."
+ , _handle.idx
+ , ref.m_name
+ );
+ BX_ASSERT(_offset <= ref.m_size
+ , "Read buffer offset out of range (%d > %d)."
+ , _offset
+ , ref.m_size
+ );
+
+ const uint32_t size = bx::min(_size, ref.m_size - _offset);
+
+ BX_WARN(size == _size || UINT32_MAX == _size
+ , "Read buffer size truncated (%d -> %d)."
+ , _size
+ , size
+ );
+
+ if (0 != size)
+ {
+ CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::ReadBuffer);
+ cmdbuf.write(ref.m_handle);
+ cmdbuf.write(_data);
+ cmdbuf.write(ref.m_offset + _offset);
+ cmdbuf.write(size);
+ }
+
+ return m_submit->m_frameNum + 2;
+ }
+
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers)
{
TextureRef& ref = m_textureRef[_handle.idx];
diff --git a/src/cs_blit_buffer_to_texture.bin.h b/src/cs_blit_buffer_to_texture.bin.h
new file mode 100644
index 000000000..ff574adfa
--- /dev/null
+++ b/src/cs_blit_buffer_to_texture.bin.h
@@ -0,0 +1,599 @@
+static const uint8_t cs_blit_buffer_to_texture_glsl[1083] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x06, 0x04, 0x00, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // ....layout(local
+ 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x78, 0x20, 0x3d, 0x20, 0x38, 0x2c, 0x20, 0x6c, 0x6f, 0x63, // _size_x = 8, loc
+ 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x79, 0x20, 0x3d, 0x20, 0x38, 0x2c, 0x20, 0x6c, // al_size_y = 8, l
+ 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x7a, 0x20, 0x3d, 0x20, 0x31, 0x29, // ocal_size_z = 1)
+ 0x20, 0x69, 0x6e, 0x3b, 0x0a, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x62, 0x69, 0x6e, // in;..layout(bin
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x73, 0x74, 0x64, 0x34, 0x33, 0x30, // ding = 0, std430
+ 0x29, 0x20, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, // ) readonly buffe
+ 0x72, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x42, 0x75, // r bgfx_blitSrcBu
+ 0x66, 0x66, 0x65, 0x72, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, // ffer.{. vec4
+ 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x5b, 0x5d, 0x3b, 0x0a, // bgfx_blitSrc[];.
+ 0x7d, 0x20, 0x5f, 0x39, 0x37, 0x3b, 0x0a, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, // } _97;..uniform
+ 0x76, 0x65, 0x63, 0x34, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, // vec4 bgfx_blitRe
+ 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x32, 0x5d, 0x3b, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, // gion[2];.layout(
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x62, 0x69, // location = 0, bi
+ 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x72, 0x67, 0x62, 0x61, 0x33, // nding = 0, rgba3
+ 0x32, 0x66, 0x29, 0x20, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x77, 0x72, 0x69, 0x74, // 2f) uniform writ
+ 0x65, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x32, 0x44, 0x41, 0x72, 0x72, // eonly image2DArr
+ 0x61, 0x79, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x3b, // ay bgfx_blitDst;
+ 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, // ..void main().{.
+ 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, // do. {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x31, 0x35, 0x20, 0x3d, // ivec3 _15 =
+ 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, // ivec3(gl_Global
+ 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x3b, 0x0a, 0x20, // InvocationID);.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x5f, 0x32, 0x30, 0x20, 0x3d, // int _20 =
+ 0x20, 0x5f, 0x31, 0x35, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // _15.x;.
+ 0x69, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x33, 0x33, 0x20, 0x3d, 0x20, 0x69, 0x76, 0x65, 0x63, // ivec3 _33 = ivec
+ 0x33, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, // 3(bgfx_blitRegio
+ 0x6e, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // n[1].xyz);.
+ 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x33, 0x35, 0x20, 0x3d, 0x20, 0x5f, 0x32, // bool _35 = _2
+ 0x30, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, // 0 >= _33.x;.
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x34, 0x38, 0x3b, 0x0a, 0x20, 0x20, // bool _48;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x33, 0x35, 0x29, 0x0a, // if (!_35).
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x34, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x2e, // _48 = _15.
+ 0x79, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, // y >= _33.y;.
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, // }. el
+ 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, // se. {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x34, 0x38, 0x20, 0x3d, 0x20, 0x5f, // _48 = _
+ 0x33, 0x35, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, // 35;. }.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x36, 0x30, 0x3b, 0x0a, // bool _60;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x34, 0x38, // if (!_48
+ 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, // ). {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x36, 0x30, 0x20, 0x3d, 0x20, 0x5f, 0x31, // _60 = _1
+ 0x35, 0x2e, 0x7a, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, // 5.z >= _33.z;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // }.
+ 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, // else. {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x36, 0x30, 0x20, 0x3d, // _60 =
+ 0x20, 0x5f, 0x34, 0x38, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, // _48;. }.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x36, 0x30, 0x29, // if (_60)
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // . {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, // break;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // }.
+ 0x69, 0x6d, 0x61, 0x67, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, // imageStore(bgfx_
+ 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x2c, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x28, 0x62, // blitDst, ivec3(b
+ 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, // gfx_blitRegion[0
+ 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x5f, 0x31, 0x35, 0x2c, 0x20, 0x5f, 0x39, // ].xyz) + _15, _9
+ 0x37, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x5b, 0x28, // 7.bgfx_blitSrc[(
+ 0x28, 0x5f, 0x31, 0x35, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x62, 0x67, 0x66, // (_15.z * int(bgf
+ 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x31, 0x5d, 0x2e, // x_blitRegion[1].
+ 0x77, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x28, 0x5f, 0x31, 0x35, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x69, // w)) + (_15.y * i
+ 0x6e, 0x74, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, // nt(bgfx_blitRegi
+ 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x5f, 0x32, 0x30, // on[0].w))) + _20
+ 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, // ]);. brea
+ 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x28, 0x66, // k;. } while(f
+ 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // alse);.}...
+};
+static const uint8_t cs_blit_buffer_to_texture_essl[1089] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x0c, 0x04, 0x00, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // ....layout(local
+ 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x78, 0x20, 0x3d, 0x20, 0x38, 0x2c, 0x20, 0x6c, 0x6f, 0x63, // _size_x = 8, loc
+ 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x79, 0x20, 0x3d, 0x20, 0x38, 0x2c, 0x20, 0x6c, // al_size_y = 8, l
+ 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x7a, 0x20, 0x3d, 0x20, 0x31, 0x29, // ocal_size_z = 1)
+ 0x20, 0x69, 0x6e, 0x3b, 0x0a, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x62, 0x69, 0x6e, // in;..layout(bin
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x73, 0x74, 0x64, 0x34, 0x33, 0x30, // ding = 0, std430
+ 0x29, 0x20, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, // ) readonly buffe
+ 0x72, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x42, 0x75, // r bgfx_blitSrcBu
+ 0x66, 0x66, 0x65, 0x72, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, // ffer.{. vec4
+ 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x5b, 0x5d, 0x3b, 0x0a, // bgfx_blitSrc[];.
+ 0x7d, 0x20, 0x5f, 0x39, 0x37, 0x3b, 0x0a, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, // } _97;..uniform
+ 0x76, 0x65, 0x63, 0x34, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, // vec4 bgfx_blitRe
+ 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x32, 0x5d, 0x3b, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, // gion[2];.layout(
+ 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x62, 0x69, // location = 0, bi
+ 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x72, 0x67, 0x62, 0x61, 0x33, // nding = 0, rgba3
+ 0x32, 0x66, 0x29, 0x20, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x77, 0x72, 0x69, 0x74, // 2f) uniform writ
+ 0x65, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x69, 0x6d, 0x61, 0x67, // eonly highp imag
+ 0x65, 0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, // e2DArray bgfx_bl
+ 0x69, 0x74, 0x44, 0x73, 0x74, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, // itDst;..void mai
+ 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, // n().{. do.
+ 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, // {. ivec3
+ 0x20, 0x5f, 0x31, 0x35, 0x20, 0x3d, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x28, 0x67, 0x6c, 0x5f, // _15 = ivec3(gl_
+ 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, // GlobalInvocation
+ 0x49, 0x44, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, // ID);. int
+ 0x20, 0x5f, 0x32, 0x30, 0x20, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, // _20 = _15.x;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x33, 0x33, 0x20, // ivec3 _33
+ 0x3d, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // = ivec3(bgfx_bli
+ 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x3b, // tRegion[1].xyz);
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x33, // . bool _3
+ 0x35, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x30, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, 0x78, // 5 = _20 >= _33.x
+ 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, // ;. bool _
+ 0x34, 0x38, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, // 48;. if (
+ 0x21, 0x5f, 0x33, 0x35, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, // !_35). {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x34, 0x38, 0x20, // _48
+ 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x2e, 0x79, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, 0x79, // = _15.y >= _33.y
+ 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, // ;. }.
+ 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // else.
+ 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, // {. _
+ 0x34, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x35, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // 48 = _35;.
+ 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, // }. bool
+ 0x20, 0x5f, 0x36, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, // _60;. if
+ 0x20, 0x28, 0x21, 0x5f, 0x34, 0x38, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // (!_48).
+ 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x36, // {. _6
+ 0x30, 0x20, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x2e, 0x7a, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, // 0 = _15.z >= _33
+ 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, // .z;. }.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // else.
+ 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // {.
+ 0x20, 0x5f, 0x36, 0x30, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x38, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, // _60 = _48;.
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, // }. if
+ 0x20, 0x28, 0x5f, 0x36, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, // (_60). {
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, // . bre
+ 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, // ak;. }.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, // imageStore
+ 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x2c, 0x20, 0x69, // (bgfx_blitDst, i
+ 0x76, 0x65, 0x63, 0x33, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, // vec3(bgfx_blitRe
+ 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x5f, // gion[0].xyz) + _
+ 0x31, 0x35, 0x2c, 0x20, 0x5f, 0x39, 0x37, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // 15, _97.bgfx_bli
+ 0x74, 0x53, 0x72, 0x63, 0x5b, 0x28, 0x28, 0x5f, 0x31, 0x35, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x69, // tSrc[((_15.z * i
+ 0x6e, 0x74, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, // nt(bgfx_blitRegi
+ 0x6f, 0x6e, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x28, 0x5f, 0x31, 0x35, // on[1].w)) + (_15
+ 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, // .y * int(bgfx_bl
+ 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x29, // itRegion[0].w)))
+ 0x20, 0x2b, 0x20, 0x5f, 0x32, 0x30, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // + _20]);.
+ 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x77, // break;. } w
+ 0x68, 0x69, 0x6c, 0x65, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, // hile(false);.}..
+ 0x00, // .
+};
+static const uint8_t cs_blit_buffer_to_texture_spv[1966] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x01, 0x00, 0x02, // .bgfx_blitDst...
+ 0x00, 0x03, 0x00, 0x00, 0x03, 0x55, 0x00, 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // .....U..bgfx_bli
+ 0x74, 0x53, 0x72, 0x63, 0x41, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x07, // tSrcA.........H.
+ 0x00, 0x00, 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00, 0xd2, 0x00, // ....#...........
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, // ................
+ 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, // ......GLSL.std.4
+ 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // 50..............
+ 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, // ..............ma
+ 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, // in....s.........
+ 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, // ................
+ 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x05, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x05, 0x00, // ................
+ 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, // ......main......
+ 0x06, 0x00, 0x26, 0x00, 0x00, 0x00, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x42, 0x6c, 0x6f, // ..&...UniformBlo
+ 0x63, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, // ck........&.....
+ 0x00, 0x00, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, // ..bgfx_blitRegio
+ 0x6e, 0x00, 0x05, 0x00, 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, // n.....(.........
+ 0x06, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, // ..^...bgfx_blitD
+ 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x00, 0x62, 0x67, // st........f...bg
+ 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, // fx_blitSrc......
+ 0x05, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x64, 0x61, 0x74, 0x61, 0x00, // ..f.......@data.
+ 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x68, 0x00, 0x00, 0x00, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, // ......h...bgfx_b
+ 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x73, 0x00, // litSrc........s.
+ 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, // ..gl_GlobalInvoc
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x25, 0x00, // ationID...G...%.
+ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x26, 0x00, // ..........G...&.
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, // ......H...&.....
+ 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x28, 0x00, // ..#.......G...(.
+ 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x28, 0x00, // ..!.......G...(.
+ 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x5e, 0x00, // ..".......G...^.
+ 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x21, 0x00, // ......G...^...!.
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x22, 0x00, // ......G...^...".
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00, // ......G...e.....
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x66, 0x00, 0x00, 0x00, 0x03, 0x00, // ......G...f.....
+ 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, // ..H...f.........
+ 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, // ..H...f.......#.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x68, 0x00, 0x00, 0x00, 0x18, 0x00, // ......G...h.....
+ 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, // ..G...h...!.....
+ 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, // ..G...h...".....
+ 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x73, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1c, 0x00, // ..G...s.........
+ 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, // ..........!.....
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, // .............. .
+ 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, // ................
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, // .............. .
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, // ................
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x00, // ................
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, // .............. .
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, // ......+....... .
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x24, 0x00, // ......+.......$.
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0c, 0x00, // ..........%.....
+ 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, // ..$.......&...%.
+ 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x26, 0x00, // .. ...'.......&.
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, // ..;...'...(.....
+ 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, // ..+.......).....
+ 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, // ..+.......*.....
+ 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, // ......+.........
+ 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, // .. ...,.........
+ 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x32, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1f, 0x00, // ......2...+.....
+ 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x4e, 0x00, // ..M....... ...N.
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x5d, 0x00, // .......... ...].
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x5d, 0x00, // ..........;...].
+ 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00, 0x65, 0x00, // ..^...........e.
+ 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x66, 0x00, 0x00, 0x00, 0x65, 0x00, // ..........f...e.
+ 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x67, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x66, 0x00, // .. ...g.......f.
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x02, 0x00, // ..;...g...h.....
+ 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, // .. ...r.........
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, // ..;...r...s.....
+ 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // ..6.............
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, // ..............=.
+ 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0xf7, 0x00, // ......t...s.....
+ 0x03, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x03, 0x00, 0x20, 0x00, // .............. .
+ 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x98, 0x00, 0x00, 0x00, 0x51, 0x00, // ..............Q.
+ 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, // ..........t.....
+ 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x28, 0x00, // ..A...,.......(.
+ 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, // ..)...*...=.....
+ 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x2b, 0x00, // ..........O...+.
+ 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x04, 0x00, 0x0a, 0x00, // ..........n.....
+ 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, // ..........Q.....
+ 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, // ................
+ 0x05, 0x00, 0x32, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xa0, 0x00, // ..2.............
+ 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x74, 0x00, // ..Q...........t.
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xa8, 0x00, // ......Q.........
+ 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x32, 0x00, // ..............2.
+ 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa6, 0x00, // ................
+ 0x05, 0x00, 0x32, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0xa9, 0x00, // ..2.............
+ 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x74, 0x00, // ..Q...........t.
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xb1, 0x00, // ......Q.........
+ 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x32, 0x00, // ..............2.
+ 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xa6, 0x00, // ................
+ 0x05, 0x00, 0x32, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xb2, 0x00, // ..2.............
+ 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, // ................
+ 0x04, 0x00, 0xb3, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xf8, 0x00, // ................
+ 0x02, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xd1, 0x00, 0x00, 0x00, 0xf8, 0x00, // ................
+ 0x02, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x4e, 0x00, 0x00, 0x00, 0xb8, 0x00, // ......A...N.....
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x4d, 0x00, // ..(...)...*...M.
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0xb8, 0x00, // ..=.............
+ 0x00, 0x00, 0x6e, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0xb9, 0x00, // ..n.............
+ 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xac, 0x00, // ................
+ 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x4e, 0x00, 0x00, 0x00, 0xbe, 0x00, // ......A...N.....
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x4d, 0x00, // ..(...)...)...M.
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xbe, 0x00, // ..=.............
+ 0x00, 0x00, 0x6e, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xbf, 0x00, // ..n.............
+ 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xa3, 0x00, // ................
+ 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xc2, 0x00, // ................
+ 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x09, 0x00, // ................
+ 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x41, 0x00, // ..............A.
+ 0x06, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, // ..,.......(...).
+ 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xc7, 0x00, // ..)...=.........
+ 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x2b, 0x00, 0x00, 0x00, 0xc8, 0x00, // ......O...+.....
+ 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // ................
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xc9, 0x00, // ......n.........
+ 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xcb, 0x00, // ................
+ 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, // ......t...=.....
+ 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x2c, 0x00, // ......^...A...,.
+ 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0xc5, 0x00, // ......h...).....
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0xce, 0x00, // ..=.............
+ 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xcf, 0x00, // ..c.............
+ 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xd1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xd1, 0x00, // ................
+ 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, // ......8..... .
+};
+static const uint8_t cs_blit_buffer_to_texture_wgsl[1170] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x01, 0x00, 0x02, // .bgfx_blitDst...
+ 0x00, 0x03, 0x00, 0x00, 0x03, 0x55, 0x00, 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // .....U..bgfx_bli
+ 0x74, 0x53, 0x72, 0x63, 0x41, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x04, // tSrcA.........*.
+ 0x00, 0x00, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x28, 0x6f, 0x66, 0x66, // ..diagnostic(off
+ 0x2c, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x75, 0x6e, 0x69, // , derivative_uni
+ 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x74, 0x79, 0x29, 0x3b, 0x0a, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, // formity);.diagno
+ 0x73, 0x74, 0x69, 0x63, 0x28, 0x6f, 0x66, 0x66, 0x2c, 0x20, 0x73, 0x75, 0x62, 0x67, 0x72, 0x6f, // stic(off, subgro
+ 0x75, 0x70, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x74, 0x79, 0x29, 0x3b, 0x0a, // up_uniformity);.
+ 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x42, // .struct UniformB
+ 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, // lock {. bgfx_bl
+ 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x20, 0x3a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, // itRegion : array
+ 0x3c, 0x76, 0x65, 0x63, 0x34, 0x3c, 0x66, 0x33, 0x32, 0x3e, 0x2c, 0x20, 0x32, 0x75, 0x3e, 0x2c, // , 2u>,
+ 0x0a, 0x7d, 0x0a, 0x0a, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x30, 0x75, 0x29, 0x20, 0x40, // .}..@group(0u) @
+ 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x30, 0x75, 0x29, 0x20, 0x76, 0x61, 0x72, 0x3c, // binding(0u) var<
+ 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x20, 0x76, 0x20, 0x3a, 0x20, 0x55, 0x6e, 0x69, // uniform> v : Uni
+ 0x66, 0x6f, 0x72, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0a, 0x0a, 0x40, 0x67, 0x72, 0x6f, // formBlock;..@gro
+ 0x75, 0x70, 0x28, 0x30, 0x75, 0x29, 0x20, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, // up(0u) @binding(
+ 0x32, 0x75, 0x29, 0x20, 0x76, 0x61, 0x72, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // 2u) var bgfx_bli
+ 0x74, 0x44, 0x73, 0x74, 0x20, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, // tDst : texture_s
+ 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x32, 0x64, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3c, // torage_2d_array<
+ 0x72, 0x67, 0x62, 0x61, 0x33, 0x32, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, // rgba32float, wri
+ 0x74, 0x65, 0x3e, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x62, 0x67, 0x66, // te>;..struct bgf
+ 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x6d, 0x20, // x_blitSrc {. m
+ 0x3a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3c, 0x76, 0x65, 0x63, 0x34, 0x3c, 0x66, 0x33, 0x32, // : array>,.}..@group(0u
+ 0x29, 0x20, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x33, 0x75, 0x29, 0x20, 0x76, // ) @binding(3u) v
+ 0x61, 0x72, 0x3c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x61, 0x64, // ar bgfx_blitSrc_1
+ 0x20, 0x3a, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x3b, // : bgfx_blitSrc;
+ 0x0a, 0x0a, 0x40, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x20, 0x40, 0x77, 0x6f, 0x72, 0x6b, // ..@compute @work
+ 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x38, 0x75, 0x2c, 0x20, 0x38, // group_size(8u, 8
+ 0x75, 0x2c, 0x20, 0x31, 0x75, 0x29, 0x0a, 0x66, 0x6e, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x40, // u, 1u).fn main(@
+ 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x28, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69, // builtin(global_i
+ 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x29, 0x20, 0x67, 0x6c, // nvocation_id) gl
+ 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, // _GlobalInvocatio
+ 0x6e, 0x49, 0x44, 0x20, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x33, 0x3c, 0x75, 0x33, 0x32, 0x3e, 0x29, // nID : vec3)
+ 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x76, // {. let v_1 = v
+ 0x65, 0x63, 0x33, 0x3c, 0x69, 0x33, 0x32, 0x3e, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, // ec3(gl_Glob
+ 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x3b, // alInvocationID);
+ 0x0a, 0x20, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x28, 0x30, 0x75, 0x29, 0x20, 0x7b, 0x0a, // . switch(0u) {.
+ 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3a, 0x20, 0x7b, 0x0a, 0x20, // default: {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x32, 0x20, 0x3d, 0x20, 0x76, // let v_2 = v
+ 0x5f, 0x31, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, // _1.x;. let
+ 0x76, 0x5f, 0x33, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x33, 0x3c, 0x69, 0x33, 0x32, 0x3e, 0x28, // v_3 = vec3(
+ 0x76, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, // v.bgfx_blitRegio
+ 0x6e, 0x5b, 0x31, 0x69, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, // n[1i].xyz);.
+ 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x34, 0x20, 0x3d, 0x20, 0x76, 0x5f, 0x31, 0x2e, // let v_4 = v_1.
+ 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x35, // y;. let v_5
+ 0x20, 0x3d, 0x20, 0x76, 0x5f, 0x31, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // = v_1.z;.
+ 0x69, 0x66, 0x20, 0x28, 0x28, 0x28, 0x28, 0x76, 0x5f, 0x32, 0x20, 0x3e, 0x3d, 0x20, 0x76, 0x5f, // if ((((v_2 >= v_
+ 0x33, 0x2e, 0x78, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x76, 0x5f, 0x34, 0x20, 0x3e, 0x3d, 0x20, 0x76, // 3.x) | (v_4 >= v
+ 0x5f, 0x33, 0x2e, 0x79, 0x29, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x76, 0x5f, 0x35, 0x20, 0x3e, 0x3d, // _3.y)) | (v_5 >=
+ 0x20, 0x76, 0x5f, 0x33, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, // v_3.z))) {.
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // break;.
+ 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x36, // }. let v_6
+ 0x20, 0x3d, 0x20, 0x28, 0x28, 0x28, 0x76, 0x5f, 0x35, 0x20, 0x2a, 0x20, 0x69, 0x33, 0x32, 0x28, // = (((v_5 * i32(
+ 0x76, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, // v.bgfx_blitRegio
+ 0x6e, 0x5b, 0x31, 0x69, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x28, 0x76, 0x5f, 0x34, // n[1i].w)) + (v_4
+ 0x20, 0x2a, 0x20, 0x69, 0x33, 0x32, 0x28, 0x76, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, // * i32(v.bgfx_bl
+ 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x69, 0x5d, 0x2e, 0x77, 0x29, 0x29, // itRegion[0i].w))
+ 0x29, 0x20, 0x2b, 0x20, 0x76, 0x5f, 0x32, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // ) + v_2);.
+ 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x37, 0x20, 0x3d, 0x20, 0x28, 0x76, 0x65, 0x63, 0x33, 0x3c, // let v_7 = (vec3<
+ 0x69, 0x33, 0x32, 0x3e, 0x28, 0x76, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // i32>(v.bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x69, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x20, // Region[0i].xyz)
+ 0x2b, 0x20, 0x76, 0x5f, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, // + v_1);. te
+ 0x78, 0x74, 0x75, 0x72, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, // xtureStore(bgfx_
+ 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x2c, 0x20, 0x76, 0x5f, 0x37, 0x2e, 0x78, 0x79, 0x2c, // blitDst, v_7.xy,
+ 0x20, 0x76, 0x5f, 0x37, 0x2e, 0x7a, 0x2c, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // v_7.z, bgfx_bli
+ 0x74, 0x53, 0x72, 0x63, 0x5f, 0x31, 0x2e, 0x6d, 0x5b, 0x76, 0x5f, 0x36, 0x5d, 0x29, 0x3b, 0x0a, // tSrc_1.m[v_6]);.
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x7d, 0x0a, 0x00, 0x00, 0x20, 0x00, // }. }.}... .
+ 0x20, 0x00, // .
+};
+static const uint8_t cs_blit_buffer_to_texture_dxbc[580] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x0c, 0x02, 0x00, 0x00, 0x44, 0x58, 0x42, 0x43, 0x45, 0x0b, 0x84, 0x8f, 0x8f, 0x19, 0x7f, 0xee, // ....DXBCE.......
+ 0x16, 0x37, 0x63, 0x75, 0x24, 0x0f, 0xcd, 0x96, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, // .7cu$...........
+ 0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, // ....,...<...L...
+ 0x49, 0x53, 0x47, 0x4e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // ISGN............
+ 0x4f, 0x53, 0x47, 0x4e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // OSGN............
+ 0x53, 0x48, 0x45, 0x58, 0xb8, 0x01, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x6e, 0x00, 0x00, 0x00, // SHEX....P...n...
+ 0x6a, 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, // j...Y...F. .....
+ 0x02, 0x00, 0x00, 0x00, 0x58, 0x08, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ....X....p......
+ 0x55, 0x55, 0x00, 0x00, 0x9c, 0x40, 0x00, 0x04, 0x00, 0xe0, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, // UU...@..........
+ 0x55, 0x55, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x02, 0x72, 0x00, 0x02, 0x00, 0x68, 0x00, 0x00, 0x02, // UU.._...r...h...
+ 0x02, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // ................
+ 0x01, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x06, 0x72, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ........r.......
+ 0x46, 0x82, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x06, // F. .........!...
+ 0x72, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x02, 0x02, 0x00, 0x46, 0x02, 0x10, 0x00, // r.......F...F...
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ....<...........
+ 0x1a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x3c, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, // <...........*...
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, // ................
+ 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, // ........>.......
+ 0x1b, 0x00, 0x00, 0x06, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x80, 0x20, 0x00, // ............:. .
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x06, 0xf2, 0x00, 0x10, 0x00, // ................
+ 0x01, 0x00, 0x00, 0x00, 0x36, 0x89, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ....6. .........
+ 0x26, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x00, 0x00, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // &.......".......
+ 0x0a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x02, 0x00, 0x23, 0x00, 0x00, 0x08, // ............#...
+ 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x10, 0x00, // ........*.......
+ 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x06, // ................
+ 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x0a, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 0x06, 0xf2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, // ................
+ 0x96, 0x0f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0a, 0x02, 0x00, 0x2d, 0x00, 0x00, 0x89, // ........F...-...
+ 0x42, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // B...CU..........
+ 0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ........F~......
+ 0xa4, 0x00, 0x00, 0x07, 0xf2, 0xe0, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, // ............F...
+ 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, // ....F.......>...
+ 0x00, 0x00, 0x20, 0x00, // .. .
+};
+static const uint8_t cs_blit_buffer_to_texture_dxil[2144] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x28, 0x08, 0x00, 0x00, 0x44, 0x58, 0x42, 0x43, 0xcd, 0x29, 0xa9, 0x3f, 0x1d, 0x3c, 0xff, 0x54, // (...DXBC.).?.<.T
+ 0xac, 0x34, 0x88, 0x93, 0x8c, 0xe0, 0x21, 0x61, 0x01, 0x00, 0x00, 0x00, 0x28, 0x08, 0x00, 0x00, // .4....!a....(...
+ 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, // ....<...L.......
+ 0x6c, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, // l.......D...`...
+ 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SFI0............
+ 0x49, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // ISG1............
+ 0x4f, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // OSG1............
+ 0x50, 0x53, 0x56, 0x30, 0x9c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PSV0....8.......
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, // .........main...
+ 0x00, 0x00, 0x00, 0x00, 0x49, 0x4c, 0x44, 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, // ....ILDN,.....$.
+ 0x65, 0x64, 0x37, 0x63, 0x33, 0x33, 0x31, 0x38, 0x65, 0x39, 0x34, 0x66, 0x61, 0x31, 0x31, 0x38, // ed7c3318e94fa118
+ 0x37, 0x64, 0x62, 0x38, 0x39, 0x65, 0x64, 0x31, 0x39, 0x37, 0x30, 0x62, 0x30, 0x62, 0x66, 0x35, // 7db89ed1970b0bf5
+ 0x2e, 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, // .pdb....HASH....
+ 0x00, 0x00, 0x00, 0x00, 0xed, 0x7c, 0x33, 0x18, 0xe9, 0x4f, 0xa1, 0x18, 0x7d, 0xb8, 0x9e, 0xd1, // .....|3..O..}...
+ 0x97, 0x0b, 0x0b, 0xf5, 0x44, 0x58, 0x49, 0x4c, 0xc0, 0x06, 0x00, 0x00, 0x60, 0x00, 0x05, 0x00, // ....DXIL....`...
+ 0xb0, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // ....DXIL........
+ 0xa8, 0x06, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xa7, 0x01, 0x00, 0x00, // ....BC..!.......
+ 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, // .. ...........#.
+ 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, // A..I..29....%...
+ 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, // ...b..E.B..B..2.
+ 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, // 8..K.2R.H.. CF..
+ 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, // ..2B.H...".PAQ..
+ 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // .....)F.Q.......
+ 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x86, 0xf0, 0xff, 0xff, // ........@.......
+ 0xff, 0xff, 0x03, 0x20, 0x01, 0xd5, 0x06, 0x62, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x90, 0x00, // ... ...b........
+ 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, // I.........`B L..
+ 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, // ..... ..F...2"H.
+ 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, // d..."....".....
+ 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x7c, 0x23, 0x00, 0x25, 0x00, 0x14, 0xe6, // .L.....L.|#.%...
+ 0x08, 0xc0, 0xa0, 0x0c, 0x63, 0x0c, 0x22, 0x33, 0x00, 0x37, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, // ....c."3.7..?a.!
+ 0xf9, 0x2b, 0x21, 0xad, 0xc4, 0xe4, 0x17, 0xb7, 0x8d, 0x0a, 0x63, 0x8c, 0x19, 0x73, 0x04, 0x08, // .+!.......c..s..
+ 0xa1, 0x7b, 0x86, 0xcb, 0x9f, 0xb0, 0x87, 0x90, 0xfc, 0x10, 0x68, 0x86, 0x85, 0x40, 0x41, 0x2a, // .{........h..@A*
+ 0xc5, 0x19, 0x6a, 0x0c, 0x5a, 0x65, 0x01, 0x43, 0x8d, 0x31, 0x8c, 0x31, 0x06, 0x51, 0x3b, 0x6a, // ..j.Ze.C.1.1.Q;j
+ 0xb8, 0xfc, 0x09, 0x7b, 0x08, 0xc9, 0xe7, 0x36, 0xaa, 0x58, 0x89, 0xc9, 0x2f, 0x6e, 0x1b, 0x11, // ...{...6.X../n..
+ 0xc6, 0x18, 0x53, 0x88, 0x37, 0xd4, 0x20, 0x38, 0x47, 0x10, 0x14, 0x43, 0x0d, 0x34, 0x86, 0xa4, // ..S.7. 8G..C.4..
+ 0x39, 0x10, 0x30, 0x8c, 0x40, 0x18, 0x33, 0x7d, 0xe3, 0xc0, 0x0e, 0xe1, 0x30, 0x0f, 0xf3, 0xe0, // 9.0.@.3}....0...
+ 0x06, 0xa2, 0x50, 0x0f, 0xe6, 0x60, 0x0e, 0xe5, 0x20, 0x0f, 0x7c, 0x60, 0x0f, 0xe5, 0x30, 0x0e, // ..P..`.. .|`..0.
+ 0xf4, 0xf0, 0x0e, 0xf2, 0xc0, 0x07, 0xe6, 0xc0, 0x0e, 0xef, 0x10, 0x0e, 0xf4, 0xc0, 0x06, 0x60, // ...............`
+ 0x40, 0x07, 0x7e, 0x00, 0x06, 0x7e, 0x80, 0x02, 0x4b, 0x77, 0xa6, 0x34, 0x18, 0x07, 0x76, 0x08, // @.~..~..Kw.4..v.
+ 0x87, 0x79, 0x98, 0x07, 0x37, 0x90, 0x85, 0x5b, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8, 0x07, // .y..7..[..r..z..
+ 0x79, 0x28, 0x07, 0x39, 0x20, 0x85, 0x50, 0x90, 0x07, 0x79, 0x08, 0x87, 0x7c, 0xe0, 0x03, 0x7b, // y(.9 .P..y..|..{
+ 0x28, 0x87, 0x71, 0xa0, 0x87, 0x77, 0x90, 0x07, 0x3e, 0x30, 0x07, 0x76, 0x78, 0x87, 0x70, 0xa0, // (.q..w..>0.vx.p.
+ 0x07, 0x36, 0x00, 0x03, 0x3a, 0xf0, 0x03, 0x30, 0xf0, 0x03, 0x14, 0x58, 0xca, 0x29, 0x60, 0x67, // .6..:..0...X.)`g
+ 0x42, 0xc8, 0xe0, 0x14, 0xd8, 0xe1, 0x1d, 0xc4, 0x21, 0x1c, 0xd8, 0x61, 0x1e, 0x50, 0xb0, 0x89, // B.......!..a.P..
+ 0x4f, 0x01, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, // O.....r..t`.6h.y
+ 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, // h.r....P.m..zP.m
+ 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, // ..z0.r..s .m..q.
+ 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, // .s .m..x..s .m..
+ 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, // q`.z0.r...0.r..s
+ 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, // .m..v@.z`.t....
+ 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, // .v..s .m`.s .z0.
+ 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, // r...`.t..v@.m..x
+ 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, // ..q`.z0.r..v@.C.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x04, 0x10, 0x00, // ............<...
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x16, 0x20, 0x00, 0x04, 0x00, 0x00, // .........y. ....
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, // .......4@.......
+ 0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, // ..0............`
+ 0xc8, 0x33, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x16, 0x08, 0x00, // .3.. .......@...
+ 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, // ....2.....L...&G
+ 0xc6, 0x04, 0x43, 0x1a, 0x25, 0x30, 0x02, 0x50, 0x14, 0xc5, 0x50, 0x12, 0xe5, 0x50, 0x40, 0x85, // ..C.%0.P..P..P@.
+ 0x50, 0x10, 0x24, 0x47, 0x00, 0x08, 0xcf, 0x00, 0x90, 0x9e, 0x01, 0xa0, 0x3e, 0x03, 0x00, 0x00, // P.$G........>...
+ 0x79, 0x18, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, // y...A.....L.F...
+ 0x8f, 0x0c, 0x6f, 0xec, 0xed, 0x4d, 0x0c, 0x24, 0xc6, 0x25, 0x06, 0xc6, 0x45, 0xc6, 0x06, 0xa6, // ..o..M.$.%..E...
+ 0xc6, 0x65, 0xe6, 0x06, 0x04, 0x65, 0x8c, 0x86, 0x0c, 0xc7, 0x8c, 0xc6, 0x2c, 0x27, 0x27, 0x65, // .e...e......,''e
+ 0x43, 0x10, 0x4c, 0x10, 0x06, 0x63, 0x82, 0x30, 0x1c, 0x1b, 0x84, 0x81, 0x98, 0x20, 0x0c, 0xc8, // C.L..c.0..... ..
+ 0x06, 0x61, 0x30, 0x28, 0x8c, 0xcd, 0x4d, 0x10, 0x86, 0x64, 0xc3, 0x80, 0x24, 0xc4, 0x04, 0x01, // .a0(..M..d..$...
+ 0x83, 0x08, 0x4c, 0x10, 0x06, 0x65, 0x83, 0x40, 0x34, 0x1b, 0x12, 0x62, 0x61, 0x08, 0x62, 0x30, // ..L..e.@4..ba.b0
+ 0x08, 0x67, 0x43, 0xf0, 0x4c, 0x10, 0xb4, 0x68, 0x82, 0x30, 0x2c, 0x13, 0x04, 0xe9, 0xd9, 0xb0, // .gC.L..h.0,.....
+ 0x10, 0x11, 0x43, 0x10, 0x83, 0x34, 0x4d, 0x93, 0xb3, 0x21, 0xa0, 0x26, 0x08, 0x9d, 0x34, 0x41, // ..C..4M..!.&..4A
+ 0x18, 0x98, 0x0d, 0x08, 0x61, 0x31, 0x04, 0x31, 0x5c, 0xc0, 0x86, 0x00, 0xdb, 0x40, 0x40, 0x55, // ....a1.1.....@@U
+ 0x06, 0x4c, 0x10, 0x04, 0x80, 0x44, 0x5b, 0x58, 0x9a, 0xdb, 0x04, 0x61, 0x68, 0x26, 0x08, 0x83, // .L...D[X...ah&..
+ 0xb3, 0x61, 0xf0, 0xbc, 0x61, 0x83, 0xd0, 0x7d, 0x1b, 0x8a, 0x8d, 0x03, 0x34, 0x30, 0xa8, 0xc2, // .a..a..}....40..
+ 0xc6, 0x66, 0xd7, 0xe6, 0x92, 0x46, 0x56, 0xe6, 0x46, 0x37, 0x25, 0x08, 0xaa, 0x90, 0xe1, 0xb9, // .f...FV.F7%.....
+ 0xd8, 0x95, 0xc9, 0xcd, 0xa5, 0xbd, 0xb9, 0x4d, 0x09, 0x88, 0x26, 0x64, 0x78, 0x2e, 0x76, 0x61, // .......M..&dx.va
+ 0x6c, 0x76, 0x65, 0x72, 0x53, 0x02, 0xa3, 0x0e, 0x19, 0x9e, 0xcb, 0x1c, 0x5a, 0x18, 0x59, 0x99, // lverS.......Z.Y.
+ 0x5c, 0xd3, 0x1b, 0x59, 0x19, 0xdb, 0x94, 0x20, 0x29, 0x43, 0x86, 0xe7, 0x22, 0x57, 0x36, 0xf7, // ...Y... )C.."W6.
+ 0x56, 0x27, 0x37, 0x56, 0x36, 0x37, 0x25, 0xc8, 0xea, 0x90, 0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, // V'7V67%.........
+ 0xe5, 0x41, 0xbd, 0xa5, 0xb9, 0xd1, 0xcd, 0x4d, 0x09, 0xc0, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, // .A.....M....y...
+ 0x51, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, // Q...3......f..=.
+ 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, // C8...B..yx.s.q..
+ 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, // ........3.B.....
+ 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, // ..f0.=.C8.....=.
+ 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, // C=..=.x.tp.{..yH
+ 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, // .pp.zp.vx.p ....
+ 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, // .....0.n0.....P.
+ 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, // 3....!..!..a.f0.
+ 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, // ;..;.C9..<..<..;
+ 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, // ...v`.{h.7h.rh.7
+ 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, // ..p..p`.v(.v..vx
+ 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, // .w.._..q..r..y..
+ 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, // ,..........0.b..
+ 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, // ...........a..!.
+ 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, // ....a...C9.C9.C9
+ 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, // .C9..8.C8..;../.
+ 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, // .<..;..;....!.|p
+ 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, // .z(.v....C.....
+ 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, // ..............P.
+ 0xf4, 0x30, 0x83, 0x81, 0xc8, 0x01, 0x1f, 0xdc, 0x40, 0x1c, 0xe4, 0xa1, 0x1c, 0xc2, 0x61, 0x1d, // .0......@.....a.
+ 0xdc, 0x40, 0x1c, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, // .@......q ......
+ 0x26, 0x40, 0x0d, 0x97, 0xef, 0x3c, 0x7e, 0x40, 0x15, 0x05, 0x11, 0x95, 0x0e, 0x30, 0xf8, 0xc5, // &@...<~@.....0..
+ 0x6d, 0x1b, 0xc1, 0x36, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x40, 0x15, 0x05, 0x11, 0x95, 0x0e, 0x30, // m..6....B@.....0
+ 0x94, 0x84, 0x01, 0x08, 0x98, 0x5f, 0xdc, 0xb6, 0x15, 0x48, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x44, // ....._...H..;./D
+ 0x04, 0x30, 0x11, 0x21, 0xd0, 0x0c, 0x0b, 0x61, 0x03, 0xd6, 0x70, 0xf9, 0xce, 0xe3, 0x4f, 0xc4, // .0.!...a..p...O.
+ 0x35, 0x51, 0x11, 0xc1, 0x4e, 0x4e, 0x44, 0xf8, 0xc5, 0x6d, 0x5b, 0x80, 0x34, 0x5c, 0xbe, 0xf3, // 5Q..NND..m[.4...
+ 0xf8, 0xd3, 0x11, 0x11, 0xc0, 0x20, 0x0e, 0x3e, 0x72, 0xdb, 0x06, 0x40, 0x30, 0x00, 0xd2, 0x00, // ..... .>r..@0...
+ 0x61, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x13, 0x04, 0x45, 0x2c, 0x10, 0x00, 0x00, 0x00, // a ..D.....E,....
+ 0x06, 0x00, 0x00, 0x00, 0x34, 0x4a, 0xae, 0x74, 0x03, 0xca, 0xae, 0x08, 0x0a, 0x31, 0x60, 0x06, // ....4J.t.....1`.
+ 0xa0, 0x0c, 0x03, 0x08, 0x95, 0xc0, 0x08, 0x40, 0x11, 0x94, 0x07, 0x00, 0x23, 0x06, 0x09, 0x00, // .......@....#...
+ 0x82, 0x60, 0x30, 0x65, 0x0b, 0x71, 0x5d, 0xcf, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x4c, 0x1a, // .`0e.q]..A.. .L.
+ 0x43, 0x60, 0x18, 0x34, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xd3, 0xd6, 0x10, 0x59, 0x16, 0x8d, // C`.4b.. .....Y..
+ 0x18, 0x18, 0x00, 0x08, 0x82, 0x01, 0x01, 0x06, 0x8d, 0x36, 0x62, 0x60, 0x00, 0x20, 0x08, 0x06, // .........6b`. ..
+ 0x44, 0x18, 0x38, 0xdc, 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x10, 0x62, 0xf0, 0x34, 0x23, 0x06, // D.8..... ..b.4#.
+ 0x07, 0x00, 0x82, 0x60, 0x00, 0x81, 0xc1, 0x43, 0x78, 0xa3, 0x09, 0x01, 0x70, 0xc1, 0xa0, 0xe1, // ...`...Cx...p...
+ 0x06, 0x23, 0x40, 0x83, 0x59, 0x86, 0x80, 0x08, 0x46, 0x13, 0x88, 0xe0, 0x82, 0x41, 0xc3, 0x0d, // .#@.Y...F....A..
+ 0x48, 0x80, 0x06, 0xb3, 0x0c, 0x02, 0x11, 0x8c, 0x26, 0x1c, 0xc2, 0x05, 0x83, 0x86, 0x1b, 0x94, // H.......&.......
+ 0x00, 0x0d, 0x66, 0x19, 0x06, 0x22, 0x18, 0x4d, 0x50, 0x86, 0x0b, 0x06, 0x59, 0xd0, 0x88, 0x60, // ..f..".MP...Y..`
+ 0xc4, 0xe0, 0x00, 0x40, 0x10, 0x0c, 0xa0, 0x36, 0xe0, 0x22, 0x35, 0x18, 0x4d, 0x08, 0x86, 0x0b, // ...@...6."5.M...
+ 0x06, 0x59, 0x20, 0x89, 0xa0, 0x0a, 0x0a, 0x2a, 0x10, 0x60, 0xc4, 0x00, 0x01, 0x40, 0x10, 0x0c, // .Y ....*.`...@..
+ 0x96, 0x3a, 0x00, 0x03, 0x2c, 0xf8, 0x46, 0x13, 0x02, 0x60, 0x34, 0x41, 0x08, 0x46, 0x13, 0x06, // .:..,.F..`4A.F..
+ 0x61, 0x34, 0x81, 0x18, 0x46, 0x13, 0x16, 0x60, 0x34, 0x81, 0x09, 0x46, 0x13, 0x1a, 0xe1, 0x86, // a4..F..`4..F....
+ 0x41, 0x37, 0x0c, 0xba, 0x61, 0x50, 0x0d, 0x61, 0x00, 0x35, 0x84, 0x01, 0xd4, 0x10, 0x06, 0x30, // A7..aP.a.5.....0
+ 0x62, 0xe0, 0x00, 0x20, 0x08, 0x06, 0x8d, 0x28, 0xb0, 0xc1, 0x19, 0x0c, 0x42, 0xd0, 0x30, 0x8b, // b.. ...(....B.0.
+ 0x82, 0x06, 0xb3, 0x04, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, // .............. .
+};
+static const uint8_t cs_blit_buffer_to_texture_mtl[1135] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x01, 0x01, 0xff, // .bgfx_blitDst...
+ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0x1a, 0x04, 0x00, // ................
+ 0x00, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x6c, // .#include .#includ
+ 0x65, 0x20, 0x3c, 0x73, 0x69, 0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, // e .
+ 0x0a, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, // .using namespace
+ 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, // metal;..struct
+ 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, // _Global.{. fl
+ 0x6f, 0x61, 0x74, 0x34, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, // oat4 bgfx_blitRe
+ 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x32, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, // gion[2];.};..str
+ 0x75, 0x63, 0x74, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, // uct bgfx_blitSrc
+ 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x5f, 0x64, // .{. float4 _d
+ 0x61, 0x74, 0x61, 0x5b, 0x31, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x6b, 0x65, 0x72, 0x6e, // ata[1];.};..kern
+ 0x65, 0x6c, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x78, 0x6c, 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x4d, // el void xlatMtlM
+ 0x61, 0x69, 0x6e, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x5f, 0x47, 0x6c, // ain(constant _Gl
+ 0x6f, 0x62, 0x61, 0x6c, 0x26, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x75, 0x20, 0x5b, 0x5b, 0x62, // obal& _mtl_u [[b
+ 0x75, 0x66, 0x66, 0x65, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, // uffer(0)]], cons
+ 0x74, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, // t device bgfx_bl
+ 0x69, 0x74, 0x53, 0x72, 0x63, 0x26, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // itSrc& bgfx_blit
+ 0x53, 0x72, 0x63, 0x5f, 0x31, 0x20, 0x5b, 0x5b, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x28, 0x31, // Src_1 [[buffer(1
+ 0x29, 0x5d, 0x5d, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x64, 0x5f, 0x61, // )]], texture2d_a
+ 0x72, 0x72, 0x61, 0x79, 0x3c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x63, 0x63, 0x65, // rray bgfx_
+ 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x20, 0x5b, 0x5b, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, // blitDst [[textur
+ 0x65, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x67, 0x6c, // e(0)]], uint3 gl
+ 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, // _GlobalInvocatio
+ 0x6e, 0x49, 0x44, 0x20, 0x5b, 0x5b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x70, 0x6f, 0x73, // nID [[thread_pos
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x67, 0x72, 0x69, 0x64, 0x5d, 0x5d, 0x29, // ition_in_grid]])
+ 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, // .{. do. {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x5f, 0x31, 0x35, // int3 _15
+ 0x39, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x75, 0x2e, // 9 = int3(_mtl_u.
+ 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, // bgfx_blitRegion[
+ 0x31, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // 1].xyz);.
+ 0x20, 0x69, 0x66, 0x20, 0x28, 0x28, 0x28, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, // if (((int3(gl_G
+ 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, // lobalInvocationI
+ 0x44, 0x29, 0x2e, 0x78, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x39, 0x2e, 0x78, 0x29, 0x20, // D).x >= _159.x)
+ 0x7c, 0x7c, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, // || (int3(gl_Glob
+ 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x2e, // alInvocationID).
+ 0x79, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x39, 0x2e, 0x79, 0x29, 0x29, 0x20, 0x7c, 0x7c, // y >= _159.y)) ||
+ 0x20, 0x28, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, // (int3(gl_Global
+ 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x2e, 0x7a, 0x20, // InvocationID).z
+ 0x3e, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x39, 0x2e, 0x7a, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, // >= _159.z)).
+ 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // {.
+ 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // break;.
+ 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x20, // }. int3
+ 0x5f, 0x32, 0x30, 0x33, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x5f, 0x6d, 0x74, 0x6c, // _203 = int3(_mtl
+ 0x5f, 0x75, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, // _u.bgfx_blitRegi
+ 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x69, 0x6e, 0x74, // on[0].xyz) + int
+ 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, // 3(gl_GlobalInvoc
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // ationID);.
+ 0x20, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x2e, 0x77, // bgfx_blitDst.w
+ 0x72, 0x69, 0x74, 0x65, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, // rite(bgfx_blitSr
+ 0x63, 0x5f, 0x31, 0x2e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5b, 0x28, 0x28, 0x69, 0x6e, 0x74, 0x33, // c_1._data[((int3
+ 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, // (gl_GlobalInvoca
+ 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x69, 0x6e, 0x74, 0x28, // tionID).z * int(
+ 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x75, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // _mtl_u.bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x20, 0x2b, 0x20, // Region[1].w)) +
+ 0x28, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, // (int3(gl_GlobalI
+ 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x2e, 0x79, 0x20, 0x2a, // nvocationID).y *
+ 0x20, 0x69, 0x6e, 0x74, 0x28, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x75, 0x2e, 0x62, 0x67, 0x66, 0x78, // int(_mtl_u.bgfx
+ 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x77, // _blitRegion[0].w
+ 0x29, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, // ))) + int3(gl_Gl
+ 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, // obalInvocationID
+ 0x29, 0x2e, 0x78, 0x5d, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x5f, 0x32, 0x30, 0x33, // ).x], uint2(_203
+ 0x2e, 0x78, 0x79, 0x29, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x5f, 0x32, 0x30, 0x33, 0x2e, // .xy), uint(_203.
+ 0x7a, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, // z));. bre
+ 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x28, // ak;. } while(
+ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, 0x00, 0x30, 0x00, // false);.}....0.
+};
+extern const uint8_t* cs_blit_buffer_to_texture_pssl;
+extern const uint32_t cs_blit_buffer_to_texture_pssl_size;
diff --git a/src/cs_blit_buffer_to_texture.sc b/src/cs_blit_buffer_to_texture.sc
new file mode 100644
index 000000000..2105fb360
--- /dev/null
+++ b/src/cs_blit_buffer_to_texture.sc
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011-2026 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
+ */
+
+#include "bgfx_compute.sh"
+
+BUFFER_RO(bgfx_blitSrc, vec4, 0);
+IMAGE2D_ARRAY_WO(bgfx_blitDst, rgba32f, 0);
+
+uniform vec4 bgfx_blitRegion[2];
+
+#define bgfx_dstOrigin ivec3(bgfx_blitRegion[0].xyz)
+#define bgfx_blitSize ivec3(bgfx_blitRegion[1].xyz)
+#define bgfx_blitRowPitch int(bgfx_blitRegion[0].w)
+#define bgfx_blitSlicePitch int(bgfx_blitRegion[1].w)
+
+NUM_THREADS(8, 8, 1)
+void main()
+{
+ ivec3 coord = ivec3(gl_GlobalInvocationID.xyz);
+
+ if (coord.x >= bgfx_blitSize.x
+ || coord.y >= bgfx_blitSize.y
+ || coord.z >= bgfx_blitSize.z)
+ {
+ return;
+ }
+
+ int index = coord.z * bgfx_blitSlicePitch + coord.y * bgfx_blitRowPitch + coord.x;
+
+ imageStore(bgfx_blitDst, bgfx_dstOrigin + coord, bgfx_blitSrc[index]);
+}
diff --git a/src/cs_blit_texture_to_buffer.bin.h b/src/cs_blit_texture_to_buffer.bin.h
new file mode 100644
index 000000000..a4de535f8
--- /dev/null
+++ b/src/cs_blit_texture_to_buffer.bin.h
@@ -0,0 +1,605 @@
+static const uint8_t cs_blit_texture_to_buffer_glsl[1085] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x08, 0x04, 0x00, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // ....layout(local
+ 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x78, 0x20, 0x3d, 0x20, 0x38, 0x2c, 0x20, 0x6c, 0x6f, 0x63, // _size_x = 8, loc
+ 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x79, 0x20, 0x3d, 0x20, 0x38, 0x2c, 0x20, 0x6c, // al_size_y = 8, l
+ 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x7a, 0x20, 0x3d, 0x20, 0x31, 0x29, // ocal_size_z = 1)
+ 0x20, 0x69, 0x6e, 0x3b, 0x0a, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x62, 0x69, 0x6e, // in;..layout(bin
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x73, 0x74, 0x64, 0x34, 0x33, 0x30, // ding = 0, std430
+ 0x29, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x75, 0x66, 0x66, // ) writeonly buff
+ 0x65, 0x72, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x42, // er bgfx_blitDstB
+ 0x75, 0x66, 0x66, 0x65, 0x72, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x63, 0x34, // uffer.{. vec4
+ 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x5b, 0x5d, 0x3b, // bgfx_blitDst[];
+ 0x0a, 0x7d, 0x20, 0x5f, 0x31, 0x30, 0x30, 0x3b, 0x0a, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, // .} _100;..unifor
+ 0x6d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // m vec4 bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x32, 0x5d, 0x3b, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, // Region[2];.layou
+ 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, // t(location = 0,
+ 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x72, 0x67, 0x62, // binding = 0, rgb
+ 0x61, 0x33, 0x32, 0x66, 0x29, 0x20, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x72, 0x65, // a32f) uniform re
+ 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x32, 0x44, 0x41, 0x72, // adonly image2DAr
+ 0x72, 0x61, 0x79, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, // ray bgfx_blitSrc
+ 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, // ;..void main().{
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, // . do. {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x31, 0x35, 0x20, // ivec3 _15
+ 0x3d, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, // = ivec3(gl_Globa
+ 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x3b, 0x0a, // lInvocationID);.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x5f, 0x32, 0x30, 0x20, // int _20
+ 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // = _15.x;.
+ 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x33, 0x33, 0x20, 0x3d, 0x20, 0x69, 0x76, 0x65, // ivec3 _33 = ive
+ 0x63, 0x33, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, // c3(bgfx_blitRegi
+ 0x6f, 0x6e, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, // on[1].xyz);.
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x33, 0x35, 0x20, 0x3d, 0x20, 0x5f, // bool _35 = _
+ 0x32, 0x30, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, // 20 >= _33.x;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x34, 0x38, 0x3b, 0x0a, 0x20, // bool _48;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x33, 0x35, 0x29, // if (!_35)
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // . {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x34, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x31, 0x35, // _48 = _15
+ 0x2e, 0x79, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, // .y >= _33.y;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, // }. e
+ 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, // lse. {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x34, 0x38, 0x20, 0x3d, 0x20, // _48 =
+ 0x5f, 0x33, 0x35, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, // _35;. }.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, 0x36, 0x30, 0x3b, // bool _60;
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x5f, 0x34, // . if (!_4
+ 0x38, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, // 8). {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x36, 0x30, 0x20, 0x3d, 0x20, 0x5f, // _60 = _
+ 0x31, 0x35, 0x2e, 0x7a, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, // 15.z >= _33.z;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // }.
+ 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, // else. {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x36, 0x30, 0x20, // _60
+ 0x3d, 0x20, 0x5f, 0x34, 0x38, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, // = _48;. }
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x5f, 0x36, 0x30, // . if (_60
+ 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, // ). {.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, // break;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // }.
+ 0x20, 0x5f, 0x31, 0x30, 0x30, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, // _100.bgfx_blitD
+ 0x73, 0x74, 0x5b, 0x28, 0x28, 0x5f, 0x31, 0x35, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x69, 0x6e, 0x74, // st[((_15.z * int
+ 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, // (bgfx_blitRegion
+ 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x28, 0x5f, 0x31, 0x35, 0x2e, 0x79, // [1].w)) + (_15.y
+ 0x20, 0x2a, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // * int(bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x20, 0x2b, // Region[0].w))) +
+ 0x20, 0x5f, 0x32, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x4c, 0x6f, 0x61, // _20] = imageLoa
+ 0x64, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x2c, 0x20, // d(bgfx_blitSrc,
+ 0x69, 0x76, 0x65, 0x63, 0x33, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, // ivec3(bgfx_blitR
+ 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, // egion[0].xyz) +
+ 0x5f, 0x31, 0x35, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, // _15);. br
+ 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, // eak;. } while
+ 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // (false);.}...
+};
+static const uint8_t cs_blit_texture_to_buffer_essl[1091] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x0e, 0x04, 0x00, 0x00, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // ....layout(local
+ 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x78, 0x20, 0x3d, 0x20, 0x38, 0x2c, 0x20, 0x6c, 0x6f, 0x63, // _size_x = 8, loc
+ 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x79, 0x20, 0x3d, 0x20, 0x38, 0x2c, 0x20, 0x6c, // al_size_y = 8, l
+ 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x7a, 0x20, 0x3d, 0x20, 0x31, 0x29, // ocal_size_z = 1)
+ 0x20, 0x69, 0x6e, 0x3b, 0x0a, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x28, 0x62, 0x69, 0x6e, // in;..layout(bin
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x73, 0x74, 0x64, 0x34, 0x33, 0x30, // ding = 0, std430
+ 0x29, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x75, 0x66, 0x66, // ) writeonly buff
+ 0x65, 0x72, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x42, // er bgfx_blitDstB
+ 0x75, 0x66, 0x66, 0x65, 0x72, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x63, 0x34, // uffer.{. vec4
+ 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x5b, 0x5d, 0x3b, // bgfx_blitDst[];
+ 0x0a, 0x7d, 0x20, 0x5f, 0x31, 0x30, 0x30, 0x3b, 0x0a, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, // .} _100;..unifor
+ 0x6d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // m vec4 bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x32, 0x5d, 0x3b, 0x0a, 0x6c, 0x61, 0x79, 0x6f, 0x75, // Region[2];.layou
+ 0x74, 0x28, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, // t(location = 0,
+ 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x72, 0x67, 0x62, // binding = 0, rgb
+ 0x61, 0x33, 0x32, 0x66, 0x29, 0x20, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x72, 0x65, // a32f) uniform re
+ 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x69, 0x6d, 0x61, // adonly highp ima
+ 0x67, 0x65, 0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, // ge2DArray bgfx_b
+ 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, // litSrc;..void ma
+ 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, // in().{. do.
+ 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x76, 0x65, 0x63, // {. ivec
+ 0x33, 0x20, 0x5f, 0x31, 0x35, 0x20, 0x3d, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x28, 0x67, 0x6c, // 3 _15 = ivec3(gl
+ 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, // _GlobalInvocatio
+ 0x6e, 0x49, 0x44, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, // nID);. in
+ 0x74, 0x20, 0x5f, 0x32, 0x30, 0x20, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x2e, 0x78, 0x3b, 0x0a, 0x20, // t _20 = _15.x;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x20, 0x5f, 0x33, 0x33, // ivec3 _33
+ 0x20, 0x3d, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, // = ivec3(bgfx_bl
+ 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, // itRegion[1].xyz)
+ 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x5f, // ;. bool _
+ 0x33, 0x35, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x30, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, // 35 = _20 >= _33.
+ 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, // x;. bool
+ 0x5f, 0x34, 0x38, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, // _48;. if
+ 0x28, 0x21, 0x5f, 0x33, 0x35, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, // (!_35). {
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x34, 0x38, // . _48
+ 0x20, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x2e, 0x79, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, 0x33, 0x2e, // = _15.y >= _33.
+ 0x79, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, // y;. }.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // else.
+ 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // {.
+ 0x5f, 0x34, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x33, 0x35, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // _48 = _35;.
+ 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x6f, // }. boo
+ 0x6c, 0x20, 0x5f, 0x36, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, // l _60;. i
+ 0x66, 0x20, 0x28, 0x21, 0x5f, 0x34, 0x38, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // f (!_48).
+ 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, // {. _
+ 0x36, 0x30, 0x20, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x2e, 0x7a, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x33, // 60 = _15.z >= _3
+ 0x33, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, // 3.z;. }.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, // else.
+ 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // {.
+ 0x20, 0x20, 0x5f, 0x36, 0x30, 0x20, 0x3d, 0x20, 0x5f, 0x34, 0x38, 0x3b, 0x0a, 0x20, 0x20, 0x20, // _60 = _48;.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, // }. i
+ 0x66, 0x20, 0x28, 0x5f, 0x36, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // f (_60).
+ 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, // {. br
+ 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, // eak;. }.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x31, 0x30, 0x30, 0x2e, 0x62, 0x67, 0x66, 0x78, // _100.bgfx
+ 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x5b, 0x28, 0x28, 0x5f, 0x31, 0x35, 0x2e, 0x7a, // _blitDst[((_15.z
+ 0x20, 0x2a, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // * int(bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x20, 0x2b, 0x20, // Region[1].w)) +
+ 0x28, 0x5f, 0x31, 0x35, 0x2e, 0x79, 0x20, 0x2a, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x62, 0x67, 0x66, // (_15.y * int(bgf
+ 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, // x_blitRegion[0].
+ 0x77, 0x29, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x5f, 0x32, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x69, 0x6d, // w))) + _20] = im
+ 0x61, 0x67, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x28, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // ageLoad(bgfx_bli
+ 0x74, 0x53, 0x72, 0x63, 0x2c, 0x20, 0x69, 0x76, 0x65, 0x63, 0x33, 0x28, 0x62, 0x67, 0x66, 0x78, // tSrc, ivec3(bgfx
+ 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x78, // _blitRegion[0].x
+ 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x5f, 0x31, 0x35, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, // yz) + _15);.
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, // break;. }
+ 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0a, 0x7d, // while(false);.}
+ 0x0a, 0x0a, 0x00, // ...
+};
+static const uint8_t cs_blit_texture_to_buffer_spv[1934] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x20, 0x00, 0x02, // .bgfx_blitSrc ..
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x55, 0x00, 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // .....U..bgfx_bli
+ 0x74, 0x44, 0x73, 0x74, 0x01, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x07, // tDst..........(.
+ 0x00, 0x00, 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00, 0xd7, 0x00, // ....#...........
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, // ................
+ 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, // ......GLSL.std.4
+ 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // 50..............
+ 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, // ..............ma
+ 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, // in....s.........
+ 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, // ................
+ 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x05, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x05, 0x00, // ................
+ 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, // ......main......
+ 0x06, 0x00, 0x25, 0x00, 0x00, 0x00, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x42, 0x6c, 0x6f, // ..%...UniformBlo
+ 0x63, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, // ck........%.....
+ 0x00, 0x00, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, // ..bgfx_blitRegio
+ 0x6e, 0x00, 0x05, 0x00, 0x03, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, // n.....'.........
+ 0x06, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, // ..L...bgfx_blitS
+ 0x72, 0x63, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x62, 0x67, // rc........k...bg
+ 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, // fx_blitDst......
+ 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x64, 0x61, 0x74, 0x61, 0x00, // ..k.......@data.
+ 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, // ......m...bgfx_b
+ 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 0x00, 0x73, 0x00, // litDst........s.
+ 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, // ..gl_GlobalInvoc
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x24, 0x00, // ationID...G...$.
+ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x25, 0x00, // ..........G...%.
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, // ......H...%.....
+ 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x27, 0x00, // ..#.......G...'.
+ 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x27, 0x00, // ..!.......G...'.
+ 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4c, 0x00, // ..".......G...L.
+ 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4c, 0x00, // ..!.......G...L.
+ 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6a, 0x00, // ..".......G...j.
+ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x6b, 0x00, // ..........G...k.
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, // ......H...k.....
+ 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6d, 0x00, // ..#.......G...m.
+ 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6d, 0x00, // ..!.......G...m.
+ 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x73, 0x00, // ..".......G...s.
+ 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, // ................
+ 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, // ..!.............
+ 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x09, 0x00, // ...... .........
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0a, 0x00, // .. .............
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0c, 0x00, // ................
+ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, // ..........+.....
+ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x1e, 0x00, // ................
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1e, 0x00, // .. .......+.....
+ 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1e, 0x00, // ..........+.....
+ 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x24, 0x00, // ..#...........$.
+ 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x25, 0x00, // ......#.......%.
+ 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x02, 0x00, // ..$... ...&.....
+ 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, // ..%...;...&...'.
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x28, 0x00, // ......+.......(.
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x06, 0x00, // ..........).....
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x02, 0x00, // ...... ...*.....
+ 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x19, 0x00, // ..........0.....
+ 0x09, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // ..J.............
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, // ................
+ 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, // .. ...K.......J.
+ 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, // ..;...K...L.....
+ 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x03, 0x00, // ..+.......Z.....
+ 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, // .. ...[.........
+ 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1e, 0x00, // ......j.........
+ 0x03, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x6c, 0x00, // ..k...j... ...l.
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x6c, 0x00, // ......k...;...l.
+ 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x72, 0x00, // ..m....... ...r.
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x72, 0x00, // ..........;...r.
+ 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, // ..s.......6.....
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, // ................
+ 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x74, 0x00, // ......=.......t.
+ 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, // ..s.............
+ 0x00, 0x00, 0xfb, 0x00, 0x03, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xf8, 0x00, // ................
+ 0x02, 0x00, 0x98, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x9b, 0x00, // ......Q.........
+ 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x2a, 0x00, // ..t.......A...*.
+ 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x28, 0x00, // ......'.......(.
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9c, 0x00, // ..=.............
+ 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x29, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x9d, 0x00, // ..O...).........
+ 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, // ................
+ 0x00, 0x00, 0x6e, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x9e, 0x00, // ..n.............
+ 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x9f, 0x00, // ..Q.............
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xa1, 0x00, // ..........0.....
+ 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, // ..........Q.....
+ 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, // ......t.......Q.
+ 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x01, 0x00, // ................
+ 0x00, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xa3, 0x00, // ......0.........
+ 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xaa, 0x00, // ..........0.....
+ 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x09, 0x00, // ..........Q.....
+ 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x51, 0x00, // ......t.......Q.
+ 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x02, 0x00, // ................
+ 0x00, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xac, 0x00, // ......0.........
+ 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xb3, 0x00, // ..........0.....
+ 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xb5, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xb3, 0x00, 0x00, 0x00, 0xb4, 0x00, // ................
+ 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xf9, 0x00, // ................
+ 0x02, 0x00, 0xd1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x41, 0x00, // ..............A.
+ 0x06, 0x00, 0x2a, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x18, 0x00, // ..*.......'.....
+ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xb7, 0x00, // ......=.........
+ 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x08, 0x00, 0x29, 0x00, 0x00, 0x00, 0xb8, 0x00, // ......O...).....
+ 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // ................
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xb9, 0x00, // ......n.........
+ 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xbb, 0x00, // ................
+ 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x4a, 0x00, // ......t...=...J.
+ 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x07, 0x00, 0x0c, 0x00, // ......L..._.....
+ 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x02, 0x00, // ................
+ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5b, 0x00, 0x00, 0x00, 0xc0, 0x00, // ......A...[.....
+ 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x5a, 0x00, // ..'.......(...Z.
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xc0, 0x00, // ..=.............
+ 0x00, 0x00, 0x6e, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xc1, 0x00, // ..n.............
+ 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xac, 0x00, // ................
+ 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x41, 0x00, 0x07, 0x00, 0x5b, 0x00, 0x00, 0x00, 0xc6, 0x00, // ......A...[.....
+ 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x5a, 0x00, // ..'...........Z.
+ 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0xc6, 0x00, // ..=.............
+ 0x00, 0x00, 0x6e, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc7, 0x00, // ..n.............
+ 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0xa3, 0x00, // ................
+ 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0xca, 0x00, // ................
+ 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x09, 0x00, // ................
+ 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x41, 0x00, // ..............A.
+ 0x06, 0x00, 0x2a, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x18, 0x00, // ..*.......m.....
+ 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xd6, 0x00, // ......>.........
+ 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xd1, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xd1, 0x00, // ................
+ 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, // ......8..... .
+};
+static const uint8_t cs_blit_texture_to_buffer_wgsl[1157] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x20, 0x00, 0x02, // .bgfx_blitSrc ..
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x55, 0x00, 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // .....U..bgfx_bli
+ 0x74, 0x44, 0x73, 0x74, 0x01, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x04, // tDst............
+ 0x00, 0x00, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x28, 0x6f, 0x66, 0x66, // ..diagnostic(off
+ 0x2c, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x75, 0x6e, 0x69, // , derivative_uni
+ 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x74, 0x79, 0x29, 0x3b, 0x0a, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, // formity);.diagno
+ 0x73, 0x74, 0x69, 0x63, 0x28, 0x6f, 0x66, 0x66, 0x2c, 0x20, 0x73, 0x75, 0x62, 0x67, 0x72, 0x6f, // stic(off, subgro
+ 0x75, 0x70, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x74, 0x79, 0x29, 0x3b, 0x0a, // up_uniformity);.
+ 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x42, // .struct UniformB
+ 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, // lock {. bgfx_bl
+ 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x20, 0x3a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, // itRegion : array
+ 0x3c, 0x76, 0x65, 0x63, 0x34, 0x3c, 0x66, 0x33, 0x32, 0x3e, 0x2c, 0x20, 0x32, 0x75, 0x3e, 0x2c, // , 2u>,
+ 0x0a, 0x7d, 0x0a, 0x0a, 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x30, 0x75, 0x29, 0x20, 0x40, // .}..@group(0u) @
+ 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, 0x30, 0x75, 0x29, 0x20, 0x76, 0x61, 0x72, 0x3c, // binding(0u) var<
+ 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x20, 0x76, 0x20, 0x3a, 0x20, 0x55, 0x6e, 0x69, // uniform> v : Uni
+ 0x66, 0x6f, 0x72, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0a, 0x0a, 0x40, 0x67, 0x72, 0x6f, // formBlock;..@gro
+ 0x75, 0x70, 0x28, 0x30, 0x75, 0x29, 0x20, 0x40, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x28, // up(0u) @binding(
+ 0x32, 0x75, 0x29, 0x20, 0x76, 0x61, 0x72, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // 2u) var bgfx_bli
+ 0x74, 0x53, 0x72, 0x63, 0x20, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x32, // tSrc : texture_2
+ 0x64, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3c, 0x66, 0x33, 0x32, 0x3e, 0x3b, 0x0a, 0x0a, 0x73, // d_array;..s
+ 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, // truct bgfx_blitD
+ 0x73, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x6d, 0x20, 0x3a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, // st {. m : array
+ 0x3c, 0x76, 0x65, 0x63, 0x34, 0x3c, 0x66, 0x33, 0x32, 0x3e, 0x3e, 0x2c, 0x0a, 0x7d, 0x0a, 0x0a, // >,.}..
+ 0x40, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x28, 0x30, 0x75, 0x29, 0x20, 0x40, 0x62, 0x69, 0x6e, 0x64, // @group(0u) @bind
+ 0x69, 0x6e, 0x67, 0x28, 0x33, 0x75, 0x29, 0x20, 0x76, 0x61, 0x72, 0x3c, 0x73, 0x74, 0x6f, 0x72, // ing(3u) var
+ 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x5f, 0x31, 0x20, // bgfx_blitDst_1
+ 0x3a, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x3b, 0x0a, // : bgfx_blitDst;.
+ 0x0a, 0x40, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x20, 0x40, 0x77, 0x6f, 0x72, 0x6b, 0x67, // .@compute @workg
+ 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x38, 0x75, 0x2c, 0x20, 0x38, 0x75, // roup_size(8u, 8u
+ 0x2c, 0x20, 0x31, 0x75, 0x29, 0x0a, 0x66, 0x6e, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x40, 0x62, // , 1u).fn main(@b
+ 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x28, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69, 0x6e, // uiltin(global_in
+ 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x29, 0x20, 0x67, 0x6c, 0x5f, // vocation_id) gl_
+ 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, // GlobalInvocation
+ 0x49, 0x44, 0x20, 0x3a, 0x20, 0x76, 0x65, 0x63, 0x33, 0x3c, 0x75, 0x33, 0x32, 0x3e, 0x29, 0x20, // ID : vec3)
+ 0x7b, 0x0a, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x76, 0x65, // {. let v_1 = ve
+ 0x63, 0x33, 0x3c, 0x69, 0x33, 0x32, 0x3e, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, // c3(gl_Globa
+ 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x3b, 0x0a, // lInvocationID);.
+ 0x20, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x28, 0x30, 0x75, 0x29, 0x20, 0x7b, 0x0a, 0x20, // switch(0u) {.
+ 0x20, 0x20, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3a, 0x20, 0x7b, 0x0a, 0x20, 0x20, // default: {.
+ 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x32, 0x20, 0x3d, 0x20, 0x76, 0x5f, // let v_2 = v_
+ 0x31, 0x2e, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, // 1.x;. let v
+ 0x5f, 0x33, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x33, 0x3c, 0x69, 0x33, 0x32, 0x3e, 0x28, 0x76, // _3 = vec3(v
+ 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, // .bgfx_blitRegion
+ 0x5b, 0x31, 0x69, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // [1i].xyz);.
+ 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x34, 0x20, 0x3d, 0x20, 0x76, 0x5f, 0x31, 0x2e, 0x79, // let v_4 = v_1.y
+ 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x35, 0x20, // ;. let v_5
+ 0x3d, 0x20, 0x76, 0x5f, 0x31, 0x2e, 0x7a, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, // = v_1.z;. i
+ 0x66, 0x20, 0x28, 0x28, 0x28, 0x28, 0x76, 0x5f, 0x32, 0x20, 0x3e, 0x3d, 0x20, 0x76, 0x5f, 0x33, // f ((((v_2 >= v_3
+ 0x2e, 0x78, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x76, 0x5f, 0x34, 0x20, 0x3e, 0x3d, 0x20, 0x76, 0x5f, // .x) | (v_4 >= v_
+ 0x33, 0x2e, 0x79, 0x29, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x76, 0x5f, 0x35, 0x20, 0x3e, 0x3d, 0x20, // 3.y)) | (v_5 >=
+ 0x76, 0x5f, 0x33, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // v_3.z))) {.
+ 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // break;.
+ 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x36, 0x20, // }. let v_6
+ 0x3d, 0x20, 0x28, 0x76, 0x65, 0x63, 0x33, 0x3c, 0x69, 0x33, 0x32, 0x3e, 0x28, 0x76, 0x2e, 0x62, // = (vec3(v.b
+ 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, // gfx_blitRegion[0
+ 0x69, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x76, 0x5f, 0x31, 0x29, 0x3b, 0x0a, // i].xyz) + v_1);.
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x76, 0x5f, 0x37, 0x20, 0x3d, 0x20, // let v_7 =
+ 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x28, 0x62, 0x67, 0x66, 0x78, // textureLoad(bgfx
+ 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x2c, 0x20, 0x76, 0x5f, 0x36, 0x2e, 0x78, 0x79, // _blitSrc, v_6.xy
+ 0x2c, 0x20, 0x76, 0x5f, 0x36, 0x2e, 0x7a, 0x2c, 0x20, 0x30, 0x69, 0x29, 0x3b, 0x0a, 0x20, 0x20, // , v_6.z, 0i);.
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, // bgfx_blitDst
+ 0x5f, 0x31, 0x2e, 0x6d, 0x5b, 0x28, 0x28, 0x28, 0x76, 0x5f, 0x35, 0x20, 0x2a, 0x20, 0x69, 0x33, // _1.m[(((v_5 * i3
+ 0x32, 0x28, 0x76, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, // 2(v.bgfx_blitReg
+ 0x69, 0x6f, 0x6e, 0x5b, 0x31, 0x69, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x28, 0x76, // ion[1i].w)) + (v
+ 0x5f, 0x34, 0x20, 0x2a, 0x20, 0x69, 0x33, 0x32, 0x28, 0x76, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, // _4 * i32(v.bgfx_
+ 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x69, 0x5d, 0x2e, 0x77, // blitRegion[0i].w
+ 0x29, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x76, 0x5f, 0x32, 0x29, 0x5d, 0x20, 0x3d, 0x20, 0x76, 0x5f, // ))) + v_2)] = v_
+ 0x37, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x7d, 0x0a, 0x00, // 7;. }. }.}..
+ 0x00, 0x20, 0x00, 0x20, 0x00, // . . .
+};
+static const uint8_t cs_blit_texture_to_buffer_dxbc[600] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x20, 0x02, 0x00, 0x00, 0x44, 0x58, 0x42, 0x43, 0x4a, 0xa4, 0xd9, 0xa6, 0x0e, 0x9d, 0xe4, 0x93, // ...DXBCJ.......
+ 0x67, 0xae, 0x4f, 0x97, 0x35, 0x81, 0x16, 0x25, 0x01, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, // g.O.5..%.... ...
+ 0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, // ....,...<...L...
+ 0x49, 0x53, 0x47, 0x4e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // ISGN............
+ 0x4f, 0x53, 0x47, 0x4e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // OSGN............
+ 0x53, 0x48, 0x45, 0x58, 0xcc, 0x01, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x73, 0x00, 0x00, 0x00, // SHEX....P...s...
+ 0x6a, 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, // j...Y...F. .....
+ 0x02, 0x00, 0x00, 0x00, 0x58, 0x40, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ....X@...p......
+ 0x55, 0x55, 0x00, 0x00, 0x9c, 0x08, 0x00, 0x04, 0x00, 0xe0, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, // UU..............
+ 0x55, 0x55, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x02, 0x72, 0x00, 0x02, 0x00, 0x68, 0x00, 0x00, 0x02, // UU.._...r...h...
+ 0x02, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // ................
+ 0x01, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x06, 0x72, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ........r.......
+ 0x46, 0x82, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x06, // F. .........!...
+ 0x72, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x02, 0x02, 0x00, 0x46, 0x02, 0x10, 0x00, // r.......F...F...
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ....<...........
+ 0x1a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x3c, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, // <...........*...
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, // ................
+ 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, // ........>.......
+ 0x1b, 0x00, 0x00, 0x06, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, // ............F. .
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x06, 0x72, 0x00, 0x10, 0x00, // ............r...
+ 0x01, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x02, 0x02, 0x00, // ....F.......F...
+ 0x36, 0x00, 0x00, 0x05, 0x82, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, // 6............@..
+ 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x89, 0x02, 0x02, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, // ....-.......CU..
+ 0xf2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, // ........F.......
+ 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x06, 0x12, 0x00, 0x10, 0x00, // F~..............
+ 0x00, 0x00, 0x00, 0x00, 0x3a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // ....:. .........
+ 0x26, 0x00, 0x00, 0x07, 0x00, 0xd0, 0x00, 0x00, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // &.......".......
+ 0x3a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x02, 0x00, 0x23, 0x00, 0x00, 0x08, // :...........#...
+ 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x10, 0x00, // ........*.......
+ 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x06, // ................
+ 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x0a, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x00, 0x07, 0xf2, 0xe0, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, // ........F.......
+ 0x3e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, // >..... .
+};
+static const uint8_t cs_blit_texture_to_buffer_dxil[2244] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x8c, 0x08, 0x00, 0x00, 0x44, 0x58, 0x42, 0x43, 0xf1, 0xca, 0xe7, 0x0d, 0xef, 0xc9, 0x24, 0xf0, // ....DXBC......$.
+ 0x1f, 0xf7, 0x4f, 0x1d, 0x92, 0xbe, 0xd6, 0xa7, 0x01, 0x00, 0x00, 0x00, 0x8c, 0x08, 0x00, 0x00, // ..O.............
+ 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, // ....<...L.......
+ 0x6c, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, // l.......D...`...
+ 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SFI0............
+ 0x49, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // ISG1............
+ 0x4f, 0x53, 0x47, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // OSG1............
+ 0x50, 0x53, 0x56, 0x30, 0x9c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PSV0....8.......
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, // ................
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, // .........main...
+ 0x00, 0x00, 0x00, 0x00, 0x49, 0x4c, 0x44, 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, // ....ILDN,.....$.
+ 0x38, 0x62, 0x63, 0x61, 0x35, 0x33, 0x34, 0x65, 0x33, 0x35, 0x36, 0x65, 0x64, 0x33, 0x34, 0x37, // 8bca534e356ed347
+ 0x36, 0x63, 0x30, 0x33, 0x61, 0x32, 0x65, 0x34, 0x63, 0x65, 0x62, 0x30, 0x36, 0x62, 0x39, 0x34, // 6c03a2e4ceb06b94
+ 0x2e, 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, // .pdb....HASH....
+ 0x00, 0x00, 0x00, 0x00, 0x8b, 0xca, 0x53, 0x4e, 0x35, 0x6e, 0xd3, 0x47, 0x6c, 0x03, 0xa2, 0xe4, // ......SN5n.Gl...
+ 0xce, 0xb0, 0x6b, 0x94, 0x44, 0x58, 0x49, 0x4c, 0x24, 0x07, 0x00, 0x00, 0x60, 0x00, 0x05, 0x00, // ..k.DXIL$...`...
+ 0xc9, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // ....DXIL........
+ 0x0c, 0x07, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, // ....BC..!.......
+ 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, // .. ...........#.
+ 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, // A..I..29....%...
+ 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, // ...b..E.B..B..2.
+ 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, // 8..K.2b.H.. CF..
+ 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, // ..2B.H...#.PAQ..
+ 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // .....1F.Q.......
+ 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, // ........@.......
+ 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, // ... m0..........
+ 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, // I.........`B L..
+ 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x32, 0x22, 0x88, 0x09, // ..... ..]...2"..
+ 0x20, 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04, 0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, // d...#....#.....
+ 0x12, 0x4c, 0x8c, 0x8c, 0x0b, 0x84, 0xc4, 0x4c, 0x10, 0x80, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, // .L.....L....@...
+ 0xe6, 0x08, 0xc0, 0xa0, 0x0c, 0xc3, 0x30, 0x10, 0x31, 0x47, 0x80, 0x90, 0x71, 0xcf, 0x70, 0xf9, // ......0.1G..q.p.
+ 0x13, 0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, 0x28, 0x38, 0x66, 0x00, 0x8a, 0x02, 0x0c, // .........(8f....
+ 0xc8, 0x30, 0x24, 0x49, 0x92, 0x18, 0xa4, 0xdc, 0x34, 0x5c, 0xfe, 0x84, 0x3d, 0x84, 0xe4, 0xaf, // .0$I....4...=...
+ 0x84, 0xb4, 0x12, 0x93, 0x5f, 0xdc, 0x36, 0x2a, 0x92, 0x24, 0x49, 0x86, 0xa2, 0x30, 0x03, 0x32, // ...._.6*.$I..0.2
+ 0x0c, 0xc3, 0x30, 0x0c, 0x03, 0x35, 0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, // ..0..5G..?a.!..F
+ 0x15, 0x2b, 0x31, 0xf9, 0xc5, 0x6d, 0x23, 0x22, 0x49, 0x92, 0xa4, 0x10, 0xcf, 0x80, 0x0c, 0x04, // .+1..m#"I.......
+ 0xcd, 0x11, 0x04, 0xc5, 0x40, 0x06, 0x63, 0x18, 0x24, 0x9a, 0x06, 0x02, 0x86, 0x11, 0x88, 0x64, // ....@.c.$......d
+ 0x26, 0x39, 0x18, 0x07, 0x76, 0x08, 0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, // &9..v..y..7..r..
+ 0x7a, 0xa8, 0x07, 0x79, 0x28, 0x07, 0x39, 0x20, 0x85, 0x50, 0x90, 0x07, 0x79, 0x08, 0x87, 0x7c, // z..y(.9 .P..y..|
+ 0xe0, 0x03, 0x7b, 0x28, 0x87, 0x71, 0xa0, 0x87, 0x77, 0x90, 0x07, 0x3e, 0x30, 0x07, 0x76, 0x78, // ..{(.q..w..>0.vx
+ 0x87, 0x70, 0xa0, 0x07, 0x36, 0x00, 0x03, 0x3a, 0xf0, 0x03, 0x30, 0xf0, 0x03, 0x3d, 0xd0, 0x83, // .p..6..:..0..=..
+ 0x76, 0x48, 0x07, 0x78, 0x98, 0x87, 0x5f, 0xa0, 0x87, 0x7c, 0x80, 0x87, 0x72, 0x40, 0xc1, 0x30, // vH.x.._..|..r@.0
+ 0xd3, 0x19, 0x8c, 0x03, 0x3b, 0x84, 0xc3, 0x3c, 0xcc, 0x83, 0x1b, 0xd0, 0x42, 0x39, 0xe0, 0x03, // ....;..<....B9..
+ 0x3d, 0xd4, 0x83, 0x3c, 0x94, 0x83, 0x1c, 0x90, 0x42, 0x28, 0xc8, 0x83, 0x3c, 0x84, 0x43, 0x3e, // =..<....B(..<.C>
+ 0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, // ..=..8..;.....;.
+ 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x01, 0x12, 0xac, 0x8b, // C8..............
+ 0xb0, 0x99, 0xc2, 0x60, 0x1c, 0xd8, 0x21, 0x1c, 0xe6, 0x61, 0x1e, 0xdc, 0x40, 0x16, 0x6e, 0x41, // ...`..!..a..@.nA
+ 0x14, 0xea, 0xc1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0x81, 0x0f, 0xec, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, // ................
+ 0xde, 0x41, 0x1e, 0xf8, 0xc0, 0x1c, 0xd8, 0xe1, 0x1d, 0xc2, 0x81, 0x1e, 0xd8, 0x00, 0x0c, 0xe8, // .A..............
+ 0xc0, 0x0f, 0xc0, 0xc0, 0x0f, 0x50, 0x60, 0x91, 0x96, 0x02, 0xd6, 0x4c, 0x08, 0x19, 0x9c, 0x02, // .....P`....L....
+ 0x3b, 0xbc, 0x83, 0x38, 0x84, 0x03, 0x3b, 0xcc, 0x03, 0x0a, 0x38, 0xea, 0xa6, 0x00, 0x00, 0x00, // ;..8..;...8.....
+ 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, // ..r..t`.6h.yh.r.
+ 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, // ...P.m..zP.m..z0
+ 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, // .r..s .m..q..s .
+ 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, // m..x..s .m..q`.z
+ 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, // 0.r...0.r..s .m.
+ 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, // .v@.z`.t.....v..
+ 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, // s .m`.s .z0.r...
+ 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, // `.t..v@.m..x..q`
+ 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, // .z0.r..v@.C.....
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x04, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, // ........<.......
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x14, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .....y. ........
+ 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, // ...4@.........0.
+ 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, // ...........`.3..
+ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x16, 0x08, 0x00, 0x0b, 0x00, 0x00, 0x00, // 0.......@.......
+ 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a, // 2.....L...&G..C.
+ 0x4a, 0x60, 0x04, 0xa0, 0x28, 0x8a, 0xa1, 0x1c, 0x4a, 0xa2, 0x80, 0x0a, 0xa1, 0x20, 0x48, 0x1a, // J`..(...J.... H.
+ 0x01, 0xa0, 0x6c, 0x06, 0x80, 0xb6, 0x19, 0x00, 0xf2, 0x66, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, // ..l......f..y...
+ 0x41, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x8f, 0x0c, 0x6f, 0xec, // A.....L.F.....o.
+ 0xed, 0x4d, 0x0c, 0x24, 0xc6, 0x25, 0x06, 0xc6, 0x45, 0xc6, 0x06, 0xa6, 0xc6, 0x65, 0xe6, 0x06, // .M.$.%..E....e..
+ 0x04, 0x65, 0x8c, 0x86, 0x0c, 0xc7, 0x8c, 0xc6, 0x2c, 0x27, 0x27, 0x65, 0x43, 0x10, 0x4c, 0x10, // .e......,''eC.L.
+ 0x06, 0x63, 0x82, 0x30, 0x1c, 0x1b, 0x84, 0x81, 0x98, 0x20, 0x0c, 0xc8, 0x06, 0x61, 0x30, 0x28, // .c.0..... ...a0(
+ 0x8c, 0xcd, 0x4d, 0x10, 0x86, 0x64, 0xc3, 0x80, 0x24, 0xc4, 0x04, 0x21, 0x83, 0x08, 0x4c, 0x10, // ..M..d..$..!..L.
+ 0x06, 0x65, 0x82, 0x30, 0x2c, 0x1b, 0x04, 0xc2, 0xd9, 0x90, 0x10, 0x0b, 0x43, 0x10, 0x43, 0x43, // .e.0,.......C.CC
+ 0x3c, 0x1b, 0x02, 0x68, 0x82, 0xb0, 0x45, 0x13, 0x04, 0xe9, 0xd9, 0xb0, 0x10, 0x12, 0x43, 0x10, // <..h..E.......C.
+ 0x83, 0x31, 0x4d, 0xd3, 0xb3, 0x21, 0xa0, 0x26, 0x08, 0x9e, 0x34, 0x41, 0x18, 0x98, 0x0d, 0x08, // .1M..!.&..4A....
+ 0x61, 0x31, 0x04, 0x31, 0x5c, 0xc0, 0x86, 0x00, 0xdb, 0x40, 0x44, 0x55, 0x06, 0x4c, 0x10, 0x04, // a1.1.....@DU.L..
+ 0x80, 0x44, 0x5b, 0x58, 0x9a, 0xdb, 0x04, 0x61, 0x68, 0x26, 0x08, 0x83, 0xb3, 0x61, 0xf0, 0xbc, // .D[X...ah&...a..
+ 0x61, 0x83, 0xd0, 0x7d, 0x1b, 0x8a, 0x8d, 0x03, 0x34, 0x30, 0xa8, 0xc2, 0xc6, 0x66, 0xd7, 0xe6, // a..}....40...f..
+ 0x92, 0x46, 0x56, 0xe6, 0x46, 0x37, 0x25, 0x08, 0xaa, 0x90, 0xe1, 0xb9, 0xd8, 0x95, 0xc9, 0xcd, // .FV.F7%.........
+ 0xa5, 0xbd, 0xb9, 0x4d, 0x09, 0x88, 0x26, 0x64, 0x78, 0x2e, 0x76, 0x61, 0x6c, 0x76, 0x65, 0x72, // ...M..&dx.valver
+ 0x53, 0x02, 0xa3, 0x0e, 0x19, 0x9e, 0xcb, 0x1c, 0x5a, 0x18, 0x59, 0x99, 0x5c, 0xd3, 0x1b, 0x59, // S.......Z.Y....Y
+ 0x19, 0xdb, 0x94, 0x20, 0x29, 0x43, 0x86, 0xe7, 0x22, 0x57, 0x36, 0xf7, 0x56, 0x27, 0x37, 0x56, // ... )C.."W6.V'7V
+ 0x36, 0x37, 0x25, 0xc8, 0xea, 0x90, 0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, 0xe5, 0x41, 0xbd, 0xa5, // 67%..........A..
+ 0xb9, 0xd1, 0xcd, 0x4d, 0x09, 0xc0, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, // ...M....y...Q...
+ 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, // 3......f..=.C8..
+ 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, // .B..yx.s.q......
+ 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, // ....3.B.......f0
+ 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, // .=.C8.....=.C=..
+ 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, // =.x.tp.{..yH.pp.
+ 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, // zp.vx.p ........
+ 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, // .0.n0.....P.3...
+ 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, // .!..!..a.f0.;..;
+ 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, // .C9..<..<..;...v
+ 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, // `.{h.7h.rh.7..p.
+ 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, // .p`.v(.v..vx.w..
+ 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, // _..q..r..y..,...
+ 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, // .......0.b......
+ 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, // .......a..!.....
+ 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, // a...C9.C9.C9.C9.
+ 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, // .8.C8..;../..<..
+ 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, // ;..;....!.|p.z(.
+ 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, // v....C..... ....
+ 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x30, 0x83, 0x81, // ..........P..0..
+ 0xc8, 0x01, 0x1f, 0xdc, 0x40, 0x1c, 0xe4, 0xa1, 0x1c, 0xc2, 0x61, 0x1d, 0xdc, 0x40, 0x1c, 0xe4, // ....@.....a..@..
+ 0x01, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x26, 0x50, 0x0d, 0x97, // ....q ......&P..
+ 0xef, 0x3c, 0x7e, 0x40, 0x15, 0x05, 0x11, 0xb1, 0x93, 0x13, 0x11, 0x7e, 0x71, 0xdb, 0x46, 0xb0, // .<~@.......~q.F.
+ 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10, 0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25, 0x61, 0x00, // ...<..PEAD...%a.
+ 0x02, 0xe6, 0x17, 0xb7, 0x6d, 0x05, 0xd2, 0x70, 0xf9, 0xce, 0xe3, 0x0b, 0x11, 0x01, 0x4c, 0x44, // ....m..p......LD
+ 0x08, 0x34, 0xc3, 0x42, 0xd8, 0x40, 0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0x13, 0x71, 0x4d, 0x54, 0x44, // .4.B.@5.....qMTD
+ 0x94, 0x0e, 0x30, 0xf8, 0xc5, 0x6d, 0x5b, 0x80, 0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0xd3, 0x11, 0x11, // ..0..m[.4.......
+ 0xc0, 0x20, 0x0e, 0x3e, 0x72, 0xdb, 0x06, 0x40, 0x30, 0x00, 0xd2, 0x00, 0x61, 0x20, 0x00, 0x00, // . .>r..@0...a ..
+ 0x46, 0x00, 0x00, 0x00, 0x13, 0x04, 0x45, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // F.....E,........
+ 0x34, 0xcc, 0x00, 0x94, 0x5c, 0xe9, 0x06, 0x94, 0x5d, 0x11, 0x14, 0x61, 0x40, 0x29, 0x06, 0x90, // 4.......]..a@)..
+ 0x51, 0x02, 0x23, 0x00, 0x45, 0x50, 0x1e, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x30, 0x65, // Q.#.EP..#....`0e
+ 0x0a, 0x71, 0x5d, 0xcf, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x4c, 0xda, 0x42, 0x60, 0x18, 0x34, // .q]..A.. .L.B`.4
+ 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xd3, 0xc6, 0x10, 0x59, 0x16, 0x8d, 0x18, 0x18, 0x00, 0x08, // b.. .....Y......
+ 0x82, 0x01, 0x01, 0x06, 0x8c, 0x36, 0x62, 0x60, 0x00, 0x20, 0x08, 0x06, 0x44, 0x18, 0x34, 0xdc, // .....6b`. ..D.4.
+ 0x88, 0x81, 0x01, 0x80, 0x20, 0x18, 0x10, 0x62, 0xe0, 0x30, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, // .... ..b.0#....`
+ 0x00, 0x81, 0x81, 0x43, 0x78, 0xa3, 0x09, 0x01, 0x70, 0xc1, 0x40, 0xc3, 0x0d, 0x46, 0x80, 0x06, // ...Cx...p.@..F..
+ 0xb3, 0x0c, 0x01, 0x11, 0x8c, 0x26, 0x10, 0xc1, 0x05, 0x03, 0x0d, 0x37, 0x20, 0x01, 0x1a, 0xcc, // .....&.....7 ...
+ 0x32, 0x08, 0x44, 0x30, 0x9a, 0x70, 0x08, 0x17, 0x0c, 0x34, 0xdc, 0xa0, 0x04, 0x68, 0x30, 0xcb, // 2.D0.p...4...h0.
+ 0x30, 0x10, 0xc1, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x40, 0x6a, 0x80, 0x39, 0x67, 0x30, 0x9a, // 0...... .@j.9g0.
+ 0x10, 0x00, 0xa3, 0x09, 0x42, 0x30, 0x9a, 0x30, 0x08, 0x37, 0x0c, 0x74, 0xc3, 0x40, 0x37, 0x0c, // ....B0.0.7.t.@7.
+ 0x54, 0x03, 0x05, 0x35, 0x50, 0x50, 0x03, 0x05, 0x23, 0x06, 0x0d, 0x00, 0x82, 0x60, 0xd0, 0xd4, // T..5PP..#....`..
+ 0x01, 0x18, 0x64, 0x71, 0x30, 0x08, 0x41, 0x19, 0x94, 0x41, 0x19, 0x8c, 0x26, 0x04, 0xc0, 0x68, // ..dq0.A..A..&..h
+ 0x82, 0x10, 0x8c, 0x26, 0x0c, 0xc2, 0x68, 0x02, 0x31, 0x8c, 0x26, 0x64, 0xc3, 0x05, 0x03, 0x59, // ...&..h.1.&d...Y
+ 0xc0, 0x89, 0x60, 0x34, 0x41, 0x1a, 0x2e, 0x18, 0xc8, 0x02, 0x30, 0x10, 0x41, 0x11, 0x62, 0x00, // ..`4A.....0.A.b.
+ 0x15, 0x08, 0x30, 0x62, 0xd0, 0x00, 0x20, 0x08, 0x06, 0xca, 0x28, 0xb0, 0xc1, 0x19, 0x04, 0x72, // ..0b.. ...(....r
+ 0xc0, 0x2c, 0x4a, 0x82, 0x06, 0xb3, 0x04, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .,J.............
+ 0x00, 0x00, 0x20, 0x00, // .. .
+};
+static const uint8_t cs_blit_texture_to_buffer_mtl[1140] =
+{
+ 0x43, 0x53, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CSH.............
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0f, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, // .......bgfx_blit
+ 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x02, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Region..........
+ 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x01, 0x01, 0xff, // .bgfx_blitSrc...
+ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // ........bgfx_bli
+ 0x74, 0x53, 0x72, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08, 0x00, // tSrc............
+ 0x08, 0x00, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, // ........#include
+ 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a, // .
+ 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69, 0x6d, 0x64, 0x2f, 0x73, // #include ..using na
+ 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a, // mespace metal;..
+ 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x0a, 0x7b, // struct _Global.{
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x62, 0x67, 0x66, 0x78, // . float4 bgfx
+ 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x32, 0x5d, 0x3b, 0x0a, // _blitRegion[2];.
+ 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, // };..struct bgfx_
+ 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, // blitDst.{. fl
+ 0x6f, 0x61, 0x74, 0x34, 0x20, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5b, 0x31, 0x5d, 0x3b, 0x0a, 0x7d, // oat4 _data[1];.}
+ 0x3b, 0x0a, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x78, // ;..kernel void x
+ 0x6c, 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x4d, 0x61, 0x69, 0x6e, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, // latMtlMain(const
+ 0x61, 0x6e, 0x74, 0x20, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x26, 0x20, 0x5f, 0x6d, 0x74, // ant _Global& _mt
+ 0x6c, 0x5f, 0x75, 0x20, 0x5b, 0x5b, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x28, 0x30, 0x29, 0x5d, // l_u [[buffer(0)]
+ 0x5d, 0x2c, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, // ], device bgfx_b
+ 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, 0x26, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, // litDst& bgfx_bli
+ 0x74, 0x44, 0x73, 0x74, 0x5f, 0x31, 0x20, 0x5b, 0x5b, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x28, // tDst_1 [[buffer(
+ 0x31, 0x29, 0x5d, 0x5d, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x64, 0x5f, // 1)]], texture2d_
+ 0x61, 0x72, 0x72, 0x61, 0x79, 0x3c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3e, 0x20, 0x62, 0x67, 0x66, // array bgf
+ 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, 0x72, 0x63, 0x20, 0x5b, 0x5b, 0x74, 0x65, 0x78, 0x74, // x_blitSrc [[text
+ 0x75, 0x72, 0x65, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x20, // ure(0)]], uint3
+ 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, // gl_GlobalInvocat
+ 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x20, 0x5b, 0x5b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x70, // ionID [[thread_p
+ 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x67, 0x72, 0x69, 0x64, 0x5d, // osition_in_grid]
+ 0x5d, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, // ]).{. do.
+ 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x20, 0x5f, // {. int3 _
+ 0x31, 0x35, 0x39, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, // 159 = int3(_mtl_
+ 0x75, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, // u.bgfx_blitRegio
+ 0x6e, 0x5b, 0x31, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // n[1].xyz);.
+ 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x28, 0x28, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, // if (((int3(gl
+ 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, // _GlobalInvocatio
+ 0x6e, 0x49, 0x44, 0x29, 0x2e, 0x78, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x39, 0x2e, 0x78, // nID).x >= _159.x
+ 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, // ) || (int3(gl_Gl
+ 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, // obalInvocationID
+ 0x29, 0x2e, 0x79, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x39, 0x2e, 0x79, 0x29, 0x29, 0x20, // ).y >= _159.y))
+ 0x7c, 0x7c, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, // || (int3(gl_Glob
+ 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x2e, // alInvocationID).
+ 0x7a, 0x20, 0x3e, 0x3d, 0x20, 0x5f, 0x31, 0x35, 0x39, 0x2e, 0x7a, 0x29, 0x29, 0x0a, 0x20, 0x20, // z >= _159.z)).
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // {.
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, // break;.
+ 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, // }. int
+ 0x33, 0x20, 0x5f, 0x31, 0x38, 0x37, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x5f, 0x6d, // 3 _187 = int3(_m
+ 0x74, 0x6c, 0x5f, 0x75, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, // tl_u.bgfx_blitRe
+ 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x20, 0x2b, 0x20, 0x69, // gion[0].xyz) + i
+ 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, // nt3(gl_GlobalInv
+ 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, // ocationID);.
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x44, 0x73, 0x74, // bgfx_blitDst
+ 0x5f, 0x31, 0x2e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5b, 0x28, 0x28, 0x69, 0x6e, 0x74, 0x33, 0x28, // _1._data[((int3(
+ 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, // gl_GlobalInvocat
+ 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x5f, // ionID).z * int(_
+ 0x6d, 0x74, 0x6c, 0x5f, 0x75, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x52, // mtl_u.bgfx_blitR
+ 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x31, 0x5d, 0x2e, 0x77, 0x29, 0x29, 0x20, 0x2b, 0x20, 0x28, // egion[1].w)) + (
+ 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x49, 0x6e, // int3(gl_GlobalIn
+ 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, 0x2e, 0x79, 0x20, 0x2a, 0x20, // vocationID).y *
+ 0x69, 0x6e, 0x74, 0x28, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x75, 0x2e, 0x62, 0x67, 0x66, 0x78, 0x5f, // int(_mtl_u.bgfx_
+ 0x62, 0x6c, 0x69, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5b, 0x30, 0x5d, 0x2e, 0x77, 0x29, // blitRegion[0].w)
+ 0x29, 0x29, 0x20, 0x2b, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x28, 0x67, 0x6c, 0x5f, 0x47, 0x6c, 0x6f, // )) + int3(gl_Glo
+ 0x62, 0x61, 0x6c, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x29, // balInvocationID)
+ 0x2e, 0x78, 0x5d, 0x20, 0x3d, 0x20, 0x62, 0x67, 0x66, 0x78, 0x5f, 0x62, 0x6c, 0x69, 0x74, 0x53, // .x] = bgfx_blitS
+ 0x72, 0x63, 0x2e, 0x72, 0x65, 0x61, 0x64, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x32, 0x28, 0x5f, 0x31, // rc.read(uint2(_1
+ 0x38, 0x37, 0x2e, 0x78, 0x79, 0x29, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x5f, 0x31, 0x38, // 87.xy), uint(_18
+ 0x37, 0x2e, 0x7a, 0x29, 0x2c, 0x20, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // 7.z), 0);.
+ 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x77, // break;. } w
+ 0x68, 0x69, 0x6c, 0x65, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, // hile(false);.}..
+ 0x00, 0x00, 0x30, 0x00, // ..0.
+};
+extern const uint8_t* cs_blit_texture_to_buffer_pssl;
+extern const uint32_t cs_blit_texture_to_buffer_pssl_size;
diff --git a/src/cs_blit_texture_to_buffer.sc b/src/cs_blit_texture_to_buffer.sc
new file mode 100644
index 000000000..d216a7834
--- /dev/null
+++ b/src/cs_blit_texture_to_buffer.sc
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011-2026 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
+ */
+
+#include "bgfx_compute.sh"
+
+IMAGE2D_ARRAY_RO(bgfx_blitSrc, rgba32f, 0);
+BUFFER_WO(bgfx_blitDst, vec4, 0);
+
+uniform vec4 bgfx_blitRegion[2];
+
+#define bgfx_srcOrigin ivec3(bgfx_blitRegion[0].xyz)
+#define bgfx_blitSize ivec3(bgfx_blitRegion[1].xyz)
+#define bgfx_blitRowPitch int(bgfx_blitRegion[0].w)
+#define bgfx_blitSlicePitch int(bgfx_blitRegion[1].w)
+
+NUM_THREADS(8, 8, 1)
+void main()
+{
+ ivec3 coord = ivec3(gl_GlobalInvocationID.xyz);
+
+ if (coord.x >= bgfx_blitSize.x
+ || coord.y >= bgfx_blitSize.y
+ || coord.z >= bgfx_blitSize.z)
+ {
+ return;
+ }
+
+ vec4 color = imageLoad(bgfx_blitSrc, bgfx_srcOrigin + coord);
+
+ int index = coord.z * bgfx_blitSlicePitch + coord.y * bgfx_blitRowPitch + coord.x;
+
+ bgfx_blitDst[index] = color;
+}
diff --git a/src/glimports.h b/src/glimports.h
index 20e551117..51254a7c2 100644
--- a/src/glimports.h
+++ b/src/glimports.h
@@ -75,6 +75,7 @@ typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum targ
typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
@@ -164,6 +165,7 @@ typedef const GLubyte* (GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint i
typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void * (GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
@@ -220,6 +222,7 @@ typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsiz
typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
@@ -278,6 +281,7 @@ GL_IMPORT______(false, PFNGLCOMPRESSEDTEXIMAGE2DPROC, glCompressedT
GL_IMPORT______(false, PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2D);
GL_IMPORT______(true , PFNGLCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3D);
GL_IMPORT______(true , PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3D);
+GL_IMPORT______(true , PFNGLCOPYBUFFERSUBDATAPROC, glCopyBufferSubData);
GL_IMPORT______(true , PFNGLCOPYIMAGESUBDATAPROC, glCopyImageSubData);
GL_IMPORT______(true , PFNGLCOPYTEXSUBIMAGE2DPROC, glCopyTexSubImage2D);
GL_IMPORT______(false, PFNGLCREATEPROGRAMPROC, glCreateProgram);
@@ -374,6 +378,7 @@ GL_IMPORT______(true, PFNGLTEXIMAGE3DMULTISAMPLEPROC, glTexImage3DM
#endif // BGFX_CONFIG_RENDERER_OPENGLES
GL_IMPORT______(false, PFNGLLINKPROGRAMPROC, glLinkProgram);
+GL_IMPORT______(true, PFNGLMAPBUFFERRANGEPROC, glMapBufferRange);
GL_IMPORT______(true, PFNGLMEMORYBARRIERPROC, glMemoryBarrier);
GL_IMPORT______(true, PFNGLMULTIDRAWARRAYSINDIRECTPROC, glMultiDrawArraysIndirect);
GL_IMPORT______(true, PFNGLMULTIDRAWELEMENTSINDIRECTPROC, glMultiDrawElementsIndirect);
@@ -426,6 +431,7 @@ GL_IMPORT______(false, PFNGLUNIFORM4FVPROC, glUniform4fv)
GL_IMPORT______(false, PFNGLUNIFORM4FPROC, glUniform4f);
GL_IMPORT______(false, PFNGLUNIFORMMATRIX3FVPROC, glUniformMatrix3fv);
GL_IMPORT______(false, PFNGLUNIFORMMATRIX4FVPROC, glUniformMatrix4fv);
+GL_IMPORT______(true, PFNGLUNMAPBUFFERPROC, glUnmapBuffer);
GL_IMPORT______(false, PFNGLUSEPROGRAMPROC, glUseProgram);
GL_IMPORT______(true, PFNGLVERTEXATTRIBDIVISORPROC, glVertexAttribDivisor);
GL_IMPORT______(false, PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer);
@@ -593,6 +599,10 @@ GL_IMPORT______(true, PFNGLSAMPLERPARAMETERFPROC, glSamplerPara
GL_IMPORT______(true, PFNGLSAMPLERPARAMETERIPROC, glSamplerParameteri);
GL_IMPORT______(true, PFNGLSAMPLERPARAMETERFVPROC, glSamplerParameterfv);
+GL_IMPORT______(true, PFNGLCOPYBUFFERSUBDATAPROC, glCopyBufferSubData);
+GL_IMPORT______(true, PFNGLMAPBUFFERRANGEPROC, glMapBufferRange);
+GL_IMPORT______(true, PFNGLUNMAPBUFFERPROC, glUnmapBuffer);
+
GL_IMPORT______(true, PFNGLBINDBUFFERBASEPROC, glBindBufferBase);
GL_IMPORT______(true, PFNGLBINDBUFFERRANGEPROC, glBindBufferRange);
GL_IMPORT______(true, PFNGLBINDIMAGETEXTUREPROC, glBindImageTexture);
diff --git a/src/makefile b/src/makefile
index 43723bb37..0fdc5fb7f 100644
--- a/src/makefile
+++ b/src/makefile
@@ -24,6 +24,8 @@ BIN = vs_debugfont.bin.h \
cs_mipgen_oddy.bin.h \
cs_mipgen_oddxy.bin.h \
cs_yuv_to_rgb.bin.h \
+ cs_blit_texture_to_buffer.bin.h \
+ cs_blit_buffer_to_texture.bin.h \
.PHONY: all
all: $(BIN)
@@ -116,6 +118,12 @@ cs_mipgen_oddxy.bin.h : cs_mipgen_oddxy.sc cs_mipgen.sh
cs_yuv_to_rgb.bin.h : cs_yuv_to_rgb.sc
$(call shader-embedded-compute)
+cs_blit_texture_to_buffer.bin.h : cs_blit_texture_to_buffer.sc
+ $(call shader-embedded-compute)
+
+cs_blit_buffer_to_texture.bin.h : cs_blit_buffer_to_texture.sc
+ $(call shader-embedded-compute)
+
.PHONY: clean
clean:
@echo Cleaning...
diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp
index fb48eab36..bce46efac 100644
--- a/src/renderer_d3d11.cpp
+++ b/src/renderer_d3d11.cpp
@@ -8,6 +8,8 @@
#if BGFX_CONFIG_RENDERER_DIRECT3D11
# include "renderer_d3d11.h"
# include "video_d3d11.h"
+# include "cs_blit_texture_to_buffer.bin.h"
+# include "cs_blit_buffer_to_texture.bin.h"
# include
namespace bgfx { namespace d3d11
@@ -1740,6 +1742,14 @@ namespace bgfx { namespace d3d11
m_nvapi.initAftermath(m_device, m_deviceCtx);
+ {
+ const Memory t2b = { (uint8_t*)cs_blit_texture_to_buffer_dxbc, sizeof(cs_blit_texture_to_buffer_dxbc) };
+ const Memory b2t = { (uint8_t*)cs_blit_buffer_to_texture_dxbc, sizeof(cs_blit_buffer_to_texture_dxbc) };
+
+ m_blitShader[0].create(&t2b);
+ m_blitShader[1].create(&b2t);
+ }
+
g_internalData.context = m_device;
return true;
@@ -1816,6 +1826,11 @@ namespace bgfx { namespace d3d11
invalidateCache();
+ for (uint32_t ii = 0; ii < BX_COUNTOF(m_blitShader); ++ii)
+ {
+ m_blitShader[ii].destroy();
+ }
+
for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii)
{
m_frameBuffers[ii].destroy();
@@ -1986,8 +2001,13 @@ namespace bgfx { namespace d3d11
{
const TextureD3D11& texture = m_textures[_handle.idx];
const uint32_t subresource = _mip + _layer*texture.m_numMips;
+
+ BX_ASSERT(NULL != texture.m_staging, "Texture must be created with BGFX_TEXTURE_READ_BACK.");
+
+ m_deviceCtx->CopySubresourceRegion(texture.m_staging, subresource, 0, 0, 0, texture.m_ptr, subresource, NULL);
+
D3D11_MAPPED_SUBRESOURCE mapped;
- DX_CHECK(m_deviceCtx->Map(texture.m_ptr, subresource, D3D11_MAP_READ, 0, &mapped) );
+ DX_CHECK(m_deviceCtx->Map(texture.m_staging, subresource, D3D11_MAP_READ, 0, &mapped) );
uint32_t srcWidth = bx::max(1, texture.m_width >>_mip);
uint32_t srcHeight = bx::max(1, texture.m_height>>_mip);
@@ -2021,7 +2041,47 @@ namespace bgfx { namespace d3d11
bx::memCopy(dst, dstPitch, src, srcPitch, pitch, numRows);
}
- m_deviceCtx->Unmap(texture.m_ptr, subresource);
+ m_deviceCtx->Unmap(texture.m_staging, subresource);
+ }
+
+ BufferD3D11& getBuffer(Handle _handle)
+ {
+ if (_handle.isIndexBuffer() )
+ {
+ return m_indexBuffers[_handle.idx];
+ }
+
+ return m_vertexBuffers[_handle.idx];
+ }
+
+ void readBuffer(Handle _handle, void* _data, uint32_t _offset, uint32_t _size) override
+ {
+ const BufferD3D11& buffer = getBuffer(_handle);
+
+ D3D11_BUFFER_DESC desc;
+ bx::memSet(&desc, 0, sizeof(desc) );
+ desc.ByteWidth = _offset + _size;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+
+ ID3D11Buffer* staging = NULL;
+ DX_CHECK(m_device->CreateBuffer(&desc, NULL, &staging) );
+
+ D3D11_BOX box;
+ box.left = _offset;
+ box.right = _offset + _size;
+ box.top = 0;
+ box.bottom = 1;
+ box.front = 0;
+ box.back = 1;
+ m_deviceCtx->CopySubresourceRegion(staging, 0, _offset, 0, 0, buffer.m_ptr, 0, &box);
+
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ DX_CHECK(m_deviceCtx->Map(staging, 0, D3D11_MAP_READ, 0, &mapped) );
+ bx::memCopy(_data, (const uint8_t*)mapped.pData + _offset, _size);
+ m_deviceCtx->Unmap(staging, 0);
+
+ DX_RELEASE(staging, 0);
}
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) override
@@ -2297,6 +2357,7 @@ namespace bgfx { namespace d3d11
}
}
+ void blitBufferTexture(const BlitItem& _blit);
void submitBlit(BlitState& _bs, uint16_t _view);
void submitUniformCache(UniformCacheState& _ucs, uint16_t _view);
@@ -3933,6 +3994,7 @@ namespace bgfx { namespace d3d11
IndexBufferD3D11 m_indexBuffers[BGFX_CONFIG_MAX_INDEX_BUFFERS];
VertexBufferD3D11 m_vertexBuffers[BGFX_CONFIG_MAX_VERTEX_BUFFERS];
ShaderD3D11 m_shaders[BGFX_CONFIG_MAX_SHADERS];
+ ShaderD3D11 m_blitShader[2];
ProgramD3D11 m_program[BGFX_CONFIG_MAX_PROGRAMS];
TextureD3D11 m_textures[BGFX_CONFIG_MAX_TEXTURES];
VertexLayout m_vertexLayouts[BGFX_CONFIG_MAX_VERTEX_LAYOUTS];
@@ -4843,7 +4905,7 @@ namespace bgfx { namespace d3d11
}
}
- const bool writeOnly = 0 != (m_flags & (BGFX_TEXTURE_RT_WRITE_ONLY|BGFX_TEXTURE_READ_BACK) );
+ const bool writeOnly = 0 != (m_flags & BGFX_TEXTURE_RT_WRITE_ONLY);
const bool computeWrite = 0 != (m_flags & BGFX_TEXTURE_COMPUTE_WRITE)
|| isVideoDecodeDst
;
@@ -4855,6 +4917,16 @@ namespace bgfx { namespace d3d11
const uint32_t msaaQuality = bx::satSub(uint32_t( (m_flags&BGFX_TEXTURE_RT_MSAA_MASK) >> BGFX_TEXTURE_RT_MSAA_SHIFT ), 1u);
const DXGI_SAMPLE_DESC& msaa = s_msaa[msaaQuality];
+
+ const bool blitUav = true
+ && blit
+ && !compressed
+ && !writeOnly
+ && 1 == msaa.Count
+ && !bimg::isDepth(bimg::TextureFormat::Enum(m_textureFormat) )
+ && 0 != (g_caps.formats[m_textureFormat] & BGFX_CAPS_FORMAT_TEXTURE_IMAGE_WRITE)
+ ;
+
const bool msaaSample = true
&& 1 < msaa.Count
&& 0 != (m_flags&BGFX_TEXTURE_MSAA_SAMPLE)
@@ -4950,11 +5022,15 @@ namespace bgfx { namespace d3d11
desc.Usage = D3D11_USAGE_DEFAULT;
}
+ if (blitUav)
+ {
+ desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ }
+
if (readBack)
{
- desc.BindFlags = 0;
- desc.Usage = D3D11_USAGE_STAGING;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc.Usage = D3D11_USAGE_DEFAULT;
}
if (imageContainer.m_cubeMap)
@@ -5064,9 +5140,7 @@ namespace bgfx { namespace d3d11
if (readBack)
{
- desc.BindFlags = 0;
- desc.Usage = D3D11_USAGE_STAGING;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc.Usage = D3D11_USAGE_DEFAULT;
}
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
@@ -5093,6 +5167,32 @@ namespace bgfx { namespace d3d11
{
}
+ if (readBack)
+ {
+ if (Texture3D == m_type)
+ {
+ D3D11_TEXTURE3D_DESC desc;
+ m_texture3d->GetDesc(&desc);
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc.MiscFlags = 0;
+
+ DX_CHECK(s_renderD3D11->m_device->CreateTexture3D(&desc, NULL, (ID3D11Texture3D**)&m_staging) );
+ }
+ else
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ m_texture2d->GetDesc(&desc);
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ desc.MiscFlags = 0;
+
+ DX_CHECK(s_renderD3D11->m_device->CreateTexture2D(&desc, NULL, (ID3D11Texture2D**)&m_staging) );
+ }
+ }
+
if (!writeOnly)
{
DX_CHECK(s_renderD3D11->m_device->CreateShaderResourceView(m_ptr, &srvd, &m_srv) );
@@ -5185,6 +5285,7 @@ namespace bgfx { namespace d3d11
DX_RELEASE(m_rt, 0);
DX_RELEASE(m_srv, 0);
DX_RELEASE(m_uav, 0);
+ DX_RELEASE(m_staging, 0);
if (0 == (m_flags & BGFX_SAMPLER_INTERNAL_SHARED) )
{
@@ -6148,6 +6249,157 @@ namespace bgfx { namespace d3d11
}
}
+ void RendererContextD3D11::blitBufferTexture(const BlitItem& _blit)
+ {
+ const bool toBuffer = _blit.m_dst.isBuffer();
+
+ const TextureD3D11& texture = m_textures[(toBuffer ? _blit.m_src : _blit.m_dst).idx];
+ const BufferD3D11& buffer = getBuffer(toBuffer ? _blit.m_dst : _blit.m_src);
+
+ const bimg::TextureFormat::Enum format = bimg::TextureFormat::Enum(texture.m_textureFormat);
+
+ if (bimg::isCompressed(format)
+ || bimg::isDepth(format) )
+ {
+ BX_WARN(false, "Blit between buffer and texture is not supported for compressed or depth formats.");
+
+ return;
+ }
+
+ if (0 == (g_caps.formats[texture.m_textureFormat] & BGFX_CAPS_FORMAT_TEXTURE_IMAGE_WRITE) )
+ {
+ BX_WARN(false, "Blit between buffer and texture is not supported for texture format %s.", bimg::getName(format) );
+
+ return;
+ }
+
+ if (TextureD3D11::Texture3D == texture.m_type)
+ {
+ BX_WARN(false, "Blit between buffer and 3D texture is not supported.");
+
+ return;
+ }
+
+ if (NULL == m_blitShader[toBuffer ? 0 : 1].m_computeShader)
+ {
+ return;
+ }
+
+ const uint32_t bpp = bimg::getBitsPerPixel(format) / 8;
+ const uint32_t offset = toBuffer ? _blit.m_dstOffset : _blit.m_srcOffset;
+
+ if (0 != offset % bpp
+ || 0 != _blit.m_rowPitch % bpp)
+ {
+ BX_WARN(false
+ , "Buffer offset %d and row pitch %d must be a multiple of texture format block size %d."
+ , offset
+ , _blit.m_rowPitch
+ , bpp
+ );
+
+ return;
+ }
+
+ const DXGI_FORMAT dxgiFormat = texture.getSrvFormat();
+ const uint32_t numElements = (_blit.m_rowPitch * _blit.m_height) / bpp;
+
+ ID3D11ShaderResourceView* srv = NULL;
+ ID3D11UnorderedAccessView* uav = NULL;
+
+ if (toBuffer)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvd = {};
+ srvd.Format = dxgiFormat;
+ srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvd.Texture2DArray.MostDetailedMip = _blit.m_srcMip;
+ srvd.Texture2DArray.MipLevels = 1;
+ srvd.Texture2DArray.FirstArraySlice = _blit.m_srcZ;
+ srvd.Texture2DArray.ArraySize = 1;
+
+ DX_CHECK(m_device->CreateShaderResourceView(texture.m_ptr, &srvd, &srv) );
+
+ D3D11_UNORDERED_ACCESS_VIEW_DESC uavd = {};
+ uavd.Format = dxgiFormat;
+ uavd.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+ uavd.Buffer.FirstElement = offset / bpp;
+ uavd.Buffer.NumElements = numElements;
+
+ DX_CHECK(m_device->CreateUnorderedAccessView(buffer.m_ptr, &uavd, &uav) );
+ }
+ else
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvd = {};
+ srvd.Format = dxgiFormat;
+ srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+ srvd.Buffer.FirstElement = offset / bpp;
+ srvd.Buffer.NumElements = numElements;
+
+ DX_CHECK(m_device->CreateShaderResourceView(buffer.m_ptr, &srvd, &srv) );
+
+ D3D11_UNORDERED_ACCESS_VIEW_DESC uavd = {};
+ uavd.Format = dxgiFormat;
+ uavd.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+ uavd.Texture2DArray.MipSlice = _blit.m_dstMip;
+ uavd.Texture2DArray.FirstArraySlice = _blit.m_dstZ;
+ uavd.Texture2DArray.ArraySize = 1;
+
+ DX_CHECK(m_device->CreateUnorderedAccessView(texture.m_ptr, &uavd, &uav) );
+ }
+
+ if (NULL == srv
+ || NULL == uav)
+ {
+ DX_RELEASE(srv, 0);
+ DX_RELEASE(uav, 0);
+
+ return;
+ }
+
+ const ShaderD3D11& shader = m_blitShader[toBuffer ? 0 : 1];
+
+ const float params[8] =
+ {
+ float(toBuffer ? _blit.m_srcX : _blit.m_dstX),
+ float(toBuffer ? _blit.m_srcY : _blit.m_dstY),
+ 0.0f,
+ float(_blit.m_rowPitch / bpp),
+ float(_blit.m_width),
+ float(_blit.m_height),
+ 1.0f,
+ 0.0f,
+ };
+
+ ID3D11DeviceContext* deviceCtx = m_deviceCtx;
+
+ deviceCtx->CSSetShader(shader.m_computeShader, NULL, 0);
+ deviceCtx->CSSetShaderResources(0, 1, &srv);
+ deviceCtx->CSSetUnorderedAccessViews(0, 1, &uav, NULL);
+
+ if (NULL != shader.m_buffer)
+ {
+ deviceCtx->UpdateSubresource(shader.m_buffer, 0, NULL, params, 0, 0);
+ deviceCtx->CSSetConstantBuffers(0, 1, &shader.m_buffer);
+ }
+
+ deviceCtx->Dispatch(
+ bx::strideAlign(_blit.m_width, 8) / 8
+ , bx::strideAlign(_blit.m_height, 8) / 8
+ , 1
+ );
+
+ ID3D11ShaderResourceView* srvNull = NULL;
+ ID3D11UnorderedAccessView* uavNull = NULL;
+ deviceCtx->CSSetShaderResources(0, 1, &srvNull);
+ deviceCtx->CSSetUnorderedAccessViews(0, 1, &uavNull, NULL);
+ deviceCtx->CSSetShader(NULL, NULL, 0);
+
+ m_currentProgram = NULL;
+
+ DX_RELEASE(srv, 0);
+ DX_RELEASE(uav, 0);
+ }
+
void RendererContextD3D11::submitBlit(BlitState& _bs, uint16_t _view)
{
ID3D11DeviceContext* deviceCtx = m_deviceCtx;
@@ -6156,6 +6408,33 @@ namespace bgfx { namespace d3d11
{
const BlitItem& blit = _bs.advance();
+ if (blit.m_src.isBuffer()
+ && blit.m_dst.isBuffer() )
+ {
+ const BufferD3D11& srcBuf = getBuffer(blit.m_src);
+ const BufferD3D11& dstBuf = getBuffer(blit.m_dst);
+
+ D3D11_BOX box;
+ box.left = blit.m_srcOffset;
+ box.right = blit.m_srcOffset + blit.m_size;
+ box.top = 0;
+ box.bottom = 1;
+ box.front = 0;
+ box.back = 1;
+
+ deviceCtx->CopySubresourceRegion(dstBuf.m_ptr, 0, blit.m_dstOffset, 0, 0, srcBuf.m_ptr, 0, &box);
+
+ continue;
+ }
+
+ if (blit.m_src.isBuffer()
+ || blit.m_dst.isBuffer() )
+ {
+ blitBufferTexture(blit);
+
+ continue;
+ }
+
const TextureD3D11& src = m_textures[blit.m_src.idx];
const TextureD3D11& dst = m_textures[blit.m_dst.idx];
@@ -6180,66 +6459,13 @@ namespace bgfx { namespace d3d11
const uint32_t srcSubresource = blit.m_srcZ*src.m_numMips + blit.m_srcMip;
const uint32_t dstSubresource = blit.m_dstZ*dst.m_numMips + blit.m_dstMip;
- if (0 != (dst.m_flags & BGFX_TEXTURE_READ_BACK) )
- {
- const D3D11_TEXTURE2D_DESC desc =
- {
- .Width = bx::max(1, src.m_width >> blit.m_srcMip),
- .Height = bx::max(1, src.m_height >> blit.m_srcMip),
- .MipLevels = 1,
- .ArraySize = 1,
- .Format = resolveFormat,
- .SampleDesc = { .Count = 1, .Quality = 0 },
- .Usage = D3D11_USAGE_DEFAULT,
- .BindFlags = D3D11_BIND_SHADER_RESOURCE,
- .CPUAccessFlags = 0,
- .MiscFlags = 0,
- };
-
- ID3D11Texture2D* scratch;
- DX_CHECK(m_device->CreateTexture2D(&desc, NULL, &scratch) );
-
- deviceCtx->ResolveSubresource(
- scratch
- , 0
- , src.m_ptr
- , srcSubresource
- , resolveFormat
- );
-
- const D3D11_BOX box =
- {
- .left = blit.m_srcX,
- .top = blit.m_srcY,
- .front = 0,
- .right = uint32_t(blit.m_srcX) + blit.m_width,
- .bottom = uint32_t(blit.m_srcY) + blit.m_height,
- .back = 1,
- };
-
- deviceCtx->CopySubresourceRegion(
- dst.m_ptr
- , dstSubresource
- , blit.m_dstX
- , blit.m_dstY
- , 0
- , scratch
- , 0
- , &box
- );
-
- DX_RELEASE(scratch, 0);
- }
- else
- {
- deviceCtx->ResolveSubresource(
- dst.m_ptr
- , dstSubresource
- , src.m_ptr
- , srcSubresource
- , resolveFormat
- );
- }
+ deviceCtx->ResolveSubresource(
+ dst.m_ptr
+ , dstSubresource
+ , src.m_ptr
+ , srcSubresource
+ , resolveFormat
+ );
continue;
}
@@ -7311,6 +7537,7 @@ namespace bgfx { namespace d3d11
perfStats.numDraw = statsKeyType[0];
perfStats.numCompute = statsKeyType[1];
perfStats.numBlit = _render->m_numBlitItems;
+ perfStats.numBlitRepack = _render->m_numBlitRepack;
perfStats.maxGpuLatency = maxGpuLatency;
perfStats.gpuFrameNum = result.m_frameNum;
bx::memCopy(perfStats.numPrims, statsNumPrimsRendered, sizeof(perfStats.numPrims) );
diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h
index a80c149cd..b6b488a0e 100644
--- a/src/renderer_d3d11.h
+++ b/src/renderer_d3d11.h
@@ -343,6 +343,7 @@ namespace bgfx { namespace d3d11
TextureD3D11()
: m_ptr(NULL)
, m_rt(NULL)
+ , m_staging(NULL)
, m_srv(NULL)
, m_uav(NULL)
, m_videoDecoder(NULL)
@@ -376,6 +377,7 @@ namespace bgfx { namespace d3d11
ID3D11Texture2D* m_rt2d;
};
+ ID3D11Resource* m_staging;
ID3D11ShaderResourceView* m_srv;
ID3D11UnorderedAccessView* m_uav;
VideoDecoderD3D11* m_videoDecoder;
diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp
index 9829f2b95..aba16634d 100644
--- a/src/renderer_d3d12.cpp
+++ b/src/renderer_d3d12.cpp
@@ -8,6 +8,8 @@
#if BGFX_CONFIG_RENDERER_DIRECT3D12
# include "renderer_d3d12.h"
# include "video_d3d12.h"
+# include "cs_blit_texture_to_buffer.bin.h"
+# include "cs_blit_buffer_to_texture.bin.h"
#if !BX_PLATFORM_WINDOWS && !BX_PLATFORM_LINUX
# include
@@ -831,9 +833,11 @@ namespace bgfx { namespace d3d12
, m_rtMsaa(false)
, m_directAccessSupport(false)
, m_variableRateShadingSupport(false)
+ , m_computeStateDirty(false)
, m_mipGen(NULL)
, m_zeroInitBuffer(NULL)
{
+ bx::memSet(m_blitPso, 0, sizeof(m_blitPso) );
}
~RendererContextD3D12()
@@ -1765,13 +1769,15 @@ namespace bgfx { namespace d3d12
| BGFX_CAPS_VERTEX_ID
| BGFX_CAPS_VIEWPORT_LAYER_ARRAY
);
- g_caps.limits.maxTextureSize = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
- g_caps.limits.maxTextureLayers = D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
- g_caps.limits.maxFBAttachments = bx::min(16, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS);
- g_caps.limits.maxComputeBindings = bx::min(D3D12_UAV_SLOT_COUNT, BGFX_MAX_COMPUTE_BINDINGS);
- g_caps.limits.maxVertexStreams = BGFX_CONFIG_MAX_VERTEX_STREAMS;
+ g_caps.limits.maxTextureSize = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ g_caps.limits.maxTextureLayers = D3D12_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+ g_caps.limits.maxFBAttachments = bx::min(16, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS);
+ g_caps.limits.maxComputeBindings = bx::min(D3D12_UAV_SLOT_COUNT, BGFX_MAX_COMPUTE_BINDINGS);
+ g_caps.limits.maxVertexStreams = BGFX_CONFIG_MAX_VERTEX_STREAMS;
g_caps.limits.maxVertexAttributes = D3D12_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT;
- g_caps.limits.maxInstanceData = bx::min(g_caps.limits.maxInstanceData, g_caps.limits.maxVertexAttributes);
+ g_caps.limits.maxInstanceData = bx::min(g_caps.limits.maxInstanceData, g_caps.limits.maxVertexAttributes);
+ g_caps.limits.blitRowPitchAlign = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT;
+ g_caps.limits.blitOffsetAlign = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT;
for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii)
{
@@ -2044,6 +2050,38 @@ namespace bgfx { namespace d3d12
m_nvapi.initAftermath(m_device, m_commandList);
}
+ {
+ const Memory t2b = { (uint8_t*)cs_blit_texture_to_buffer_dxil, sizeof(cs_blit_texture_to_buffer_dxil) };
+ const Memory b2t = { (uint8_t*)cs_blit_buffer_to_texture_dxil, sizeof(cs_blit_buffer_to_texture_dxil) };
+
+ m_blitShader[0].create(&t2b);
+ m_blitShader[1].create(&b2t);
+
+ for (uint32_t ii = 0; ii < BX_COUNTOF(m_blitPso); ++ii)
+ {
+ const Memory* code = m_blitShader[ii].m_code;
+
+ if (NULL == code)
+ {
+ continue;
+ }
+
+ const D3D12_COMPUTE_PIPELINE_STATE_DESC desc =
+ {
+ .pRootSignature = m_computeRootSignature,
+ .CS = { code->data, code->size },
+ .NodeMask = 0,
+ .CachedPSO = { NULL, 0 },
+ .Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
+ };
+
+ DX_CHECK(m_device->CreateComputePipelineState(&desc
+ , IID_ID3D12PipelineState
+ , (void**)&m_blitPso[ii]
+ ) );
+ }
+ }
+
g_internalData.context = m_device;
return true;
@@ -2142,6 +2180,12 @@ namespace bgfx { namespace d3d12
DX_RELEASE_W(m_infoQueue, 0);
#endif // BX_PLATFORM_WINDOWS
+ for (uint32_t ii = 0; ii < BX_COUNTOF(m_blitPso); ++ii)
+ {
+ DX_RELEASE(m_blitPso[ii], 0);
+ m_blitShader[ii].destroy();
+ }
+
DX_RELEASE(m_rtvDescriptorHeap, 0);
DX_RELEASE(m_dsvDescriptorHeap, 0);
DX_RELEASE(m_textureSrvHeap, 0);
@@ -2535,6 +2579,38 @@ namespace bgfx { namespace d3d12
DX_RELEASE(readback, 0);
}
+ BufferD3D12& getBuffer(Handle _handle)
+ {
+ if (_handle.isIndexBuffer() )
+ {
+ return m_indexBuffers[_handle.idx];
+ }
+
+ return m_vertexBuffers[_handle.idx];
+ }
+
+ void readBuffer(Handle _handle, void* _data, uint32_t _offset, uint32_t _size) override
+ {
+ BufferD3D12& buffer = getBuffer(_handle);
+
+ ID3D12Resource* readback = createCommittedResource(m_device, HeapProperty::ReadBack, _size);
+
+ const D3D12_RESOURCE_STATES state = buffer.setState(m_commandList, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ m_commandList->CopyBufferRegion(readback, 0, buffer.m_ptr, _offset, _size);
+ buffer.setState(m_commandList, state);
+
+ finish();
+ m_commandList = m_cmd.alloc();
+
+ void* src = NULL;
+ readback->Map(0, NULL, (void**)&src);
+ bx::memCopy(_data, src, _size);
+ D3D12_RANGE readbackWriteRange = { 0, 0 };
+ readback->Unmap(0, &readbackWriteRange);
+
+ DX_RELEASE(readback, 0);
+ }
+
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) override
{
TextureD3D12& texture = m_textures[_handle.idx];
@@ -2830,6 +2906,10 @@ namespace bgfx { namespace d3d12
void submitBlit(BlitState& _bs, uint16_t _view);
+ void blitBufferTexture(const BlitItem& _blit);
+
+ bool blitBufferTextureCompute(const BlitItem& _blit);
+
void submitUniformCache(UniformCacheState& _ucs, uint16_t _view);
void submit(Frame* _render, const ClearQuad& _clearQuad, const MipGen& _mipGen, TextVideoMemBlitter& _textVideoMemBlitter) override;
@@ -4400,9 +4480,14 @@ namespace bgfx { namespace d3d12
bool m_directAccessSupport;
bool m_variableRateShadingSupport;
+ bool m_computeStateDirty;
+
const MipGen* m_mipGen;
ID3D12Resource* m_zeroInitBuffer;
+ ShaderD3D12 m_blitShader[2];
+ ID3D12PipelineState* m_blitPso[2];
+
void generateMips(ID3D12GraphicsCommandList* _commandList, TextureD3D12& _texture);
};
@@ -7986,6 +8071,368 @@ namespace bgfx { namespace d3d12
static constexpr uint8_t kBindStateValid = 1;
static constexpr uint8_t kBindStateEmpty = 2;
+ bool RendererContextD3D12::blitBufferTextureCompute(const BlitItem& _blit)
+ {
+ const bool toBuffer = _blit.m_dst.isBuffer();
+
+ ID3D12PipelineState* pso = m_blitPso[toBuffer ? 0 : 1];
+
+ if (NULL == pso)
+ {
+ return false;
+ }
+
+ TextureD3D12& texture = m_textures[(toBuffer ? _blit.m_src : _blit.m_dst).idx];
+ BufferD3D12& buffer = getBuffer(toBuffer ? _blit.m_dst : _blit.m_src);
+
+ const bimg::TextureFormat::Enum format = bimg::TextureFormat::Enum(texture.m_textureFormat);
+
+ if (bimg::isCompressed(format)
+ || bimg::isDepth(format)
+ || TextureD3D12::Texture3D == texture.m_type
+ || NULL != texture.m_singleMsaa
+ || 0 == (g_caps.formats[texture.m_textureFormat] & BGFX_CAPS_FORMAT_TEXTURE_IMAGE_WRITE) )
+ {
+ return false;
+ }
+
+ const bool writable = toBuffer
+ ? 0 != (buffer.m_flags & BGFX_BUFFER_COMPUTE_WRITE)
+ : 0 != (texture.m_flags & BGFX_TEXTURE_COMPUTE_WRITE)
+ ;
+
+ if (!writable)
+ {
+ return false;
+ }
+
+ const uint32_t bpp = bimg::getBitsPerPixel(format) / 8;
+ const uint32_t offset = toBuffer ? _blit.m_dstOffset : _blit.m_srcOffset;
+
+ if (0 != offset % bpp
+ || 0 != _blit.m_rowPitch % bpp
+ || 0 != _blit.m_slicePitch % bpp)
+ {
+ return false;
+ }
+
+ const uint32_t depth = bx::max(1, _blit.m_depth);
+ const uint16_t z = toBuffer ? _blit.m_srcZ : _blit.m_dstZ;
+ const uint8_t mip = toBuffer ? _blit.m_srcMip : _blit.m_dstMip;
+
+ const DXGI_FORMAT dxgiFormat = texture.m_srvd.Format;
+ const uint32_t numElements = _blit.m_size / bpp;
+
+ D3D12_SHADER_RESOURCE_VIEW_DESC srvd = {};
+ srvd.Format = dxgiFormat;
+ srvd.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+
+ D3D12_UNORDERED_ACCESS_VIEW_DESC uavd = {};
+ uavd.Format = dxgiFormat;
+
+ if (toBuffer)
+ {
+ srvd.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvd.Texture2DArray.MostDetailedMip = mip;
+ srvd.Texture2DArray.MipLevels = 1;
+ srvd.Texture2DArray.FirstArraySlice = z;
+ srvd.Texture2DArray.ArraySize = depth;
+
+ uavd.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
+ uavd.Buffer.FirstElement = offset / bpp;
+ uavd.Buffer.NumElements = numElements;
+ }
+ else
+ {
+ srvd.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
+ srvd.Buffer.FirstElement = offset / bpp;
+ srvd.Buffer.NumElements = numElements;
+
+ uavd.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
+ uavd.Texture2DArray.MipSlice = mip;
+ uavd.Texture2DArray.FirstArraySlice = z;
+ uavd.Texture2DArray.ArraySize = depth;
+ }
+
+ texture.setState(m_commandList, toBuffer
+ ? D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
+ : D3D12_RESOURCE_STATE_UNORDERED_ACCESS
+ );
+ buffer.setState(m_commandList, toBuffer
+ ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS
+ : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
+ );
+
+ ScratchBufferD3D12& scratchBuffer = m_scratchBuffer[m_backBufferColorIdx];
+
+ m_commandList->SetComputeRootSignature(m_computeRootSignature);
+
+ ID3D12DescriptorHeap* heaps[] =
+ {
+ m_samplerAllocator.getHeap(),
+ scratchBuffer.getHeap(),
+ };
+ m_commandList->SetDescriptorHeaps(BX_COUNTOF(heaps), heaps);
+
+ uint32_t samplerFlags[BGFX_MAX_COMPUTE_BINDINGS] = {};
+ const uint16_t samplerStateIdx = getSamplerState(samplerFlags, BGFX_MAX_COMPUTE_BINDINGS, NULL);
+ m_commandList->SetComputeRootDescriptorTable(ComputeRp::Sampler, m_samplerAllocator.get(samplerStateIdx) );
+
+ m_commandList->SetPipelineState(pso);
+
+ D3D12_GPU_DESCRIPTOR_HANDLE srvHandle[BGFX_MAX_COMPUTE_BINDINGS] = {};
+ scratchBuffer.allocSrv(srvHandle[0], toBuffer ? texture.m_ptr : buffer.m_ptr, srvd);
+
+ for (uint32_t ii = 1; ii < BGFX_MAX_COMPUTE_BINDINGS; ++ii)
+ {
+ scratchBuffer.allocEmpty(srvHandle[ii]);
+ }
+
+ m_commandList->SetComputeRootDescriptorTable(ComputeRp::SRV, srvHandle[0]);
+
+ D3D12_GPU_DESCRIPTOR_HANDLE uavHandle[BGFX_MAX_COMPUTE_BINDINGS] = {};
+ scratchBuffer.allocUav(uavHandle[0], toBuffer ? buffer.m_ptr : texture.m_ptr, uavd);
+
+ for (uint32_t ii = 1; ii < BGFX_MAX_COMPUTE_BINDINGS; ++ii)
+ {
+ scratchBuffer.allocEmpty(uavHandle[ii]);
+ }
+
+ m_commandList->SetComputeRootDescriptorTable(ComputeRp::UAV, uavHandle[0]);
+
+ const float blitRegion[8] =
+ {
+ float(toBuffer ? _blit.m_srcX : _blit.m_dstX),
+ float(toBuffer ? _blit.m_srcY : _blit.m_dstY),
+ 0.0f,
+ float(_blit.m_rowPitch / bpp),
+ float(_blit.m_width),
+ float(_blit.m_height),
+ float(depth),
+ float(_blit.m_slicePitch / bpp),
+ };
+
+ ChunkedScratchBufferOffset sbo;
+ m_uniformScratchBuffer.write(sbo, blitRegion, sizeof(blitRegion) );
+ m_commandList->SetComputeRootConstantBufferView(ComputeRp::CBV, sbo.buffer + sbo.offsets[0]);
+
+ m_commandList->Dispatch(
+ bx::max( (_blit.m_width + 7) / 8, 1)
+ , bx::max( (_blit.m_height + 7) / 8, 1)
+ , depth
+ );
+
+ const D3D12_RESOURCE_BARRIER barrier =
+ {
+ .Type = D3D12_RESOURCE_BARRIER_TYPE_UAV,
+ .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE,
+ .UAV = { .pResource = toBuffer ? buffer.m_ptr : texture.m_ptr },
+ };
+ m_commandList->ResourceBarrier(1, &barrier);
+
+ m_computeStateDirty = true;
+
+ return true;
+ }
+
+ void RendererContextD3D12::blitBufferTexture(const BlitItem& _blit)
+ {
+ const bool toBuffer = _blit.m_dst.isBuffer();
+
+ TextureD3D12& texture = m_textures[toBuffer ? _blit.m_src.idx : _blit.m_dst.idx];
+ BufferD3D12& buffer = getBuffer(toBuffer ? _blit.m_dst : _blit.m_src);
+
+ const uint32_t bufferOffset = toBuffer ? _blit.m_dstOffset : _blit.m_srcOffset;
+
+ const TextureFormat::Enum format = TextureFormat::Enum(texture.m_textureFormat);
+
+ const uint32_t tightPitch = calcTextureRegionPitch(format, _blit.m_width);
+ const uint32_t numRows = calcTextureRegionNumRows(format, _blit.m_height);
+ const uint32_t depth = bx::max(1, _blit.m_depth);
+
+ const uint32_t rowPitch = _blit.m_rowPitch;
+ const uint32_t slicePitch = _blit.m_slicePitch;
+
+ const uint32_t alignedPitch = bx::alignUp(tightPitch, uint32_t(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) );
+
+ const bool is3D = TextureD3D12::Texture3D == texture.m_type;
+
+ const uint16_t z = toBuffer ? _blit.m_srcZ : _blit.m_dstZ;
+ const uint8_t mip = toBuffer ? _blit.m_srcMip : _blit.m_dstMip;
+ const uint16_t x = toBuffer ? _blit.m_srcX : _blit.m_dstX;
+ const uint16_t y = toBuffer ? _blit.m_srcY : _blit.m_dstY;
+
+ const uint32_t numSlices = is3D ? 1 : depth;
+ const uint32_t sliceRows = is3D ? numRows*depth : numRows;
+
+ const bool direct = 0 == rowPitch % D3D12_TEXTURE_DATA_PITCH_ALIGNMENT
+ && 0 == bufferOffset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT
+ && (is3D
+ ? slicePitch == rowPitch*numRows
+ : 1 == numSlices || 0 == slicePitch % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT
+ )
+ ;
+
+ if (!direct
+ && blitBufferTextureCompute(_blit) )
+ {
+ return;
+ }
+
+ const uint32_t scratchSlicePitch = alignedPitch*sliceRows;
+
+ const bool contiguous = rowPitch == alignedPitch
+ && slicePitch == scratchSlicePitch
+ ;
+
+ const uint32_t numCopies = contiguous ? 1 : sliceRows;
+ const uint32_t copySize = contiguous ? scratchSlicePitch : tightPitch;
+
+ ID3D12Resource* scratch = NULL;
+
+ if (!direct)
+ {
+ const uint32_t scratchSize = scratchSlicePitch*numSlices;
+
+ scratch = createCommittedResource(m_device, HeapProperty::Default, scratchSize);
+
+ if (NULL == scratch)
+ {
+ return;
+ }
+
+ m_cmd.release(scratch);
+ }
+
+ ID3D12Resource* copyPtr = direct ? buffer.m_ptr : scratch;
+ const uint32_t copyPitch = direct ? rowPitch : alignedPitch;
+ const uint32_t copySlicePitch = direct ? slicePitch : scratchSlicePitch;
+ const uint64_t copyOffset = direct ? bufferOffset : 0;
+
+ const D3D12_RESOURCE_DESC desc = getResourceDesc(texture.m_ptr);
+
+ const D3D12_RESOURCE_STATES bufferState = buffer.setState(
+ m_commandList
+ , toBuffer
+ ? D3D12_RESOURCE_STATE_COPY_DEST
+ : D3D12_RESOURCE_STATE_COPY_SOURCE
+ );
+ const D3D12_RESOURCE_STATES textureState = texture.setState(
+ m_commandList
+ , toBuffer
+ ? D3D12_RESOURCE_STATE_COPY_SOURCE
+ : D3D12_RESOURCE_STATE_COPY_DEST
+ );
+
+ if (!direct
+ && !toBuffer)
+ {
+ for (uint32_t slice = 0; slice < numSlices; ++slice)
+ {
+ for (uint32_t row = 0; row < numCopies; ++row)
+ {
+ m_commandList->CopyBufferRegion(
+ scratch
+ , slice*scratchSlicePitch + row*alignedPitch
+ , buffer.m_ptr
+ , bufferOffset + slice*slicePitch + row*rowPitch
+ , copySize
+ );
+ }
+ }
+
+ setResourceBarrier(m_commandList, scratch, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ }
+
+ for (uint32_t slice = 0; slice < numSlices; ++slice)
+ {
+ const uint32_t subresource = is3D
+ ? mip
+ : (TextureD3D12::TextureCube == texture.m_type
+ ? z + slice
+ : bx::min(z + slice, texture.m_numLayers - 1)
+ )*texture.m_numMips + mip
+ ;
+
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;
+ uint32_t footprintRows;
+ uint64_t total;
+ m_device->GetCopyableFootprints(&desc, subresource, 1, 0, &layout, &footprintRows, NULL, &total);
+
+ layout.Offset = copyOffset + uint64_t(slice)*copySlicePitch;
+ layout.Footprint.Width = _blit.m_width;
+ layout.Footprint.Height = _blit.m_height;
+ layout.Footprint.Depth = is3D ? depth : 1;
+ layout.Footprint.RowPitch = copyPitch;
+
+ const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
+ {
+ .pResource = copyPtr,
+ .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
+ .PlacedFootprint = layout,
+ };
+
+ const D3D12_TEXTURE_COPY_LOCATION textureLocation =
+ {
+ .pResource = texture.m_ptr,
+ .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX,
+ .SubresourceIndex = subresource,
+ };
+
+ if (toBuffer)
+ {
+ const D3D12_BOX box =
+ {
+ .left = x,
+ .top = y,
+ .front = is3D ? uint32_t(z) : 0,
+ .right = uint32_t(x) + _blit.m_width,
+ .bottom = uint32_t(y) + _blit.m_height,
+ .back = is3D ? z + depth : 1,
+ };
+
+ m_commandList->CopyTextureRegion(&bufferLocation, 0, 0, 0, &textureLocation, &box);
+ }
+ else
+ {
+ const D3D12_BOX box =
+ {
+ .left = 0,
+ .top = 0,
+ .front = 0,
+ .right = _blit.m_width,
+ .bottom = _blit.m_height,
+ .back = is3D ? depth : 1,
+ };
+
+ m_commandList->CopyTextureRegion(&textureLocation, x, y, is3D ? z : 0, &bufferLocation, &box);
+ }
+ }
+
+ if (!direct
+ && toBuffer)
+ {
+ setResourceBarrier(m_commandList, scratch, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE);
+
+ for (uint32_t slice = 0; slice < numSlices; ++slice)
+ {
+ for (uint32_t row = 0; row < numCopies; ++row)
+ {
+ m_commandList->CopyBufferRegion(
+ buffer.m_ptr
+ , bufferOffset + slice*slicePitch + row*rowPitch
+ , scratch
+ , slice*scratchSlicePitch + row*alignedPitch
+ , copySize
+ );
+ }
+ }
+ }
+
+ texture.setState(m_commandList, textureState);
+ buffer.setState(m_commandList, bufferState);
+ }
+
void RendererContextD3D12::submitBlit(BlitState& _bs, uint16_t _view)
{
TextureHandle currentSrc = { kInvalidHandle };
@@ -7998,6 +8445,31 @@ namespace bgfx { namespace d3d12
{
const BlitItem& blit = _bs.advance();
+ if (blit.m_src.isBuffer()
+ && blit.m_dst.isBuffer() )
+ {
+ BufferD3D12& srcBuf = getBuffer(blit.m_src);
+ BufferD3D12& dstBuf = getBuffer(blit.m_dst);
+
+ const D3D12_RESOURCE_STATES srcBufState = srcBuf.setState(m_commandList, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ const D3D12_RESOURCE_STATES dstBufState = dstBuf.setState(m_commandList, D3D12_RESOURCE_STATE_COPY_DEST);
+
+ m_commandList->CopyBufferRegion(dstBuf.m_ptr, blit.m_dstOffset, srcBuf.m_ptr, blit.m_srcOffset, blit.m_size);
+
+ srcBuf.setState(m_commandList, srcBufState);
+ dstBuf.setState(m_commandList, dstBufState);
+
+ continue;
+ }
+
+ if (blit.m_src.isBuffer()
+ || blit.m_dst.isBuffer() )
+ {
+ blitBufferTexture(blit);
+
+ continue;
+ }
+
TextureD3D12& src = m_textures[blit.m_src.idx];
TextureD3D12& dst = m_textures[blit.m_dst.idx];
@@ -8506,10 +8978,17 @@ namespace bgfx { namespace d3d12
commandListChanged = true;
}
- if (commandListChanged)
+ if (commandListChanged
+ || m_computeStateDirty)
{
- commandListChanged = false;
- blendFactor = UINT32_MAX;
+ commandListChanged = false;
+ m_computeStateDirty = false;
+ blendFactor = UINT32_MAX;
+
+ currentPso = NULL;
+ currentBindIdx = UINT32_MAX;
+ currentSamplerStateIdx = kInvalidHandle;
+ currentProgram = BGFX_INVALID_HANDLE;
m_commandList->SetComputeRootSignature(m_computeRootSignature);
ID3D12DescriptorHeap* heaps[] = {
@@ -8826,10 +9305,12 @@ namespace bgfx { namespace d3d12
currentState.m_stencil = newStencil;
if (resetState
- || commandListChanged)
+ || commandListChanged
+ || m_computeStateDirty)
{
wasCompute = false;
commandListChanged = false;
+ m_computeStateDirty = false;
blendFactor = UINT32_MAX;
m_commandList->SetGraphicsRootSignature(m_rootSignature);
@@ -9265,6 +9746,7 @@ namespace bgfx { namespace d3d12
perfStats.numDraw = statsKeyType[0];
perfStats.numCompute = statsKeyType[1];
perfStats.numBlit = _render->m_numBlitItems;
+ perfStats.numBlitRepack = _render->m_numBlitRepack;
perfStats.maxGpuLatency = maxGpuLatency;
perfStats.gpuFrameNum = result.m_frameNum;
bx::memCopy(perfStats.numPrims, statsNumPrimsRendered, sizeof(perfStats.numPrims) );
diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp
index 9ab565342..2e9e30009 100644
--- a/src/renderer_gl.cpp
+++ b/src/renderer_gl.cpp
@@ -3592,6 +3592,46 @@ namespace bgfx { namespace gl
}
}
+ GLuint getBufferId(Handle _handle) const
+ {
+ if (_handle.isIndexBuffer() )
+ {
+ return m_indexBuffers[_handle.idx].m_id;
+ }
+
+ return m_vertexBuffers[_handle.idx].m_id;
+ }
+
+ void readBuffer(Handle _handle, void* _data, uint32_t _offset, uint32_t _size) override
+ {
+ if (NULL == glMapBufferRange)
+ {
+ bx::memSet(_data, 0, _size);
+ return;
+ }
+
+ if (NULL != glMemoryBarrier)
+ {
+ GL_CHECK(glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT) );
+ }
+
+ GL_CHECK(glBindBuffer(GL_COPY_READ_BUFFER, getBufferId(_handle) ) );
+
+ const void* src = glMapBufferRange(GL_COPY_READ_BUFFER, _offset, _size, GL_MAP_READ_BIT);
+
+ if (NULL != src)
+ {
+ bx::memCopy(_data, src, _size);
+ GL_CHECK(glUnmapBuffer(GL_COPY_READ_BUFFER) );
+ }
+ else
+ {
+ bx::memSet(_data, 0, _size);
+ }
+
+ GL_CHECK(glBindBuffer(GL_COPY_READ_BUFFER, 0) );
+ }
+
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) override
{
TextureGL& texture = m_textures[_handle.idx];
@@ -3809,6 +3849,8 @@ namespace bgfx { namespace gl
void submitBlit(BlitState& _bs, uint16_t _view);
+ bool submitBlitBufferItem(const BlitItem& _bi);
+
void submitUniformCache(UniformCacheState& _ucs, uint16_t _view);
void submit(Frame* _render, const ClearQuad& _clearQuad, const MipGen& _mipGen, TextVideoMemBlitter& _textVideoMemBlitter) override;
@@ -7741,6 +7783,185 @@ namespace bgfx { namespace gl
return true;
}
+ static void blitBuffer(GLuint _src, GLuint _dst, const BlitItem& _bi)
+ {
+ if (NULL == glCopyBufferSubData)
+ {
+ return;
+ }
+
+ if (NULL != glMemoryBarrier)
+ {
+ GL_CHECK(glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT) );
+ }
+
+ GL_CHECK(glBindBuffer(GL_COPY_READ_BUFFER, _src) );
+ GL_CHECK(glBindBuffer(GL_COPY_WRITE_BUFFER, _dst) );
+
+ GL_CHECK(glCopyBufferSubData(
+ GL_COPY_READ_BUFFER
+ , GL_COPY_WRITE_BUFFER
+ , _bi.m_srcOffset
+ , _bi.m_dstOffset
+ , _bi.m_size
+ ) );
+
+ GL_CHECK(glBindBuffer(GL_COPY_READ_BUFFER, 0) );
+ GL_CHECK(glBindBuffer(GL_COPY_WRITE_BUFFER, 0) );
+ }
+
+ static void blitBufferToTexture(const TextureGL& _dst, GLuint _src, const BlitItem& _bi)
+ {
+ if (NULL == glBindBuffer)
+ {
+ return;
+ }
+
+ if (NULL != glMemoryBarrier)
+ {
+ GL_CHECK(glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT) );
+ }
+
+ GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _src) );
+ GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1) );
+ GL_CHECK(glBindTexture(_dst.m_target, _dst.m_id) );
+
+ uint32_t rowLength, imageHeight;
+ calcTextureRegionTexelPitch(
+ rowLength
+ , imageHeight
+ , TextureFormat::Enum(_dst.m_textureFormat)
+ , _bi.m_rowPitch
+ , _bi.m_slicePitch
+ );
+
+ GL_CHECK(glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength) );
+ GL_CHECK(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, imageHeight) );
+
+ const GLvoid* data = (const GLvoid*)uintptr_t(_bi.m_srcOffset);
+
+ if (GL_TEXTURE_3D == _dst.m_target
+ || GL_TEXTURE_2D_ARRAY == _dst.m_target
+ || GL_TEXTURE_CUBE_MAP_ARRAY == _dst.m_target)
+ {
+ GL_CHECK(glTexSubImage3D(
+ _dst.m_target
+ , _bi.m_dstMip
+ , _bi.m_dstX
+ , _bi.m_dstY
+ , _bi.m_dstZ
+ , _bi.m_width
+ , _bi.m_height
+ , bx::max(1, _bi.m_depth)
+ , _dst.m_fmt
+ , _dst.m_type
+ , data
+ ) );
+ }
+ else
+ {
+ GL_CHECK(glTexSubImage2D(
+ GL_TEXTURE_CUBE_MAP == _dst.m_target
+ ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + _bi.m_dstZ
+ : _dst.m_target
+ , _bi.m_dstMip
+ , _bi.m_dstX
+ , _bi.m_dstY
+ , _bi.m_width
+ , _bi.m_height
+ , _dst.m_fmt
+ , _dst.m_type
+ , data
+ ) );
+ }
+
+ GL_CHECK(glBindTexture(_dst.m_target, 0) );
+ GL_CHECK(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0) );
+ GL_CHECK(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) );
+ GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 4) );
+ GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0) );
+ }
+
+ static void blitTextureToBuffer(GLuint _dst, const TextureGL& _src, const BlitItem& _bi)
+ {
+ if (NULL == glBindBuffer)
+ {
+ return;
+ }
+
+ if (NULL == glGetTextureSubImage)
+ {
+ BX_WARN(false, "Blit texture into buffer is not supported. glGetTextureSubImage is unavailable.");
+
+ return;
+ }
+
+ GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, _dst) );
+ GL_CHECK(glPixelStorei(GL_PACK_ALIGNMENT, 1) );
+
+ uint32_t rowLength, imageHeight;
+ calcTextureRegionTexelPitch(
+ rowLength
+ , imageHeight
+ , TextureFormat::Enum(_src.m_textureFormat)
+ , _bi.m_rowPitch
+ , _bi.m_slicePitch
+ );
+
+ GL_CHECK(glPixelStorei(GL_PACK_ROW_LENGTH, rowLength) );
+ GL_CHECK(glPixelStorei(GL_PACK_IMAGE_HEIGHT, imageHeight) );
+
+ GL_CHECK(glGetTextureSubImage(
+ _src.m_id
+ , _bi.m_srcMip
+ , _bi.m_srcX
+ , _bi.m_srcY
+ , _bi.m_srcZ
+ , _bi.m_width
+ , _bi.m_height
+ , bx::max(1, _bi.m_depth)
+ , _src.m_fmt
+ , _src.m_type
+ , _bi.m_size
+ , (GLvoid*)uintptr_t(_bi.m_dstOffset)
+ ) );
+
+ GL_CHECK(glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0) );
+ GL_CHECK(glPixelStorei(GL_PACK_ROW_LENGTH, 0) );
+ GL_CHECK(glPixelStorei(GL_PACK_ALIGNMENT, 4) );
+ GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0) );
+ }
+
+ bool RendererContextGL::submitBlitBufferItem(const BlitItem& _bi)
+ {
+ const bool srcIsBuffer = _bi.m_src.isBuffer();
+ const bool dstIsBuffer = _bi.m_dst.isBuffer();
+
+ if (srcIsBuffer
+ && dstIsBuffer)
+ {
+ blitBuffer(getBufferId(_bi.m_src), getBufferId(_bi.m_dst), _bi);
+
+ return true;
+ }
+
+ if (dstIsBuffer)
+ {
+ blitTextureToBuffer(getBufferId(_bi.m_dst), m_textures[_bi.m_src.idx], _bi);
+
+ return true;
+ }
+
+ if (srcIsBuffer)
+ {
+ blitBufferToTexture(m_textures[_bi.m_dst.idx], getBufferId(_bi.m_src), _bi);
+
+ return true;
+ }
+
+ return false;
+ }
+
void RendererContextGL::submitBlit(BlitState& _bs, uint16_t _view)
{
if (m_blitSupported)
@@ -7749,6 +7970,11 @@ namespace bgfx { namespace gl
{
const BlitItem& bi = _bs.advance();
+ if (submitBlitBufferItem(bi) )
+ {
+ continue;
+ }
+
const TextureGL& src = m_textures[bi.m_src.idx];
const TextureGL& dst = m_textures[bi.m_dst.idx];
@@ -7820,6 +8046,11 @@ namespace bgfx { namespace gl
{
const BlitItem& bi = _bs.advance();
+ if (submitBlitBufferItem(bi) )
+ {
+ continue;
+ }
+
const TextureGL& src = m_textures[bi.m_src.idx];
const TextureGL& dst = m_textures[bi.m_dst.idx];
@@ -7865,6 +8096,15 @@ namespace bgfx { namespace gl
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_currentFbo) );
}
}
+ else
+ {
+ while (_bs.hasItem(_view) )
+ {
+ const BlitItem& bi = _bs.advance();
+
+ submitBlitBufferItem(bi);
+ }
+ }
}
void RendererContextGL::submitUniformCache(UniformCacheState& _ucs, uint16_t _view)
@@ -9120,6 +9360,7 @@ namespace bgfx { namespace gl
perfStats.numDraw = statsKeyType[0];
perfStats.numCompute = statsKeyType[1];
perfStats.numBlit = _render->m_numBlitItems;
+ perfStats.numBlitRepack = _render->m_numBlitRepack;
perfStats.maxGpuLatency = maxGpuLatency;
perfStats.gpuFrameNum = result.m_frameNum;
bx::memCopy(perfStats.numPrims, statsNumPrimsRendered, sizeof(perfStats.numPrims) );
diff --git a/src/renderer_gl.h b/src/renderer_gl.h
index b151853ad..13872c39e 100644
--- a/src/renderer_gl.h
+++ b/src/renderer_gl.h
@@ -341,6 +341,18 @@ typedef double GLdouble;
# define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
#endif // GL_UNSIGNED_INT_10F_11F_11F_REV
+#ifndef GL_COPY_READ_BUFFER
+# define GL_COPY_READ_BUFFER 0x8F36
+#endif // GL_COPY_READ_BUFFER
+
+#ifndef GL_COPY_WRITE_BUFFER
+# define GL_COPY_WRITE_BUFFER 0x8F37
+#endif // GL_COPY_WRITE_BUFFER
+
+#ifndef GL_MAP_READ_BIT
+# define GL_MAP_READ_BIT 0x0001
+#endif // GL_MAP_READ_BIT
+
#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
# define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#endif // GL_COMPRESSED_RGB_S3TC_DXT1_EXT
@@ -738,6 +750,18 @@ typedef double GLdouble;
# define GL_UNPACK_ROW_LENGTH 0x0CF2
#endif // GL_UNPACK_ROW_LENGTH
+#ifndef GL_UNPACK_IMAGE_HEIGHT
+# define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#endif // GL_UNPACK_IMAGE_HEIGHT
+
+#ifndef GL_PACK_ROW_LENGTH
+# define GL_PACK_ROW_LENGTH 0x0D02
+#endif // GL_PACK_ROW_LENGTH
+
+#ifndef GL_PACK_IMAGE_HEIGHT
+# define GL_PACK_IMAGE_HEIGHT 0x806C
+#endif // GL_PACK_IMAGE_HEIGHT
+
#ifndef GL_DEPTH_STENCIL
# define GL_DEPTH_STENCIL 0x84F9
#endif // GL_DEPTH_STENCIL
@@ -886,6 +910,10 @@ typedef double GLdouble;
# define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
#endif // GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
+#ifndef GL_BUFFER_UPDATE_BARRIER_BIT
+# define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#endif // GL_BUFFER_UPDATE_BARRIER_BIT
+
#ifndef GL_SHADER_STORAGE_BARRIER_BIT
# define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
#endif // GL_SHADER_STORAGE_BARRIER_BIT
diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp
index 0dbaf44f6..dfeeb6475 100644
--- a/src/renderer_mtl.cpp
+++ b/src/renderer_mtl.cpp
@@ -1683,6 +1683,33 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
texture.m_ptr->getBytes(_data, bytesPerRow, 0, region, _mip, _layer);
}
+ BufferMtl& getBuffer(Handle _handle)
+ {
+ if (_handle.isIndexBuffer() )
+ {
+ return m_indexBuffers[_handle.idx];
+ }
+
+ return m_vertexBuffers[_handle.idx];
+ }
+
+ void readBuffer(Handle _handle, void* _data, uint32_t _offset, uint32_t _size) override
+ {
+ BufferMtl& buffer = getBuffer(_handle);
+
+ MTL::BlitCommandEncoder* bce = s_renderMtl->getBlitCommandEncoder();
+#if BX_PLATFORM_OSX
+ bce->synchronizeResource(buffer.m_ptr);
+#endif // BX_PLATFORM_OSX
+ BX_UNUSED(bce);
+ endEncoding();
+
+ m_cmd.kick(false, true);
+ m_commandBuffer = NULL;
+
+ bx::memCopy(_data, (const uint8_t*)buffer.m_ptr->contents() + _offset, _size);
+ }
+
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) override
{
TextureMtl& texture = m_textures[_handle.idx];
@@ -5693,6 +5720,77 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
{
const BlitItem& blit = _bs.advance();
+ if (blit.m_src.isBuffer()
+ && blit.m_dst.isBuffer() )
+ {
+ const BufferMtl& srcBuf = getBuffer(blit.m_src);
+ const BufferMtl& dstBuf = getBuffer(blit.m_dst);
+ m_blitCommandEncoder->copyFromBuffer(srcBuf.m_ptr, blit.m_srcOffset, dstBuf.m_ptr, blit.m_dstOffset, blit.m_size);
+
+ continue;
+ }
+
+ if (blit.m_src.isBuffer() )
+ {
+ const BufferMtl& srcBuf = getBuffer(blit.m_src);
+ const TextureMtl& dstTex = m_textures[blit.m_dst.idx];
+
+ const uint32_t depth = bx::max(blit.m_depth, 1);
+ const bool is3D = MTL::TextureType3D == dstTex.m_ptr->textureType();
+
+ m_blitCommandEncoder->copyFromBuffer(
+ srcBuf.m_ptr
+ , blit.m_srcOffset
+ , blit.m_rowPitch
+ , blit.m_slicePitch
+ , MTL::Size::Make(blit.m_width, blit.m_height, is3D ? depth : 1)
+ , dstTex.m_ptr
+ , is3D ? 0 : blit.m_dstZ
+ , blit.m_dstMip
+ , MTL::Origin::Make(blit.m_dstX, blit.m_dstY, is3D ? blit.m_dstZ : 0)
+ );
+
+ continue;
+ }
+
+ if (blit.m_dst.isBuffer() )
+ {
+ const TextureMtl& srcTex = m_textures[blit.m_src.idx];
+ const BufferMtl& dstBuf = getBuffer(blit.m_dst);
+
+ if (NULL != srcTex.m_ptrMsaa)
+ {
+ BX_ASSERT(false, "Can't blit between buffer and MSAA texture.");
+
+ continue;
+ }
+
+ const uint32_t depth = bx::max(blit.m_depth, 1);
+ const bool is3D = MTL::TextureType3D == srcTex.m_ptr->textureType();
+
+ m_blitCommandEncoder->copyFromTexture(
+ srcTex.m_ptr
+ , is3D ? 0 : blit.m_srcZ
+ , blit.m_srcMip
+ , MTL::Origin::Make(blit.m_srcX, blit.m_srcY, is3D ? blit.m_srcZ : 0)
+ , MTL::Size::Make(blit.m_width, blit.m_height, is3D ? depth : 1)
+ , dstBuf.m_ptr
+ , blit.m_dstOffset
+ , blit.m_rowPitch
+ , blit.m_slicePitch
+ );
+
+#if BX_PLATFORM_OSX
+ if (m_hasSynchronizeResource
+ && MTL::StorageModeManaged == dstBuf.m_ptr->storageMode() )
+ {
+ m_blitCommandEncoder->synchronizeResource(dstBuf.m_ptr);
+ }
+#endif // BX_PLATFORM_OSX
+
+ continue;
+ }
+
const TextureMtl& src = m_textures[blit.m_src.idx];
const TextureMtl& dst = m_textures[blit.m_dst.idx];
@@ -6949,6 +7047,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
perfStats.numDraw = statsKeyType[0];
perfStats.numCompute = statsKeyType[1];
perfStats.numBlit = _render->m_numBlitItems;
+ perfStats.numBlitRepack = _render->m_numBlitRepack;
perfStats.maxGpuLatency = maxGpuLatency;
perfStats.gpuFrameNum = m_gpuTimer.m_frameNum;
bx::memCopy(perfStats.numPrims, statsNumPrimsRendered, sizeof(perfStats.numPrims) );
diff --git a/src/renderer_noop.cpp b/src/renderer_noop.cpp
index 290babc0d..2baa2d8e7 100644
--- a/src/renderer_noop.cpp
+++ b/src/renderer_noop.cpp
@@ -182,6 +182,10 @@ namespace bgfx { namespace noop
{
}
+ void readBuffer(Handle /*_handle*/, void* /*_data*/, uint32_t /*_offset*/, uint32_t /*_size*/) override
+ {
+ }
+
void resizeTexture(TextureHandle /*_handle*/, uint16_t /*_width*/, uint16_t /*_height*/, uint8_t /*_numMips*/, uint16_t /*_numLayers*/) override
{
}
diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp
index e65d68ceb..511a445f8 100644
--- a/src/renderer_vk.cpp
+++ b/src/renderer_vk.cpp
@@ -2736,6 +2736,47 @@ VK_IMPORT_DEVICE
recycleMemory(stagingMemory);
}
+ BufferVK& getBuffer(Handle _handle)
+ {
+ if (_handle.isIndexBuffer() )
+ {
+ return m_indexBuffers[_handle.idx];
+ }
+
+ return m_vertexBuffers[_handle.idx];
+ }
+
+ void readBuffer(Handle _handle, void* _data, uint32_t _offset, uint32_t _size) override
+ {
+ const BufferVK& buffer = getBuffer(_handle);
+
+ DeviceMemoryAllocationVK stagingMemory;
+ VkBuffer stagingBuffer;
+ VK_CHECK(createReadbackBuffer(_size, &stagingBuffer, &stagingMemory) );
+
+ setMemoryBarrier(
+ m_commandBuffer
+ , VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
+ , VK_PIPELINE_STAGE_TRANSFER_BIT
+ );
+
+ VkBufferCopy region;
+ region.srcOffset = _offset;
+ region.dstOffset = 0;
+ region.size = _size;
+ vkCmdCopyBuffer(m_commandBuffer, buffer.m_buffer, stagingBuffer, 1, ®ion);
+
+ kick(true);
+
+ void* dst = NULL;
+ VK_CHECK(vkMapMemory(m_device, stagingMemory.mem, stagingMemory.offset, _size, 0, &dst) );
+ bx::memCopy(_data, dst, _size);
+ vkUnmapMemory(m_device, stagingMemory.mem);
+
+ vkDestroy(stagingBuffer);
+ recycleMemory(stagingMemory);
+ }
+
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) override
{
const TextureVK& texture = m_textures[_handle.idx];
@@ -5580,6 +5621,7 @@ VK_DESTROY
| (_vertex ? VK_BUFFER_USAGE_VERTEX_BUFFER_BIT : VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
| (storage || indirect ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : 0)
| (indirect ? VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT : 0)
+ | (storage || indirect ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0)
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
;
bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
@@ -9606,6 +9648,27 @@ VK_DESTROY
const BlitItem& blit = bs0.advance();
+ srcLayouts[item] = VK_IMAGE_LAYOUT_UNDEFINED;
+ dstLayouts[item] = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ if (blit.m_src.isBuffer()
+ && blit.m_dst.isBuffer() )
+ {
+ continue;
+ }
+
+ if (blit.m_src.isBuffer() )
+ {
+ dstLayouts[item] = m_textures[blit.m_dst.idx].m_currentImageLayout;
+ continue;
+ }
+
+ if (blit.m_dst.isBuffer() )
+ {
+ srcLayouts[item] = m_textures[blit.m_src.idx].m_currentImageLayout;
+ continue;
+ }
+
TextureVK& src = m_textures[blit.m_src.idx];
TextureVK& dst = m_textures[blit.m_dst.idx];
@@ -9628,6 +9691,127 @@ VK_DESTROY
{
const BlitItem& blit = bs0.advance();
+ if (blit.m_src.isBuffer()
+ && blit.m_dst.isBuffer() )
+ {
+ const BufferVK& srcBuf = getBuffer(blit.m_src);
+ const BufferVK& dstBuf = getBuffer(blit.m_dst);
+
+ setMemoryBarrier(
+ m_commandBuffer
+ , VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
+ , VK_PIPELINE_STAGE_TRANSFER_BIT
+ );
+
+ VkBufferCopy region;
+ region.srcOffset = blit.m_srcOffset;
+ region.dstOffset = blit.m_dstOffset;
+ region.size = blit.m_size;
+ vkCmdCopyBuffer(m_commandBuffer, srcBuf.m_buffer, dstBuf.m_buffer, 1, ®ion);
+
+ setMemoryBarrier(
+ m_commandBuffer
+ , VK_PIPELINE_STAGE_TRANSFER_BIT
+ , VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
+ );
+
+ continue;
+ }
+
+ if (blit.m_src.isBuffer()
+ || blit.m_dst.isBuffer() )
+ {
+ const bool toBuffer = blit.m_dst.isBuffer();
+
+ TextureVK& texture = m_textures[toBuffer ? blit.m_src.idx : blit.m_dst.idx];
+ const BufferVK& buffer = getBuffer(toBuffer ? blit.m_dst : blit.m_src);
+
+ BX_ASSERT(1 == texture.m_sampler.Count, "Can't blit between buffer and MSAA texture.");
+
+ texture.setState(
+ m_commandBuffer
+ , toBuffer
+ ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
+ : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ );
+
+ setMemoryBarrier(
+ m_commandBuffer
+ , VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
+ , VK_PIPELINE_STAGE_TRANSFER_BIT
+ );
+
+ const bool is3D = VK_IMAGE_VIEW_TYPE_3D == texture.m_type;
+ const uint32_t depth = bx::max(1, blit.m_depth);
+ const uint16_t z = toBuffer ? blit.m_srcZ : blit.m_dstZ;
+
+ uint32_t rowLength, imageHeight;
+ calcTextureRegionTexelPitch(
+ rowLength
+ , imageHeight
+ , TextureFormat::Enum(texture.m_textureFormat)
+ , blit.m_rowPitch
+ , blit.m_slicePitch
+ );
+
+ const VkBufferImageCopy region =
+ {
+ .bufferOffset = toBuffer ? blit.m_dstOffset : blit.m_srcOffset,
+ .bufferRowLength = rowLength,
+ .bufferImageHeight = imageHeight,
+ .imageSubresource =
+ {
+ .aspectMask = texture.m_aspectFlags,
+ .mipLevel = toBuffer ? blit.m_srcMip : blit.m_dstMip,
+ .baseArrayLayer = is3D ? 0u : uint32_t(z),
+ .layerCount = is3D ? 1u : depth,
+ },
+ .imageOffset =
+ {
+ .x = toBuffer ? blit.m_srcX : blit.m_dstX,
+ .y = toBuffer ? blit.m_srcY : blit.m_dstY,
+ .z = is3D ? z : 0,
+ },
+ .imageExtent =
+ {
+ .width = blit.m_width,
+ .height = blit.m_height,
+ .depth = is3D ? depth : 1,
+ },
+ };
+
+ if (toBuffer)
+ {
+ vkCmdCopyImageToBuffer(
+ m_commandBuffer
+ , texture.m_textureImage
+ , texture.m_currentImageLayout
+ , buffer.m_buffer
+ , 1
+ , ®ion
+ );
+ }
+ else
+ {
+ vkCmdCopyBufferToImage(
+ m_commandBuffer
+ , buffer.m_buffer
+ , texture.m_textureImage
+ , texture.m_currentImageLayout
+ , 1
+ , ®ion
+ );
+ }
+
+ setMemoryBarrier(
+ m_commandBuffer
+ , VK_PIPELINE_STAGE_TRANSFER_BIT
+ , VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
+ );
+
+ continue;
+ }
+
TextureVK& src = m_textures[blit.m_src.idx];
TextureVK& dst = m_textures[blit.m_dst.idx];
@@ -9762,6 +9946,24 @@ VK_DESTROY
{
const BlitItem& blit = _bs.advance();
+ if (blit.m_src.isBuffer()
+ && blit.m_dst.isBuffer() )
+ {
+ continue;
+ }
+
+ if (blit.m_src.isBuffer() )
+ {
+ m_textures[blit.m_dst.idx].setState(m_commandBuffer, dstLayouts[item]);
+ continue;
+ }
+
+ if (blit.m_dst.isBuffer() )
+ {
+ m_textures[blit.m_src.idx].setState(m_commandBuffer, srcLayouts[item]);
+ continue;
+ }
+
TextureVK& src = m_textures[blit.m_src.idx];
TextureVK& dst = m_textures[blit.m_dst.idx];
@@ -10907,6 +11109,7 @@ VK_DESTROY
perfStats.numDraw = statsKeyType[0];
perfStats.numCompute = statsKeyType[1];
perfStats.numBlit = _render->m_numBlitItems;
+ perfStats.numBlitRepack = _render->m_numBlitRepack;
perfStats.maxGpuLatency = maxGpuLatency;
perfStats.gpuFrameNum = result.m_frameNum;
bx::memCopy(perfStats.numPrims, statsNumPrimsRendered, sizeof(perfStats.numPrims) );
diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp
index b58e00d45..62f76a9a6 100644
--- a/src/renderer_webgpu.cpp
+++ b/src/renderer_webgpu.cpp
@@ -1416,14 +1416,16 @@ WGPU_IMPORT
BX_TRACE("\tmaxComputeWorkgroupsPerDimension: %u", m_limits.maxComputeWorkgroupsPerDimension);
BX_TRACE("\tmaxImmediateSize: %u", m_limits.maxImmediateSize);
- g_caps.limits.maxTextureSize = m_limits.maxTextureDimension2D;
- g_caps.limits.maxTextureLayers = m_limits.maxTextureArrayLayers;
- g_caps.limits.maxTextureSamplers = bx::min(m_limits.maxSamplersPerShaderStage, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS);
- g_caps.limits.maxComputeBindings = BGFX_CONFIG_MAX_TEXTURE_SAMPLERS;
- g_caps.limits.maxFBAttachments = bx::min(m_limits.maxColorAttachments, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS);
- g_caps.limits.maxVertexStreams = bx::min(m_limits.maxVertexBuffers, BGFX_CONFIG_MAX_VERTEX_STREAMS);
+ g_caps.limits.maxTextureSize = m_limits.maxTextureDimension2D;
+ g_caps.limits.maxTextureLayers = m_limits.maxTextureArrayLayers;
+ g_caps.limits.maxTextureSamplers = bx::min(m_limits.maxSamplersPerShaderStage, BGFX_CONFIG_MAX_TEXTURE_SAMPLERS);
+ g_caps.limits.maxComputeBindings = BGFX_CONFIG_MAX_TEXTURE_SAMPLERS;
+ g_caps.limits.maxFBAttachments = bx::min(m_limits.maxColorAttachments, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS);
+ g_caps.limits.maxVertexStreams = bx::min(m_limits.maxVertexBuffers, BGFX_CONFIG_MAX_VERTEX_STREAMS);
g_caps.limits.maxVertexAttributes = m_limits.maxVertexAttributes;
- g_caps.limits.maxInstanceData = bx::min(g_caps.limits.maxInstanceData, g_caps.limits.maxVertexAttributes);
+ g_caps.limits.maxInstanceData = bx::min(g_caps.limits.maxInstanceData, g_caps.limits.maxVertexAttributes);
+ g_caps.limits.blitRowPitchAlign = 256;
+ g_caps.limits.blitOffsetAlign = 256;
g_caps.supported = 0
| BGFX_CAPS_ALPHA_TO_COVERAGE
@@ -1798,6 +1800,36 @@ WGPU_IMPORT
*(bool*)(_userdata2) = true;
}
+ struct ReadBuffer
+ {
+ WGPUBuffer buffer;
+ uint32_t size;
+ void* data;
+ };
+
+ static void readBufferCb(WGPUMapAsyncStatus _status, WGPUStringView _message, void* _userdata1, void* _userdata2)
+ {
+ BX_ASSERT(WGPUMapAsyncStatus_Success == _status, "%d", _status);
+
+ BX_UNUSED(_status, _message, _userdata2);
+
+ ReadBuffer& readBuffer = *(ReadBuffer*)_userdata1;
+
+ const void* result = (const void*)WGPU_CHECK(wgpuBufferGetConstMappedRange(
+ readBuffer.buffer
+ , 0
+ , readBuffer.size
+ ) );
+
+ bx::memCopy(readBuffer.data, result, readBuffer.size);
+
+ WGPU_CHECK(wgpuBufferUnmap(readBuffer.buffer) );
+
+ wgpuRelease(readBuffer.buffer);
+
+ *(bool*)(_userdata2) = true;
+ }
+
void readTexture(TextureHandle _handle, void* _data, uint16_t _layer, uint8_t _mip) override
{
const TextureWGPU& texture = m_textures[_handle.idx];
@@ -1887,6 +1919,66 @@ WGPU_IMPORT
}
}
+ BufferWGPU& getBuffer(Handle _handle)
+ {
+ if (_handle.isIndexBuffer() )
+ {
+ return m_indexBuffers[_handle.idx];
+ }
+
+ return m_vertexBuffers[_handle.idx];
+ }
+
+ void readBuffer(Handle _handle, void* _data, uint32_t _offset, uint32_t _size) override
+ {
+ const BufferWGPU& buffer = getBuffer(_handle);
+
+ WGPUBufferDescriptor readBufferDesc =
+ {
+ .nextInChain = NULL,
+ .label = toWGPUStringView("Read Buffer"),
+ .usage = 0
+ | WGPUBufferUsage_MapRead
+ | WGPUBufferUsage_CopyDst
+ ,
+ .size = _size,
+ .mappedAtCreation = false,
+ };
+
+ WGPUBuffer readBufferDst = WGPU_CHECK(wgpuDeviceCreateBuffer(m_device, &readBufferDesc) );
+
+ s_done = false;
+
+ m_cmd.copyBufferToBuffer(buffer.m_buffer, _offset, readBufferDst, 0, _size);
+
+ m_cmd.kick();
+
+ ReadBuffer readBuffer =
+ {
+ .buffer = readBufferDst,
+ .size = _size,
+ .data = _data,
+ };
+
+ WGPU_CHECK(wgpuBufferMapAsync(
+ readBufferDst
+ , WGPUMapMode_Read
+ , 0
+ , _size
+ , {
+ .nextInChain = NULL,
+ .mode = WGPUCallbackMode_AllowProcessEvents,
+ .callback = readBufferCb,
+ .userdata1 = &readBuffer,
+ .userdata2 = &s_done,
+ }) );
+
+ while (!s_done)
+ {
+ wgpuInstanceProcessEvents(m_instance);
+ }
+ }
+
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) override
{
TextureWGPU& texture = m_textures[_handle.idx];
@@ -2052,6 +2144,8 @@ WGPU_IMPORT
void submitBlit(BlitState& _bs, uint16_t _view);
+ void blitBufferTexture(const BlitItem& _blit);
+
void submitUniformCache(UniformCacheState& _ucs, uint16_t _view);
void generateMips(WGPUCommandEncoder _cmdEncoder, TextureWGPU& _texture, TextureHandle _textureHandle);
@@ -3620,6 +3714,7 @@ WGPU_IMPORT
.label = WGPU_STRING_VIEW_INIT,
.usage = 0
| (storage ? WGPUBufferUsage_Storage : 0)
+ | (storage ? WGPUBufferUsage_CopySrc : 0)
| (indirect
? WGPUBufferUsage_Indirect
: _vertex ? WGPUBufferUsage_Vertex : WGPUBufferUsage_Index
@@ -5628,12 +5723,118 @@ m_resolution.formatColor = TextureFormat::BGRA8;
}
}
+ void RendererContextWGPU::blitBufferTexture(const BlitItem& _blit)
+ {
+ const bool toBuffer = _blit.m_dst.isBuffer();
+
+ const TextureWGPU& texture = m_textures[toBuffer ? _blit.m_src.idx : _blit.m_dst.idx];
+ const BufferWGPU& buffer = getBuffer(toBuffer ? _blit.m_dst : _blit.m_src);
+
+ const uint32_t bufferOffset = toBuffer ? _blit.m_dstOffset : _blit.m_srcOffset;
+
+ const TextureFormat::Enum format = TextureFormat::Enum(texture.m_textureFormat);
+
+ const uint32_t rowPitch = _blit.m_rowPitch;
+ const uint32_t slicePitch = _blit.m_slicePitch;
+ const uint32_t numRows = calcTextureRegionNumRows(format, _blit.m_height);
+ const uint32_t depth = bx::max(1, _blit.m_depth);
+
+ const uint32_t rowsPerImage = slicePitch / rowPitch;
+
+ const uint8_t mip = toBuffer ? _blit.m_srcMip : _blit.m_dstMip;
+ const uint16_t x = toBuffer ? _blit.m_srcX : _blit.m_dstX;
+ const uint16_t y = toBuffer ? _blit.m_srcY : _blit.m_dstY;
+ const uint16_t z = toBuffer ? _blit.m_srcZ : _blit.m_dstZ;
+
+ const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(format) );
+
+ const uint32_t blockHeight = bx::max(1, blockInfo.blockHeight);
+
+ const uint32_t offsetAlign = bimg::isDepth(bimg::TextureFormat::Enum(format) )
+ ? 4
+ : blockInfo.blockSize
+ ;
+
+ const bool direct = (1 == numRows*depth || 0 == rowPitch % 256)
+ && 0 == bufferOffset % offsetAlign
+ ;
+
+ const uint32_t numCopies = direct ? 1 : numRows*depth;
+ const uint32_t copyRows = direct ? numRows : 1;
+ const uint32_t copyDepth = direct ? depth : 1;
+
+ for (uint32_t ii = 0; ii < numCopies; ++ii)
+ {
+ const uint32_t slice = direct ? 0 : ii / numRows;
+ const uint32_t row = direct ? 0 : ii % numRows;
+
+ const WGPUTexelCopyBufferInfo bufferInfo =
+ {
+ .layout =
+ {
+ .offset = bufferOffset + slice*slicePitch + row*rowPitch,
+ .bytesPerRow = 1 < copyRows*copyDepth ? rowPitch : WGPU_COPY_STRIDE_UNDEFINED,
+ .rowsPerImage = 1 < copyDepth ? rowsPerImage : WGPU_COPY_STRIDE_UNDEFINED,
+ },
+ .buffer = buffer.m_buffer,
+ };
+
+ const WGPUTexelCopyTextureInfo textureInfo =
+ {
+ .texture = texture.m_texture,
+ .mipLevel = mip,
+ .origin =
+ {
+ .x = x,
+ .y = y + row*blockHeight,
+ .z = z + slice,
+ },
+ .aspect = WGPUTextureAspect_All,
+ };
+
+ const WGPUExtent3D copySize =
+ {
+ .width = _blit.m_width,
+ .height = copyRows*blockHeight,
+ .depthOrArrayLayers = copyDepth,
+ };
+
+ if (toBuffer)
+ {
+ m_cmd.copyTextureToBuffer(textureInfo, bufferInfo, copySize);
+ }
+ else
+ {
+ m_cmd.copyBufferToTexture(bufferInfo, textureInfo, copySize);
+ }
+ }
+ }
+
void RendererContextWGPU::submitBlit(BlitState& _bs, uint16_t _view)
{
while (_bs.hasItem(_view) )
{
const BlitItem& blit = _bs.advance();
+ if (blit.m_src.isBuffer()
+ && blit.m_dst.isBuffer() )
+ {
+ const BufferWGPU& srcBuf = getBuffer(blit.m_src);
+ const BufferWGPU& dstBuf = getBuffer(blit.m_dst);
+
+ m_cmd.copyBufferToBuffer(srcBuf.m_buffer, blit.m_srcOffset, dstBuf.m_buffer, blit.m_dstOffset, blit.m_size);
+
+ continue;
+ }
+
+ if (blit.m_src.isBuffer()
+ || blit.m_dst.isBuffer() )
+ {
+ blitBufferTexture(blit);
+
+ continue;
+ }
+
const TextureWGPU& src = m_textures[blit.m_src.idx];
const TextureWGPU& dst = m_textures[blit.m_dst.idx];
@@ -7007,6 +7208,7 @@ m_resolution.formatColor = TextureFormat::BGRA8;
perfStats.numDraw = statsKeyType[0];
perfStats.numCompute = statsKeyType[1];
perfStats.numBlit = _render->m_numBlitItems;
+ perfStats.numBlitRepack = _render->m_numBlitRepack;
perfStats.gpuMemoryMax = -INT64_MAX;
perfStats.gpuMemoryUsed = -INT64_MAX;