Added bgfx::isFrameBufferValid API.

This commit is contained in:
Бранимир Караџић 2021-04-16 22:13:26 -07:00
parent 41df93f81d
commit 6109697ade
11 changed files with 278 additions and 107 deletions

View File

@ -2994,6 +2994,16 @@ public static class bgfx
[LinkName("bgfx_is_texture_valid")]
public static extern bool is_texture_valid(uint16 _depth, bool _cubeMap, uint16 _numLayers, TextureFormat _format, uint64 _flags);
/// <summary>
/// Validate frame buffer parameters.
/// </summary>
///
/// <param name="_num">Number of attachments.</param>
/// <param name="_attachment">Attachment texture info. See: `bgfx::Attachment`.</param>
///
[LinkName("bgfx_is_frame_buffer_valid")]
public static extern bool is_frame_buffer_valid(uint8 _num, Attachment* _attachment);
/// <summary>
/// Calculate amount of memory required for texture.
/// </summary>

View File

@ -2950,6 +2950,17 @@ public static partial class bgfx
[return: MarshalAs(UnmanagedType.I1)]
public static extern unsafe bool is_texture_valid(ushort _depth, bool _cubeMap, ushort _numLayers, TextureFormat _format, ulong _flags);
/// <summary>
/// Validate frame buffer parameters.
/// </summary>
///
/// <param name="_num">Number of attachments.</param>
/// <param name="_attachment">Attachment texture info. See: `bgfx::Attachment`.</param>
///
[DllImport(DllName, EntryPoint="bgfx_is_frame_buffer_valid", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern unsafe bool is_frame_buffer_valid(byte _num, Attachment* _attachment);
/// <summary>
/// Calculate amount of memory required for texture.
/// </summary>

View File

@ -698,6 +698,14 @@ version(BindBgfx_Static)
*/
bool bgfx_is_texture_valid(ushort _depth, bool _cubeMap, ushort _numLayers, bgfx_texture_format_t _format, ulong _flags);
/**
* Validate frame buffer parameters.
* Params:
* _num = Number of attachments.
* _attachment = Attachment texture info. See: `bgfx::Attachment`.
*/
bool bgfx_is_frame_buffer_valid(byte _num, const(bgfx_attachment_t)* _attachment);
/**
* Calculate amount of memory required for texture.
* Params:
@ -2897,6 +2905,15 @@ else
alias da_bgfx_is_texture_valid = bool function(ushort _depth, bool _cubeMap, ushort _numLayers, bgfx_texture_format_t _format, ulong _flags);
da_bgfx_is_texture_valid bgfx_is_texture_valid;
/**
* Validate frame buffer parameters.
* Params:
* _num = Number of attachments.
* _attachment = Attachment texture info. See: `bgfx::Attachment`.
*/
alias da_bgfx_is_frame_buffer_valid = bool function(byte _num, const(bgfx_attachment_t)* _attachment);
da_bgfx_is_frame_buffer_valid bgfx_is_frame_buffer_valid;
/**
* Calculate amount of memory required for texture.
* Params:

View File

@ -10,7 +10,7 @@ public import core.stdc.stdarg : va_list;
extern(C) @nogc nothrow:
enum uint BGFX_API_VERSION = 112;
enum uint BGFX_API_VERSION = 113;
alias bgfx_view_id_t = ushort;

View File

@ -2629,6 +2629,18 @@ namespace bgfx
, uint64_t _flags
);
/// Validate frame buffer parameters.
///
/// @param[in] _num Number of attachments.
/// @param[in] _attachment Attachment texture info. See: `bgfx::Attachment`.
///
/// @returns True if frame buffer can be successfully created.
///
bool isFrameBufferValid(
uint8_t _num
, const Attachment* _attachment
);
/// Calculate amount of memory required for texture.
///
/// @param[out] _info Resulting texture info structure. See: `TextureInfo`.

View File

@ -1705,6 +1705,17 @@ BGFX_C_API void bgfx_destroy_program(bgfx_program_handle_t _handle);
*/
BGFX_C_API bool bgfx_is_texture_valid(uint16_t _depth, bool _cubeMap, uint16_t _numLayers, bgfx_texture_format_t _format, uint64_t _flags);
/**
* Validate frame buffer parameters.
*
* @param[in] _num Number of attachments.
* @param[in] _attachment Attachment texture info. See: `bgfx::Attachment`.
*
* @returns True if frame buffer can be successfully created.
*
*/
BGFX_C_API bool bgfx_is_frame_buffer_valid(uint8_t _num, const bgfx_attachment_t* _attachment);
/**
* Calculate amount of memory required for texture.
*
@ -3402,6 +3413,7 @@ typedef enum bgfx_function_id
BGFX_FUNCTION_ID_CREATE_COMPUTE_PROGRAM,
BGFX_FUNCTION_ID_DESTROY_PROGRAM,
BGFX_FUNCTION_ID_IS_TEXTURE_VALID,
BGFX_FUNCTION_ID_IS_FRAME_BUFFER_VALID,
BGFX_FUNCTION_ID_CALC_TEXTURE_SIZE,
BGFX_FUNCTION_ID_CREATE_TEXTURE,
BGFX_FUNCTION_ID_CREATE_TEXTURE_2D,
@ -3601,6 +3613,7 @@ struct bgfx_interface_vtbl
bgfx_program_handle_t (*create_compute_program)(bgfx_shader_handle_t _csh, bool _destroyShaders);
void (*destroy_program)(bgfx_program_handle_t _handle);
bool (*is_texture_valid)(uint16_t _depth, bool _cubeMap, uint16_t _numLayers, bgfx_texture_format_t _format, uint64_t _flags);
bool (*is_frame_buffer_valid)(uint8_t _num, const bgfx_attachment_t* _attachment);
void (*calc_texture_size)(bgfx_texture_info_t * _info, uint16_t _width, uint16_t _height, uint16_t _depth, bool _cubeMap, bool _hasMips, uint16_t _numLayers, bgfx_texture_format_t _format);
bgfx_texture_handle_t (*create_texture)(const bgfx_memory_t* _mem, uint64_t _flags, uint8_t _skip, bgfx_texture_info_t* _info);
bgfx_texture_handle_t (*create_texture_2d)(uint16_t _width, uint16_t _height, bool _hasMips, uint16_t _numLayers, bgfx_texture_format_t _format, uint64_t _flags, const bgfx_memory_t* _mem);

View File

@ -15,7 +15,7 @@
#ifndef BGFX_DEFINES_H_HEADER_GUARD
#define BGFX_DEFINES_H_HEADER_GUARD
#define BGFX_API_VERSION UINT32_C(112)
#define BGFX_API_VERSION UINT32_C(113)
/**
* Color RGB/alpha/depth write. When it's not specified write will be disabled.

View File

@ -1,7 +1,7 @@
-- vim: syntax=lua
-- bgfx interface
version(112)
version(113)
typedef "bool"
typedef "char"
@ -1593,6 +1593,12 @@ func.isTextureValid
.format "TextureFormat::Enum" --- Texture format. See: `TextureFormat::Enum`.
.flags "uint64_t" --- Texture flags. See `BGFX_TEXTURE_*`.
--- Validate frame buffer parameters.
func.isFrameBufferValid
"bool" --- True if frame buffer can be successfully created.
.num "uint8_t" --- Number of attachments.
.attachment "const Attachment*" --- Attachment texture info. See: `bgfx::Attachment`.
--- Calculate amount of memory required for texture.
func.calcTextureSize
"void"

View File

@ -17,6 +17,7 @@
#endif // BX_PLATFORM_OSX
BX_ERROR_RESULT(BGFX_ERROR_TEXTURE_VALIDATION, BX_MAKEFOURCC('b', 'g', 0, 1) );
BX_ERROR_RESULT(BGFX_ERROR_FRAME_BUFFER_VALIDATION, BX_MAKEFOURCC('b', 'g', 0, 2) );
namespace bgfx
{
@ -4328,8 +4329,24 @@ namespace bgfx
s_ctx->destroyProgram(_handle);
}
void checkFrameBuffer(uint8_t _num, const Attachment* _attachment)
#define BGFX_ERROR_CHECK(_condition, _err, _result, _msg, _format, ...) \
if (!BX_IGNORE_C4127(_condition) ) \
{ \
BX_ERROR_SET(_err, _result, _msg); \
BX_TRACE("%.*s: '%.*s' - " _format \
, bxErrorScope.getName().getLength() \
, bxErrorScope.getName().getPtr() \
, _err->getMessage().getLength() \
, _err->getMessage().getPtr() \
, ##__VA_ARGS__ \
); \
return; \
}
void isFrameBufferValid(uint8_t _num, const Attachment* _attachment, bx::Error* _err)
{
BX_ERROR_SCOPE(_err, "Frame buffer validation");
uint8_t color = 0;
uint8_t depth = 0;
@ -4337,60 +4354,104 @@ namespace bgfx
const uint16_t firstAttachmentWidth = bx::max<uint16_t>(firstTexture.m_width >> _attachment[0].mip, 1);
const uint16_t firstAttachmentHeight = bx::max<uint16_t>(firstTexture.m_height >> _attachment[0].mip, 1);
BX_UNUSED(firstAttachmentWidth, firstAttachmentHeight);
for (uint32_t ii = 0; ii < _num; ++ii)
{
const TextureHandle texHandle = _attachment[ii].handle;
BGFX_CHECK_HANDLE("createFrameBuffer texture", s_ctx->m_textureHandle, texHandle);
const Attachment& at = _attachment[ii];
const TextureHandle texHandle = at.handle;
const TextureRef& tr = s_ctx->m_textureRef[texHandle.idx];
BX_ASSERT(_attachment[ii].mip < tr.m_numMips
, "Invalid texture mip level (%d > %d)."
, _attachment[ii].mip
, tr.m_numMips - 1
BGFX_ERROR_CHECK(true
&& isValid(texHandle)
&& s_ctx->m_textureHandle.isValid(texHandle.idx)
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Invalid texture attachment."
, "Attachment %d, texture handle %d."
, ii
, texHandle.idx
);
BGFX_ERROR_CHECK(
at.mip < tr.m_numMips
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Invalid texture mip level."
, "Attachment %d, Mip %d, texture number of mips %d."
, ii
, at.mip
, tr.m_numMips
);
{
const uint16_t numLayers = tr.is3D()
? bx::max<uint16_t>(tr.m_depth >> _attachment[ii].mip, 1)
? bx::max<uint16_t>(tr.m_depth >> at.mip, 1)
: tr.m_numLayers * (tr.isCubeMap() ? 6 : 1)
;
BX_UNUSED(numLayers);
BX_ASSERT( (_attachment[ii].layer + _attachment[ii].numLayers) <= numLayers
, "Invalid texture layer range (layer %d + num %d > total %d)."
, _attachment[ii].layer
, _attachment[ii].numLayers
BGFX_ERROR_CHECK(
(at.layer + at.numLayers) <= numLayers
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Invalid texture layer range."
, "Attachment %d, Layer: %d, Num: %d, Max number of layers: %d."
, ii
, at.layer
, at.numLayers
, numLayers
);
}
BX_ASSERT(_attachment[0].numLayers == _attachment[ii].numLayers
, "Mismatch in attachment layer count (%d != %d)."
, _attachment[ii].numLayers
BGFX_ERROR_CHECK(
_attachment[0].numLayers == at.numLayers
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Mismatch in attachment layer count."
, "Attachment %d, Given: %d, Expected: %d."
, ii
, at.numLayers
, _attachment[0].numLayers
);
BX_ASSERT(firstTexture.m_bbRatio == tr.m_bbRatio
BGFX_ERROR_CHECK(
firstTexture.m_bbRatio == tr.m_bbRatio
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Mismatch in texture back-buffer ratio."
, "Attachment %d, Given: %d, Expected: %d."
, ii
, tr.m_bbRatio
, firstTexture.m_bbRatio
);
BX_ASSERT(firstTexture.m_numSamples == tr.m_numSamples
, "Mismatch in texture sample count (%d != %d)."
BGFX_ERROR_CHECK(
firstTexture.m_numSamples == tr.m_numSamples
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Mismatch in texture sample count."
, "Attachment %d, Given: %d, Expected: %d."
, ii
, tr.m_numSamples
, firstTexture.m_numSamples
);
if (BackbufferRatio::Count == firstTexture.m_bbRatio)
{
const uint16_t width = bx::max<uint16_t>(tr.m_width >> _attachment[ii].mip, 1);
const uint16_t height = bx::max<uint16_t>(tr.m_height >> _attachment[ii].mip, 1);
BX_UNUSED(width, height);
const uint16_t width = bx::max<uint16_t>(tr.m_width >> at.mip, 1);
const uint16_t height = bx::max<uint16_t>(tr.m_height >> at.mip, 1);
BX_ASSERT(width == firstAttachmentWidth && height == firstAttachmentHeight
, "Mismatch in texture size (%dx%d != %dx%d)."
BGFX_ERROR_CHECK(true
&& width == firstAttachmentWidth
&& height == firstAttachmentHeight
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Mismatch in texture size."
, "Attachment %d, Given: %dx%d, Expected: %dx%d."
, ii
, width
, height
, firstAttachmentWidth, firstAttachmentHeight
, firstAttachmentWidth
, firstAttachmentHeight
);
}
@ -4403,70 +4464,98 @@ namespace bgfx
++color;
}
BX_ASSERT(0 == (tr.m_flags & BGFX_TEXTURE_READ_BACK)
, "Frame buffer texture cannot be read back texture. Attachment %d: has flags 0x%016" PRIx64 "."
BGFX_ERROR_CHECK(
0 == (tr.m_flags & BGFX_TEXTURE_READ_BACK)
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Frame buffer texture cannot be created with `BGFX_TEXTURE_READ_BACK`."
, "Attachment %d, texture flags 0x%016" PRIx64 "."
, ii
, tr.m_flags
);
BX_ASSERT(0 != (tr.m_flags & BGFX_TEXTURE_RT_MASK)
, "Frame buffer texture is not created with one of `BGFX_TEXTURE_RT*` flags. Attachment %d: has flags 0x%016" PRIx64 "."
BGFX_ERROR_CHECK(
0 != (tr.m_flags & BGFX_TEXTURE_RT_MASK)
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Frame buffer texture is not created with one of `BGFX_TEXTURE_RT*` flags."
, "Attachment %d, texture flags 0x%016" PRIx64 "."
, ii
, tr.m_flags
);
}
BX_ASSERT(true
&& color <= g_caps.limits.maxFBAttachments
&& depth <= 1
, "Too many frame buffer attachments (num attachments: %d, max color attachments %d)!"
BGFX_ERROR_CHECK(
color <= g_caps.limits.maxFBAttachments
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "Too many frame buffer color attachments."
, "Num: %d, Max: %d."
, _num
, g_caps.limits.maxFBAttachments
);
BGFX_ERROR_CHECK(
depth <= 1
, _err
, BGFX_ERROR_FRAME_BUFFER_VALIDATION
, "There can be only one depth texture attachment."
, "Num depth attachments %d."
, depth
);
}
bool isFrameBufferValid(uint8_t _num, const Attachment* _attachment)
{
BGFX_MUTEX_SCOPE(s_ctx->m_resourceApiLock);
bx::Error err;
isFrameBufferValid(_num, _attachment, &err);
return err.isOk();
}
static void isTextureValid(uint16_t _depth, bool _cubeMap, uint16_t _numLayers, TextureFormat::Enum _format, uint64_t _flags, bx::Error* _err)
{
BX_ERROR_SCOPE(_err);
BX_ERROR_SCOPE(_err, "Texture validation");
const bool is3DTexture = 1 < _depth;
if (_cubeMap && is3DTexture)
{
_err->setError(BGFX_ERROR_TEXTURE_VALIDATION
, "Texture can't be depth and cube map at the same time."
BGFX_ERROR_CHECK(false
|| !_cubeMap
|| !is3DTexture
, _err
, BGFX_ERROR_TEXTURE_VALIDATION
, "Texture can't be 3D and cube map at the same time."
, ""
);
return;
}
if (is3DTexture
&& 0 == (g_caps.supported & BGFX_CAPS_TEXTURE_3D) )
{
_err->setError(BGFX_ERROR_TEXTURE_VALIDATION
BGFX_ERROR_CHECK(false
|| is3DTexture
|| 0 != (g_caps.supported & BGFX_CAPS_TEXTURE_3D)
, _err
, BGFX_ERROR_TEXTURE_VALIDATION
, "Texture3D is not supported! "
"Use bgfx::getCaps to check BGFX_CAPS_TEXTURE_3D backend renderer capabilities."
"Use bgfx::getCaps to check `BGFX_CAPS_TEXTURE_3D` backend renderer capabilities."
, ""
);
return;
}
if (0 != (_flags & BGFX_TEXTURE_RT_MASK)
&& 0 != (_flags & BGFX_TEXTURE_READ_BACK) )
{
_err->setError(BGFX_ERROR_TEXTURE_VALIDATION
, "Can't create render target with BGFX_TEXTURE_READ_BACK flag."
BGFX_ERROR_CHECK(false
|| 0 == (_flags & BGFX_TEXTURE_RT_MASK)
|| 0 == (_flags & BGFX_TEXTURE_READ_BACK)
, _err
, BGFX_ERROR_TEXTURE_VALIDATION
, "Can't create render target with `BGFX_TEXTURE_READ_BACK` flag."
, ""
);
return;
}
if (1 < _numLayers
&& 0 == (g_caps.supported & BGFX_CAPS_TEXTURE_2D_ARRAY) )
{
_err->setError(BGFX_ERROR_TEXTURE_VALIDATION
BGFX_ERROR_CHECK(false
|| 1 >= _numLayers
|| 0 != (g_caps.supported & BGFX_CAPS_TEXTURE_2D_ARRAY)
, _err
, BGFX_ERROR_TEXTURE_VALIDATION
, "Texture array is not supported! "
"Use bgfx::getCaps to check BGFX_CAPS_TEXTURE_2D_ARRAY backend renderer capabilities."
"Use bgfx::getCaps to check `BGFX_CAPS_TEXTURE_2D_ARRAY` backend renderer capabilities."
, ""
);
return;
}
bool formatSupported;
if (0 != (_flags & (BGFX_TEXTURE_RT | BGFX_TEXTURE_RT_WRITE_ONLY)) )
@ -4511,36 +4600,36 @@ namespace bgfx
) );
}
if (!formatSupported)
{
_err->setError(BGFX_ERROR_TEXTURE_VALIDATION
BGFX_ERROR_CHECK(
formatSupported
, _err
, BGFX_ERROR_TEXTURE_VALIDATION
, "Texture format is not supported! "
"Use bgfx::isTextureValid to check support for texture format before creating it."
, ""
);
return;
}
if (0 != (_flags & BGFX_TEXTURE_MSAA_SAMPLE)
&& 0 == (g_caps.formats[_format] & BGFX_CAPS_FORMAT_TEXTURE_MSAA) )
{
_err->setError(BGFX_ERROR_TEXTURE_VALIDATION
BGFX_ERROR_CHECK(false
|| 0 == (_flags & BGFX_TEXTURE_MSAA_SAMPLE)
|| 0 != (g_caps.formats[_format] & BGFX_CAPS_FORMAT_TEXTURE_MSAA)
, _err
, BGFX_ERROR_TEXTURE_VALIDATION
, "MSAA sampling for this texture format is not supported."
, ""
);
return;
}
if (0 != (_flags & BGFX_TEXTURE_SRGB)
&& 0 == (g_caps.formats[_format] & srgbCaps & (0
BGFX_ERROR_CHECK(false
|| 0 == (_flags & BGFX_TEXTURE_SRGB)
|| 0 != (g_caps.formats[_format] & srgbCaps & (0
| BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB
| BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB
| BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB
) ) )
{
_err->setError(BGFX_ERROR_TEXTURE_VALIDATION
) )
, _err
, BGFX_ERROR_TEXTURE_VALIDATION
, "sRGB sampling for this texture format is not supported."
, ""
);
return;
}
}
bool isTextureValid(uint16_t _depth, bool _cubeMap, uint16_t _numLayers, TextureFormat::Enum _format, uint64_t _flags)

View File

@ -433,6 +433,11 @@ BGFX_C_API bool bgfx_is_texture_valid(uint16_t _depth, bool _cubeMap, uint16_t _
return bgfx::isTextureValid(_depth, _cubeMap, _numLayers, (bgfx::TextureFormat::Enum)_format, _flags);
}
BGFX_C_API bool bgfx_is_frame_buffer_valid(uint8_t _num, const bgfx_attachment_t* _attachment)
{
return bgfx::isFrameBufferValid(_num, (const bgfx::Attachment*)_attachment);
}
BGFX_C_API void bgfx_calc_texture_size(bgfx_texture_info_t * _info, uint16_t _width, uint16_t _height, uint16_t _depth, bool _cubeMap, bool _hasMips, uint16_t _numLayers, bgfx_texture_format_t _format)
{
bgfx::TextureInfo & info = *(bgfx::TextureInfo *)_info;
@ -1316,6 +1321,7 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version)
bgfx_create_compute_program,
bgfx_destroy_program,
bgfx_is_texture_valid,
bgfx_is_frame_buffer_valid,
bgfx_calc_texture_size,
bgfx_create_texture,
bgfx_create_texture_2d,

View File

@ -73,7 +73,6 @@ namespace bgfx
#endif // BX_COMPILER_CLANG_ANALYZER
void trace(const char* _filePath, uint16_t _line, const char* _format, ...);
void checkFrameBuffer(uint8_t _num, const Attachment* _attachment);
inline bool operator==(const VertexLayoutHandle& _lhs, const VertexLayoutHandle& _rhs) { return _lhs.idx == _rhs.idx; }
inline bool operator==(const UniformHandle& _lhs, const UniformHandle& _rhs) { return _lhs.idx == _rhs.idx; }
@ -114,6 +113,7 @@ namespace bgfx
#include <bx/cpu.h>
#include <bx/debug.h>
#include <bx/endian.h>
#include <bx/error.h>
#include <bx/float4x4_t.h>
#include <bx/handlealloc.h>
#include <bx/hash.h>
@ -279,6 +279,7 @@ namespace bgfx
extern InternalData g_internalData;
extern PlatformData g_platformData;
extern bool g_platformDataChangedSinceReset;
extern void isFrameBufferValid(uint8_t _num, const Attachment* _attachment, bx::Error* _err);
#if BGFX_CONFIG_MAX_DRAW_CALLS < (64<<10)
typedef uint16_t RenderItemCount;
@ -4534,7 +4535,13 @@ namespace bgfx
{
BGFX_MUTEX_SCOPE(m_resourceApiLock);
checkFrameBuffer(_num, _attachment);
bx::Error err;
isFrameBufferValid(_num, _attachment, &err);
if (!err.isOk() )
{
return BGFX_INVALID_HANDLE;
}
FrameBufferHandle handle = { m_frameBufferHandle.alloc() };
BX_WARN(isValid(handle), "Failed to allocate frame buffer handle.");