Refresh/include/Refresh.h

2144 lines
66 KiB
C

/* Refresh - a cross-platform hardware-accelerated graphics library with modern capabilities
*
* Copyright (c) 2020-2024 Evan Hemsley
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
* Evan "cosmonaut" Hemsley <evan@moonside.games>
*
*/
#ifndef REFRESH_H
#define REFRESH_H
#include "SDL.h"
#include <SDL_stdinc.h>
#ifdef _WIN32
#define REFRESHAPI __declspec(dllexport)
#define REFRESHCALL __cdecl
#else
#define REFRESHAPI
#define REFRESHCALL
#endif
/* -Wpedantic nameless union/struct silencing */
#ifndef REFRESHNAMELESS
#ifdef __GNUC__
#define REFRESHNAMELESS __extension__
#else
#define REFRESHNAMELESS
#endif /* __GNUC__ */
#endif /* REFRESHNAMELESS */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Type Declarations */
typedef struct Refresh_Device Refresh_Device;
typedef struct Refresh_Buffer Refresh_Buffer;
typedef struct Refresh_TransferBuffer Refresh_TransferBuffer;
typedef struct Refresh_Texture Refresh_Texture;
typedef struct Refresh_Sampler Refresh_Sampler;
typedef struct Refresh_Shader Refresh_Shader;
typedef struct Refresh_ComputePipeline Refresh_ComputePipeline;
typedef struct Refresh_GraphicsPipeline Refresh_GraphicsPipeline;
typedef struct Refresh_CommandBuffer Refresh_CommandBuffer;
typedef struct Refresh_RenderPass Refresh_RenderPass;
typedef struct Refresh_ComputePass Refresh_ComputePass;
typedef struct Refresh_CopyPass Refresh_CopyPass;
typedef struct Refresh_Fence Refresh_Fence;
typedef struct Refresh_OcclusionQuery Refresh_OcclusionQuery;
typedef enum Refresh_PrimitiveType
{
REFRESH_PRIMITIVETYPE_POINTLIST,
REFRESH_PRIMITIVETYPE_LINELIST,
REFRESH_PRIMITIVETYPE_LINESTRIP,
REFRESH_PRIMITIVETYPE_TRIANGLELIST,
REFRESH_PRIMITIVETYPE_TRIANGLESTRIP
} Refresh_PrimitiveType;
typedef enum Refresh_LoadOp
{
REFRESH_LOADOP_LOAD,
REFRESH_LOADOP_CLEAR,
REFRESH_LOADOP_DONT_CARE
} Refresh_LoadOp;
typedef enum Refresh_StoreOp
{
REFRESH_STOREOP_STORE,
REFRESH_STOREOP_DONT_CARE
} Refresh_StoreOp;
typedef enum Refresh_IndexElementSize
{
REFRESH_INDEXELEMENTSIZE_16BIT,
REFRESH_INDEXELEMENTSIZE_32BIT
} Refresh_IndexElementSize;
typedef enum Refresh_TextureFormat
{
/* Unsigned Normalized Float Color Formats */
REFRESH_TEXTUREFORMAT_R8G8B8A8,
REFRESH_TEXTUREFORMAT_B8G8R8A8,
REFRESH_TEXTUREFORMAT_R5G6B5,
REFRESH_TEXTUREFORMAT_A1R5G5B5,
REFRESH_TEXTUREFORMAT_B4G4R4A4,
REFRESH_TEXTUREFORMAT_A2R10G10B10,
REFRESH_TEXTUREFORMAT_A2B10G10R10,
REFRESH_TEXTUREFORMAT_R16G16,
REFRESH_TEXTUREFORMAT_R16G16B16A16,
REFRESH_TEXTUREFORMAT_R8,
REFRESH_TEXTUREFORMAT_A8,
/* Compressed Unsigned Normalized Float Color Formats */
REFRESH_TEXTUREFORMAT_BC1,
REFRESH_TEXTUREFORMAT_BC2,
REFRESH_TEXTUREFORMAT_BC3,
REFRESH_TEXTUREFORMAT_BC7,
/* Signed Normalized Float Color Formats */
REFRESH_TEXTUREFORMAT_R8G8_SNORM,
REFRESH_TEXTUREFORMAT_R8G8B8A8_SNORM,
/* Signed Float Color Formats */
REFRESH_TEXTUREFORMAT_R16_SFLOAT,
REFRESH_TEXTUREFORMAT_R16G16_SFLOAT,
REFRESH_TEXTUREFORMAT_R16G16B16A16_SFLOAT,
REFRESH_TEXTUREFORMAT_R32_SFLOAT,
REFRESH_TEXTUREFORMAT_R32G32_SFLOAT,
REFRESH_TEXTUREFORMAT_R32G32B32A32_SFLOAT,
/* Unsigned Integer Color Formats */
REFRESH_TEXTUREFORMAT_R8_UINT,
REFRESH_TEXTUREFORMAT_R8G8_UINT,
REFRESH_TEXTUREFORMAT_R8G8B8A8_UINT,
REFRESH_TEXTUREFORMAT_R16_UINT,
REFRESH_TEXTUREFORMAT_R16G16_UINT,
REFRESH_TEXTUREFORMAT_R16G16B16A16_UINT,
/* SRGB Color Formats */
REFRESH_TEXTUREFORMAT_R8G8B8A8_SRGB,
REFRESH_TEXTUREFORMAT_B8G8R8A8_SRGB,
/* Compressed SRGB Color Formats */
REFRESH_TEXTUREFORMAT_BC3_SRGB,
REFRESH_TEXTUREFORMAT_BC7_SRGB,
/* Depth Formats */
REFRESH_TEXTUREFORMAT_D16_UNORM,
REFRESH_TEXTUREFORMAT_D24_UNORM,
REFRESH_TEXTUREFORMAT_D32_SFLOAT,
REFRESH_TEXTUREFORMAT_D24_UNORM_S8_UINT,
REFRESH_TEXTUREFORMAT_D32_SFLOAT_S8_UINT
} Refresh_TextureFormat;
typedef enum Refresh_TextureUsageFlagBits
{
REFRESH_TEXTUREUSAGE_SAMPLER_BIT = 0x00000001,
REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT = 0x00000002,
REFRESH_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT = 0x00000004,
REFRESH_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT = 0x00000008,
REFRESH_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT = 0x00000020,
REFRESH_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT = 0x00000040
} Refresh_TextureUsageFlagBits;
typedef Uint32 Refresh_TextureUsageFlags;
typedef enum Refresh_TextureType
{
REFRESH_TEXTURETYPE_2D,
REFRESH_TEXTURETYPE_3D,
REFRESH_TEXTURETYPE_CUBE,
} Refresh_TextureType;
typedef enum Refresh_SampleCount
{
REFRESH_SAMPLECOUNT_1,
REFRESH_SAMPLECOUNT_2,
REFRESH_SAMPLECOUNT_4,
REFRESH_SAMPLECOUNT_8
} Refresh_SampleCount;
typedef enum Refresh_CubeMapFace
{
REFRESH_CUBEMAPFACE_POSITIVEX,
REFRESH_CUBEMAPFACE_NEGATIVEX,
REFRESH_CUBEMAPFACE_POSITIVEY,
REFRESH_CUBEMAPFACE_NEGATIVEY,
REFRESH_CUBEMAPFACE_POSITIVEZ,
REFRESH_CUBEMAPFACE_NEGATIVEZ
} Refresh_CubeMapFace;
typedef enum Refresh_BufferUsageFlagBits
{
REFRESH_BUFFERUSAGE_VERTEX_BIT = 0x00000001,
REFRESH_BUFFERUSAGE_INDEX_BIT = 0x00000002,
REFRESH_BUFFERUSAGE_INDIRECT_BIT = 0x00000004,
REFRESH_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT = 0x00000008,
REFRESH_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT = 0x00000020,
REFRESH_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT = 0x00000040
} Refresh_BufferUsageFlagBits;
typedef Uint32 Refresh_BufferUsageFlags;
typedef enum Refresh_TransferBufferMapFlagBits
{
REFRESH_TRANSFER_MAP_READ = 0x00000001,
REFRESH_TRANSFER_MAP_WRITE = 0x00000002
} Refresh_TransferBufferMapFlagBits;
typedef Uint32 Refresh_TransferBufferMapFlags;
typedef enum Refresh_ShaderStage
{
REFRESH_SHADERSTAGE_VERTEX,
REFRESH_SHADERSTAGE_FRAGMENT,
REFRESH_SHADERSTAGE_COMPUTE
} Refresh_ShaderStage;
typedef enum Refresh_ShaderFormat
{
REFRESH_SHADERFORMAT_INVALID,
REFRESH_SHADERFORMAT_SPIRV, /* Vulkan */
REFRESH_SHADERFORMAT_DXBC, /* D3D11, D3D12 */
REFRESH_SHADERFORMAT_DXIL, /* D3D12 */
REFRESH_SHADERFORMAT_MSL, /* Metal */
REFRESH_SHADERFORMAT_METALLIB, /* Metal */
REFRESH_SHADERFORMAT_SECRET /* NDA'd platforms */
} Refresh_ShaderFormat;
typedef enum Refresh_VertexElementFormat
{
REFRESH_VERTEXELEMENTFORMAT_UINT,
REFRESH_VERTEXELEMENTFORMAT_FLOAT,
REFRESH_VERTEXELEMENTFORMAT_VECTOR2,
REFRESH_VERTEXELEMENTFORMAT_VECTOR3,
REFRESH_VERTEXELEMENTFORMAT_VECTOR4,
REFRESH_VERTEXELEMENTFORMAT_COLOR,
REFRESH_VERTEXELEMENTFORMAT_BYTE4,
REFRESH_VERTEXELEMENTFORMAT_SHORT2,
REFRESH_VERTEXELEMENTFORMAT_SHORT4,
REFRESH_VERTEXELEMENTFORMAT_NORMALIZEDSHORT2,
REFRESH_VERTEXELEMENTFORMAT_NORMALIZEDSHORT4,
REFRESH_VERTEXELEMENTFORMAT_HALFVECTOR2,
REFRESH_VERTEXELEMENTFORMAT_HALFVECTOR4
} Refresh_VertexElementFormat;
typedef enum Refresh_VertexInputRate
{
REFRESH_VERTEXINPUTRATE_VERTEX = 0,
REFRESH_VERTEXINPUTRATE_INSTANCE = 1
} Refresh_VertexInputRate;
typedef enum Refresh_FillMode
{
REFRESH_FILLMODE_FILL,
REFRESH_FILLMODE_LINE
} Refresh_FillMode;
typedef enum Refresh_CullMode
{
REFRESH_CULLMODE_NONE,
REFRESH_CULLMODE_FRONT,
REFRESH_CULLMODE_BACK
} Refresh_CullMode;
typedef enum Refresh_FrontFace
{
REFRESH_FRONTFACE_COUNTER_CLOCKWISE,
REFRESH_FRONTFACE_CLOCKWISE
} Refresh_FrontFace;
typedef enum Refresh_CompareOp
{
REFRESH_COMPAREOP_NEVER,
REFRESH_COMPAREOP_LESS,
REFRESH_COMPAREOP_EQUAL,
REFRESH_COMPAREOP_LESS_OR_EQUAL,
REFRESH_COMPAREOP_GREATER,
REFRESH_COMPAREOP_NOT_EQUAL,
REFRESH_COMPAREOP_GREATER_OR_EQUAL,
REFRESH_COMPAREOP_ALWAYS
} Refresh_CompareOp;
typedef enum Refresh_StencilOp
{
REFRESH_STENCILOP_KEEP,
REFRESH_STENCILOP_ZERO,
REFRESH_STENCILOP_REPLACE,
REFRESH_STENCILOP_INCREMENT_AND_CLAMP,
REFRESH_STENCILOP_DECREMENT_AND_CLAMP,
REFRESH_STENCILOP_INVERT,
REFRESH_STENCILOP_INCREMENT_AND_WRAP,
REFRESH_STENCILOP_DECREMENT_AND_WRAP
} Refresh_StencilOp;
typedef enum Refresh_BlendOp
{
REFRESH_BLENDOP_ADD,
REFRESH_BLENDOP_SUBTRACT,
REFRESH_BLENDOP_REVERSE_SUBTRACT,
REFRESH_BLENDOP_MIN,
REFRESH_BLENDOP_MAX
} Refresh_BlendOp;
typedef enum Refresh_BlendFactor
{
REFRESH_BLENDFACTOR_ZERO,
REFRESH_BLENDFACTOR_ONE,
REFRESH_BLENDFACTOR_SRC_COLOR,
REFRESH_BLENDFACTOR_ONE_MINUS_SRC_COLOR,
REFRESH_BLENDFACTOR_DST_COLOR,
REFRESH_BLENDFACTOR_ONE_MINUS_DST_COLOR,
REFRESH_BLENDFACTOR_SRC_ALPHA,
REFRESH_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
REFRESH_BLENDFACTOR_DST_ALPHA,
REFRESH_BLENDFACTOR_ONE_MINUS_DST_ALPHA,
REFRESH_BLENDFACTOR_CONSTANT_COLOR,
REFRESH_BLENDFACTOR_ONE_MINUS_CONSTANT_COLOR,
REFRESH_BLENDFACTOR_SRC_ALPHA_SATURATE
} Refresh_BlendFactor;
typedef enum Refresh_ColorComponentFlagBits
{
REFRESH_COLORCOMPONENT_R_BIT = 0x00000001,
REFRESH_COLORCOMPONENT_G_BIT = 0x00000002,
REFRESH_COLORCOMPONENT_B_BIT = 0x00000004,
REFRESH_COLORCOMPONENT_A_BIT = 0x00000008
} Refresh_ColorComponentFlagBits;
typedef Uint32 Refresh_ColorComponentFlags;
typedef enum Refresh_Filter
{
REFRESH_FILTER_NEAREST,
REFRESH_FILTER_LINEAR
} Refresh_Filter;
typedef enum Refresh_SamplerMipmapMode
{
REFRESH_SAMPLERMIPMAPMODE_NEAREST,
REFRESH_SAMPLERMIPMAPMODE_LINEAR
} Refresh_SamplerMipmapMode;
typedef enum Refresh_SamplerAddressMode
{
REFRESH_SAMPLERADDRESSMODE_REPEAT,
REFRESH_SAMPLERADDRESSMODE_MIRRORED_REPEAT,
REFRESH_SAMPLERADDRESSMODE_CLAMP_TO_EDGE,
REFRESH_SAMPLERADDRESSMODE_CLAMP_TO_BORDER
} Refresh_SamplerAddressMode;
/* FIXME: we should probably make a library-level decision about color types */
typedef enum Refresh_BorderColor
{
REFRESH_BORDERCOLOR_FLOAT_TRANSPARENT_BLACK,
REFRESH_BORDERCOLOR_INT_TRANSPARENT_BLACK,
REFRESH_BORDERCOLOR_FLOAT_OPAQUE_BLACK,
REFRESH_BORDERCOLOR_INT_OPAQUE_BLACK,
REFRESH_BORDERCOLOR_FLOAT_OPAQUE_WHITE,
REFRESH_BORDERCOLOR_INT_OPAQUE_WHITE
} Refresh_BorderColor;
typedef enum Refresh_TransferUsage
{
REFRESH_TRANSFERUSAGE_BUFFER,
REFRESH_TRANSFERUSAGE_TEXTURE
} Refresh_TransferUsage;
/*
* VSYNC:
* Waits for vblank before presenting.
* If there is a pending image to present, the new image is enqueued for presentation.
* Disallows tearing at the cost of visual latency.
* When using this present mode, AcquireSwapchainTexture will block if too many frames are in flight.
* IMMEDIATE:
* Immediately presents.
* Lowest latency option, but tearing may occur.
* When using this mode, AcquireSwapchainTexture will return NULL if too many frames are in flight.
* MAILBOX:
* Waits for vblank before presenting. No tearing is possible.
* If there is a pending image to present, the pending image is replaced by the new image.
* Similar to VSYNC, but with reduced visual latency.
* When using this mode, AcquireSwapchainTexture will return NULL if too many frames are in flight.
*/
typedef enum Refresh_PresentMode
{
REFRESH_PRESENTMODE_VSYNC,
REFRESH_PRESENTMODE_IMMEDIATE,
REFRESH_PRESENTMODE_MAILBOX
} Refresh_PresentMode;
/*
* SDR:
* B8G8R8A8 or R8G8B8A8 swapchain. Pixel values are in nonlinear sRGB encoding. Blends raw pixel values.
* SDR_LINEAR:
* B8G8R8A8_SRGB or R8G8B8A8_SRGB swapchain. Pixel values are in nonlinear sRGB encoding. Blends in linear space.
* HDR_EXTENDED_LINEAR:
* R16G16B16A16_SFLOAT swapchain. Pixel values are in extended linear encoding. Blends in linear space.
* HDR10_ST2048:
* A2R10G10B10 or A2B10G10R10 swapchain. Pixel values are in PQ ST2048 encoding. Blends raw pixel values. (TODO: verify this)
*/
typedef enum Refresh_SwapchainComposition
{
REFRESH_SWAPCHAINCOMPOSITION_SDR,
REFRESH_SWAPCHAINCOMPOSITION_SDR_LINEAR,
REFRESH_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR,
REFRESH_SWAPCHAINCOMPOSITION_HDR10_ST2048
} Refresh_SwapchainComposition;
typedef enum Refresh_BackendBits
{
REFRESH_BACKEND_INVALID = 0,
REFRESH_BACKEND_VULKAN = 0x0000000000000001,
REFRESH_BACKEND_D3D11 = 0x0000000000000002,
REFRESH_BACKEND_METAL = 0x0000000000000004,
REFRESH_BACKEND_ALL = (REFRESH_BACKEND_VULKAN | REFRESH_BACKEND_D3D11 | REFRESH_BACKEND_METAL)
} Refresh_BackendBits;
typedef Uint64 Refresh_Backend;
/* Structures */
typedef struct Refresh_DepthStencilValue
{
float depth;
Uint32 stencil;
} Refresh_DepthStencilValue;
typedef struct Refresh_Rect
{
Sint32 x;
Sint32 y;
Sint32 w;
Sint32 h;
} Refresh_Rect;
typedef struct Refresh_Color
{
float r;
float g;
float b;
float a;
} Refresh_Color;
typedef struct Refresh_Viewport
{
float x;
float y;
float w;
float h;
float minDepth;
float maxDepth;
} Refresh_Viewport;
typedef struct Refresh_TextureSlice
{
Refresh_Texture *texture;
Uint32 mipLevel;
Uint32 layer;
} Refresh_TextureSlice;
typedef struct Refresh_TextureRegion
{
Refresh_TextureSlice textureSlice;
Uint32 x;
Uint32 y;
Uint32 z;
Uint32 w;
Uint32 h;
Uint32 d;
} Refresh_TextureRegion;
typedef struct Refresh_BufferImageCopy
{
Uint32 bufferOffset;
Uint32 bufferStride; /* number of pixels from one row to the next */
Uint32 bufferImageHeight; /* number of rows from one layer/depth-slice to the next */
} Refresh_BufferImageCopy;
typedef struct Refresh_BufferCopy
{
Uint32 srcOffset;
Uint32 dstOffset;
Uint32 size;
} Refresh_BufferCopy;
typedef struct Refresh_IndirectDrawCommand
{
Uint32 vertexCount; /* number of vertices to draw */
Uint32 instanceCount; /* number of instances to draw */
Uint32 firstVertex; /* index of the first vertex to draw */
Uint32 firstInstance; /* ID of the first instance to draw */
} Refresh_IndirectDrawCommand;
typedef struct Refresh_IndexedIndirectDrawCommand
{
Uint32 indexCount; /* number of vertices to draw */
Uint32 instanceCount; /* number of instances to draw */
Uint32 firstIndex; /* base index within the index buffer */
Uint32 vertexOffset; /* value added to vertex index before indexing into the vertex buffer */
Uint32 firstInstance; /* ID of the first instance to draw */
} Refresh_IndexedIndirectDrawCommand;
/* State structures */
typedef struct Refresh_SamplerCreateInfo
{
Refresh_Filter minFilter;
Refresh_Filter magFilter;
Refresh_SamplerMipmapMode mipmapMode;
Refresh_SamplerAddressMode addressModeU;
Refresh_SamplerAddressMode addressModeV;
Refresh_SamplerAddressMode addressModeW;
float mipLodBias;
SDL_bool anisotropyEnable;
float maxAnisotropy;
SDL_bool compareEnable;
Refresh_CompareOp compareOp;
float minLod;
float maxLod;
Refresh_BorderColor borderColor;
} Refresh_SamplerCreateInfo;
typedef struct Refresh_VertexBinding
{
Uint32 binding;
Uint32 stride;
Refresh_VertexInputRate inputRate;
Uint32 stepRate;
} Refresh_VertexBinding;
typedef struct Refresh_VertexAttribute
{
Uint32 location;
Uint32 binding;
Refresh_VertexElementFormat format;
Uint32 offset;
} Refresh_VertexAttribute;
typedef struct Refresh_VertexInputState
{
const Refresh_VertexBinding *vertexBindings;
Uint32 vertexBindingCount;
const Refresh_VertexAttribute *vertexAttributes;
Uint32 vertexAttributeCount;
} Refresh_VertexInputState;
typedef struct Refresh_StencilOpState
{
Refresh_StencilOp failOp;
Refresh_StencilOp passOp;
Refresh_StencilOp depthFailOp;
Refresh_CompareOp compareOp;
} Refresh_StencilOpState;
typedef struct Refresh_ColorAttachmentBlendState
{
SDL_bool blendEnable;
Refresh_BlendFactor srcColorBlendFactor;
Refresh_BlendFactor dstColorBlendFactor;
Refresh_BlendOp colorBlendOp;
Refresh_BlendFactor srcAlphaBlendFactor;
Refresh_BlendFactor dstAlphaBlendFactor;
Refresh_BlendOp alphaBlendOp;
Refresh_ColorComponentFlags colorWriteMask;
} Refresh_ColorAttachmentBlendState;
typedef struct Refresh_ShaderCreateInfo
{
size_t codeSize;
const Uint8 *code;
const char* entryPointName;
Refresh_ShaderStage stage;
Refresh_ShaderFormat format;
} Refresh_ShaderCreateInfo;
typedef struct Refresh_TextureCreateInfo
{
Uint32 width;
Uint32 height;
Uint32 depth;
SDL_bool isCube;
Uint32 layerCount;
Uint32 levelCount;
Refresh_SampleCount sampleCount;
Refresh_TextureFormat format;
Refresh_TextureUsageFlags usageFlags;
} Refresh_TextureCreateInfo;
/* Pipeline state structures */
typedef struct Refresh_RasterizerState
{
Refresh_FillMode fillMode;
Refresh_CullMode cullMode;
Refresh_FrontFace frontFace;
SDL_bool depthBiasEnable;
float depthBiasConstantFactor;
float depthBiasClamp;
float depthBiasSlopeFactor;
} Refresh_RasterizerState;
typedef struct Refresh_MultisampleState
{
Refresh_SampleCount multisampleCount;
Uint32 sampleMask;
} Refresh_MultisampleState;
typedef struct Refresh_DepthStencilState
{
SDL_bool depthTestEnable;
SDL_bool depthWriteEnable;
Refresh_CompareOp compareOp;
SDL_bool depthBoundsTestEnable;
SDL_bool stencilTestEnable;
Refresh_StencilOpState backStencilState;
Refresh_StencilOpState frontStencilState;
Uint32 compareMask;
Uint32 writeMask;
Uint32 reference;
float minDepthBounds;
float maxDepthBounds;
} Refresh_DepthStencilState;
typedef struct Refresh_ColorAttachmentDescription
{
Refresh_TextureFormat format;
Refresh_ColorAttachmentBlendState blendState;
} Refresh_ColorAttachmentDescription;
typedef struct Refresh_GraphicsPipelineAttachmentInfo
{
Refresh_ColorAttachmentDescription *colorAttachmentDescriptions;
Uint32 colorAttachmentCount;
SDL_bool hasDepthStencilAttachment;
Refresh_TextureFormat depthStencilFormat;
} Refresh_GraphicsPipelineAttachmentInfo;
typedef struct Refresh_GraphicsPipelineResourceInfo
{
Uint32 samplerCount;
Uint32 storageBufferCount;
Uint32 storageTextureCount;
Uint32 uniformBufferCount;
} Refresh_GraphicsPipelineResourceInfo;
typedef struct Refresh_GraphicsPipelineCreateInfo
{
Refresh_Shader *vertexShader;
Refresh_Shader *fragmentShader;
Refresh_VertexInputState vertexInputState;
Refresh_PrimitiveType primitiveType;
Refresh_RasterizerState rasterizerState;
Refresh_MultisampleState multisampleState;
Refresh_DepthStencilState depthStencilState;
Refresh_GraphicsPipelineAttachmentInfo attachmentInfo;
Refresh_GraphicsPipelineResourceInfo vertexResourceInfo;
Refresh_GraphicsPipelineResourceInfo fragmentResourceInfo;
float blendConstants[4];
} Refresh_GraphicsPipelineCreateInfo;
typedef struct Refresh_ComputePipelineResourceInfo
{
Uint32 readOnlyStorageTextureCount;
Uint32 readOnlyStorageBufferCount;
Uint32 readWriteStorageTextureCount;
Uint32 readWriteStorageBufferCount;
Uint32 uniformBufferCount;
} Refresh_ComputePipelineResourceInfo;
typedef struct Refresh_ComputePipelineCreateInfo
{
Refresh_Shader *computeShader;
Refresh_ComputePipelineResourceInfo pipelineResourceInfo;
} Refresh_ComputePipelineCreateInfo;
typedef struct Refresh_ColorAttachmentInfo
{
/* The texture slice that will be used as a color attachment by a render pass. */
Refresh_TextureSlice textureSlice;
/* Can be ignored by RenderPass if CLEAR is not used */
Refresh_Color clearColor;
/* Determines what is done with the texture slice at the beginning of the render pass.
*
* LOAD:
* Loads the data currently in the texture slice.
*
* CLEAR:
* Clears the texture slice to a single color.
*
* DONT_CARE:
* The driver will do whatever it wants with the texture slice memory.
* This is a good option if you know that every single pixel will be touched in the render pass.
*/
Refresh_LoadOp loadOp;
/* Determines what is done with the texture slice at the end of the render pass.
*
* STORE:
* Stores the results of the render pass in the texture slice.
*
* DONT_CARE:
* The driver will do whatever it wants with the texture slice memory.
* This is often a good option for depth/stencil textures.
*/
Refresh_StoreOp storeOp;
/* if SDL_TRUE, cycles the texture if the texture slice is bound and loadOp is not LOAD */
SDL_bool cycle;
} Refresh_ColorAttachmentInfo;
typedef struct Refresh_DepthStencilAttachmentInfo
{
/* The texture slice that will be used as the depth stencil attachment by a render pass. */
Refresh_TextureSlice textureSlice;
/* Can be ignored by the render pass if CLEAR is not used */
Refresh_DepthStencilValue depthStencilClearValue;
/* Determines what is done with the depth values at the beginning of the render pass.
*
* LOAD:
* Loads the depth values currently in the texture slice.
*
* CLEAR:
* Clears the texture slice to a single depth.
*
* DONT_CARE:
* The driver will do whatever it wants with the memory.
* This is a good option if you know that every single pixel will be touched in the render pass.
*/
Refresh_LoadOp loadOp;
/* Determines what is done with the depth values at the end of the render pass.
*
* STORE:
* Stores the depth results in the texture slice.
*
* DONT_CARE:
* The driver will do whatever it wants with the texture slice memory.
* This is often a good option for depth/stencil textures.
*/
Refresh_StoreOp storeOp;
/* Determines what is done with the stencil values at the beginning of the render pass.
*
* LOAD:
* Loads the stencil values currently in the texture slice.
*
* CLEAR:
* Clears the texture slice to a single stencil value.
*
* DONT_CARE:
* The driver will do whatever it wants with the memory.
* This is a good option if you know that every single pixel will be touched in the render pass.
*/
Refresh_LoadOp stencilLoadOp;
/* Determines what is done with the stencil values at the end of the render pass.
*
* STORE:
* Stores the stencil results in the texture slice.
*
* DONT_CARE:
* The driver will do whatever it wants with the texture slice memory.
* This is often a good option for depth/stencil textures.
*/
Refresh_StoreOp stencilStoreOp;
/* if SDL_TRUE, cycles the texture if the texture slice is bound and any load ops are not LOAD */
SDL_bool cycle;
} Refresh_DepthStencilAttachmentInfo;
/* Binding structs */
typedef struct Refresh_BufferBinding
{
Refresh_Buffer *buffer;
Uint32 offset;
} Refresh_BufferBinding;
typedef struct Refresh_TextureSamplerBinding
{
Refresh_Texture *texture;
Refresh_Sampler *sampler;
} Refresh_TextureSamplerBinding;
typedef struct Refresh_StorageBufferReadWriteBinding
{
Refresh_Buffer *buffer;
/* if SDL_TRUE, cycles the buffer if it is bound. */
SDL_bool cycle;
} Refresh_StorageBufferReadWriteBinding;
typedef struct Refresh_StorageTextureReadWriteBinding
{
Refresh_TextureSlice textureSlice;
/* if SDL_TRUE, cycles the texture if the texture slice is bound. */
SDL_bool cycle;
} Refresh_StorageTextureReadWriteBinding;
/* Functions */
/* Device */
/**
* Creates a GPU context.
*
* Backends will first be checked for availability in order of bitflags passed using preferredBackends. If none of the backends are available, the remaining backends are checked as fallback renderers.
*
* Think of "preferred" backends as those that have pre-built shaders readily available - for example, you would set the REFRESH_BACKEND_VULKAN bit if your game includes SPIR-V shaders. If you generate shaders at runtime (i.e. via SDL_shader) and the library does _not_ provide you with a preferredBackends value, you should pass REFRESH_BACKEND_ALL so that updated versions of SDL can be aware of which backends the application was aware of at compile time. REFRESH_BACKEND_INVALID is an accepted value but is not recommended.
*
* \param preferredBackends a bitflag containing the renderers most recognized by the application
* \param debugMode enable debug mode properties and validations
* \returns a GPU context on success or NULL on failure
*
* \sa Refresh_SelectBackend
* \sa Refresh_DestroyDevice
*/
REFRESHAPI Refresh_Device* Refresh_CreateDevice(
Refresh_Backend preferredBackends,
SDL_bool debugMode
);
/**
* Destroys a GPU context previously returned by Refresh_CreateDevice.
*
* \param device a GPU Context to destroy
*
* \sa Refresh_CreateDevice
*/
REFRESHAPI void Refresh_DestroyDevice(Refresh_Device *device);
/**
* Returns the backend used to create this GPU context.
*
* \param device a GPU context to query
* \returns an Refresh_Backend value, or REFRESH_BACKEND_INVALID on error
*
* \sa Refresh_SelectBackend
*/
REFRESHAPI Refresh_Backend Refresh_GetBackend(Refresh_Device *device);
/* State Creation */
/**
* Creates a pipeline object to be used in a compute workflow.
*
* \param device a GPU Context
* \param computePipelineCreateInfo a struct describing the state of the requested compute pipeline
* \returns a compute pipeline object on success, or NULL on failure
*
* \sa Refresh_CreateShader
* \sa Refresh_BindComputePipeline
* \sa Refresh_ReleaseComputePipeline
*/
REFRESHAPI Refresh_ComputePipeline* Refresh_CreateComputePipeline(
Refresh_Device *device,
Refresh_ComputePipelineCreateInfo *computePipelineCreateInfo
);
/**
* Creates a pipeline object to be used in a graphics workflow.
*
* \param device a GPU Context
* \param pipelineCreateInfo a struct describing the state of the desired graphics pipeline
* \returns a graphics pipeline object on success, or NULL on failure
*
* \sa Refresh_CreateShader
* \sa Refresh_BindGraphicsPipeline
* \sa Refresh_ReleaseGraphicsPipeline
*/
REFRESHAPI Refresh_GraphicsPipeline* Refresh_CreateGraphicsPipeline(
Refresh_Device *device,
Refresh_GraphicsPipelineCreateInfo *pipelineCreateInfo
);
/**
* Creates a sampler object to be used when binding textures in a graphics workflow.
*
* \param device a GPU Context
* \param samplerCreateInfo a struct describing the state of the desired sampler
* \returns a sampler object on success, or NULL on failure
*
* \sa Refresh_BindVertexSamplers
* \sa Refresh_BindFragmentSamplers
* \sa SDL_ReleaseSampler
*/
REFRESHAPI Refresh_Sampler* Refresh_CreateSampler(
Refresh_Device *device,
Refresh_SamplerCreateInfo *samplerCreateInfo
);
/**
* Creates a shader to be used when creating a graphics or compute pipeline.
*
* \param device a GPU Context
* \param shaderCreateInfo a struct describing the state of the desired shader
* \returns a shader object on success, or NULL on failure
*
* \sa Refresh_CreateGraphicsPipeline
* \sa Refresh_CreateComputePipeline
* \sa Refresh_ReleaseShader
*/
REFRESHAPI Refresh_Shader* Refresh_CreateShader(
Refresh_Device *device,
Refresh_ShaderCreateInfo *shaderCreateInfo
);
/**
* Creates a texture object to be used in graphics or compute workflows.
* The contents of this texture are undefined until data is written to the texture.
*
* Note that certain combinations of usage flags are invalid.
* For example, a texture cannot have both the SAMPLER and GRAPHICS_STORAGE_READ flags.
*
* \param device a GPU Context
* \param textureCreateInfo a struct describing the state of the texture to create
* \returns a texture object on success, or NULL on failure
*
* \sa Refresh_UploadToTexture
* \sa Refresh_DownloadFromTexture
* \sa Refresh_BindVertexSamplers
* \sa Refresh_BindVertexStorageTextures
* \sa Refresh_BindFragmentSamplers
* \sa Refresh_BindFragmentStorageTextures
* \sa Refresh_BindComputeStorageTextures
* \sa Refresh_Blit
* \sa Refresh_ReleaseTexture
*/
REFRESHAPI Refresh_Texture* Refresh_CreateTexture(
Refresh_Device *device,
Refresh_TextureCreateInfo *textureCreateInfo
);
/**
* Creates a buffer object to be used in graphics or compute workflows.
* The contents of this buffer are undefined until data is written to the buffer.
*
* Note that certain combinations of usage flags are invalid.
* For example, a buffer cannot have both the VERTEX and INDEX flags.
*
* \param device a GPU Context
* \param usageFlags bitflag mask hinting at how the buffer will be used
* \param sizeInBytes the size of the buffer
* \returns a buffer object on success, or NULL on failure
*
* \sa Refresh_UploadToBuffer
* \sa Refresh_BindVertexBuffers
* \sa Refresh_BindIndexBuffer
* \sa Refresh_BindVertexStorageBuffers
* \sa Refresh_BindFragmentStorageBuffers
* \sa Refresh_BindComputeStorageBuffers
* \sa Refresh_ReleaseBuffer
*/
REFRESHAPI Refresh_Buffer* Refresh_CreateBuffer(
Refresh_Device *device,
Refresh_BufferUsageFlags usageFlags,
Uint32 sizeInBytes
);
/**
* Creates a transfer buffer to be used when uploading to or downloading from graphics resources.
*
* \param device a GPU Context
* \param usage specifies whether the transfer buffer will transfer buffers or textures
* \param mapFlags specify read-write options for the transfer buffer
* \param sizeInBytes the size of the transfer buffer
* \returns a transfer buffer on success, or NULL on failure
*
* \sa Refresh_UploadToBuffer
* \sa Refresh_DownloadFromBuffer
* \sa Refresh_UploadToTexture
* \sa Refresh_DownloadFromTexture
* \sa Refresh_ReleaseTransferBuffer
*/
REFRESHAPI Refresh_TransferBuffer* Refresh_CreateTransferBuffer(
Refresh_Device *device,
Refresh_TransferUsage usage,
Refresh_TransferBufferMapFlags mapFlags,
Uint32 sizeInBytes
);
/**
* Creates an occlusion query object.
*
* This function is included for compatibility with old render systems.
* If you are not supporting an old application, do NOT use this.
*
* \param device a GPU context
* \returns an occlusion query object
*
* \sa Refresh_ReleaseQuery
*/
REFRESHAPI Refresh_OcclusionQuery* Refresh_CreateOcclusionQuery(
Refresh_Device *device
);
/* Debug Naming */
/**
* Sets an arbitrary string constant to label a buffer. Useful for debugging.
*
* \param device a GPU Context
* \param buffer a buffer to attach the name to
* \param text a UTF-8 string constant to mark as the name of the buffer
*/
REFRESHAPI void Refresh_SetBufferName(
Refresh_Device *device,
Refresh_Buffer *buffer,
const char *text
);
/**
* Sets an arbitrary string constant to label a texture. Useful for debugging.
*
* \param device a GPU Context
* \param texture a texture to attach the name to
* \param text a UTF-8 string constant to mark as the name of the texture
*/
REFRESHAPI void Refresh_SetTextureName(
Refresh_Device *device,
Refresh_Texture *texture,
const char *text
);
/**
* Sets an arbitrary string constant to label a section of a command buffer. Useful for debugging.
*
* \param commandBuffer a command buffer
* \param text a UTF-8 string constant to mark as the label
*/
REFRESHAPI void Refresh_SetStringMarker(
Refresh_CommandBuffer *commandBuffer,
const char *text
);
/* Disposal */
/**
* Frees the given texture as soon as it is safe to do so.
* You must not reference the texture after calling this function.
*
* \param device a GPU context
* \param texture a texture to be destroyed
*/
REFRESHAPI void Refresh_ReleaseTexture(
Refresh_Device *device,
Refresh_Texture *texture
);
/**
* Frees the given sampler as soon as it is safe to do so.
* You must not reference the texture after calling this function.
*
* \param device a GPU context
* \param sampler a sampler to be destroyed
*/
REFRESHAPI void Refresh_ReleaseSampler(
Refresh_Device *device,
Refresh_Sampler *sampler
);
/**
* Frees the given buffer as soon as it is safe to do so.
* You must not reference the buffer after calling this function.
*
* \param device a GPU context
* \param buffer a buffer to be destroyed
*/
REFRESHAPI void Refresh_ReleaseBuffer(
Refresh_Device *device,
Refresh_Buffer *buffer
);
/**
* Frees the given transfer buffer as soon as it is safe to do so.
* You must not reference the transfer buffer after calling this function.
*
* \param device a GPU context
* \param transferBuffer a transfer buffer to be destroyed
*/
REFRESHAPI void Refresh_ReleaseTransferBuffer(
Refresh_Device *device,
Refresh_TransferBuffer *transferBuffer
);
/**
* Frees the given shader as soon as it is safe to do so.
* You must not reference the shader after calling this function.
*
* \param device a GPU context
* \param shader a shader to be destroyed
*/
REFRESHAPI void Refresh_ReleaseShader(
Refresh_Device *device,
Refresh_Shader *shader
);
/**
* Frees the given compute pipeline as soon as it is safe to do so.
* You must not reference the compute pipeline after calling this function.
*
* \param device a GPU context
* \param computePipeline a compute pipeline to be destroyed
*/
REFRESHAPI void Refresh_ReleaseComputePipeline(
Refresh_Device *device,
Refresh_ComputePipeline *computePipeline
);
/**
* Frees the given graphics pipeline as soon as it is safe to do so.
* You must not reference the graphics pipeline after calling this function.
*
* \param device a GPU context
* \param graphicsPipeline a graphics pipeline to be destroyed
*/
REFRESHAPI void Refresh_ReleaseGraphicsPipeline(
Refresh_Device *device,
Refresh_GraphicsPipeline *graphicsPipeline
);
/**
* Frees the given occlusion query as soon as it is safe to do so.
* You must not reference the occlusion query after calling this function.
*
* \param device a GPU context
* \param query an occlusion query object to be destroyed
*/
REFRESHAPI void Refresh_ReleaseOcclusionQuery(
Refresh_Device *device,
Refresh_OcclusionQuery *query
);
/*
* A NOTE ON CYCLING
*
* When using a command buffer, operations do not occur immediately -
* they occur some time after the command buffer is submitted.
*
* When a resource is used in a pending or active command buffer, it is considered to be "bound".
* When a resource is no longer used in any pending or active command buffers, it is considered to be "unbound".
*
* If data resources are bound, it is unspecified when that data will be unbound
* unless you acquire a fence when submitting the command buffer and wait on it.
* However, this doesn't mean you need to track resource usage manually.
*
* All of the functions and structs that involve writing to a resource have a "cycle" bool.
* GpuTransferBuffer, GpuBuffer, and GpuTexture all effectively function as ring buffers on internal resources.
* When cycle is SDL_TRUE, if the resource is bound, the cycle rotates to the next unbound internal resource,
* or if none are available, a new one is created.
* This means you don't have to worry about complex state tracking and synchronization as long as cycling is correctly employed.
*
* For example: you can call SetTransferData and then UploadToTexture. The next time you call SetTransferData,
* if you set the cycle param to SDL_TRUE, you don't have to worry about overwriting any data that is not yet uploaded.
*
* Another example: If you are using a texture in a render pass every frame, this can cause a data dependency between frames.
* If you set cycle to SDL_TRUE in the ColorAttachmentInfo struct, you can prevent this data dependency.
*
* Note that all functions which write to a texture specifically write to a GpuTextureSlice,
* and these slices themselves are tracked for binding.
* The GpuTexture will only cycle if the specific GpuTextureSlice being written to is bound.
*
* Cycling will never undefine already bound data.
* When cycling, all data in the resource is considered to be undefined for subsequent commands until that data is written again.
* You must take care not to read undefined data.
*
* You must also take care not to overwrite a section of data that has been referenced in a command without cycling first.
* It is OK to overwrite unreferenced data in a bound resource without cycling,
* but overwriting a section of data that has already been referenced will produce unexpected results.
*/
/* Graphics State */
/**
* Begins a render pass on a command buffer.
* A render pass consists of a set of texture slices, clear values, and load/store operations
* which will be rendered to during the render pass.
* All operations related to graphics pipelines must take place inside of a render pass.
* A default viewport and scissor state are automatically set when this is called.
* You cannot begin another render pass, or begin a compute pass or copy pass
* until you have ended the render pass.
*
* \param commandBuffer a command buffer
* \param colorAttachmentInfos an array of Refresh_ColorAttachmentInfo structs
* \param colorAttachmentCount the number of color attachments in the colorAttachmentInfos array
* \param depthStencilAttachmentInfo the depth-stencil target and clear value, may be NULL
* \returns a render pass handle
*
* \sa Refresh_EndRenderPass
*/
REFRESHAPI Refresh_RenderPass* Refresh_BeginRenderPass(
Refresh_CommandBuffer *commandBuffer,
Refresh_ColorAttachmentInfo *colorAttachmentInfos,
Uint32 colorAttachmentCount,
Refresh_DepthStencilAttachmentInfo *depthStencilAttachmentInfo
);
/**
* Binds a graphics pipeline on a render pass to be used in rendering.
* A graphics pipeline must be bound before making any draw calls.
*
* \param renderPass a render pass handle
* \param graphicsPipeline the graphics pipeline to bind
*/
REFRESHAPI void Refresh_BindGraphicsPipeline(
Refresh_RenderPass *renderPass,
Refresh_GraphicsPipeline *graphicsPipeline
);
/**
* Sets the current viewport state on a command buffer.
*
* \param renderPass a render pass handle
* \param viewport the viewport to set
*/
REFRESHAPI void Refresh_SetViewport(
Refresh_RenderPass *renderPass,
Refresh_Viewport *viewport
);
/**
* Sets the current scissor state on a command buffer.
*
* \param renderPass a render pass handle
* \param scissor the scissor area to set
*/
REFRESHAPI void Refresh_SetScissor(
Refresh_RenderPass *renderPass,
Refresh_Rect *scissor
);
/**
* Binds vertex buffers on a command buffer for use with subsequent draw calls.
*
* \param renderPass a render pass handle
* \param firstBinding the starting bind point for the vertex buffers
* \param pBindings an array of Refresh_BufferBinding structs containing vertex buffers and offset values
* \param bindingCount the number of bindings in the pBindings array
*/
REFRESHAPI void Refresh_BindVertexBuffers(
Refresh_RenderPass *renderPass,
Uint32 firstBinding,
Refresh_BufferBinding *pBindings,
Uint32 bindingCount
);
/**
* Binds an index buffer on a command buffer for use with subsequent draw calls.
*
* \param renderPass a render pass handle
* \param pBinding a pointer to a struct containing an index buffer and offset
* \param indexElementSize whether the index values in the buffer are 16- or 32-bit
*/
REFRESHAPI void Refresh_BindIndexBuffer(
Refresh_RenderPass *renderPass,
Refresh_BufferBinding *pBinding,
Refresh_IndexElementSize indexElementSize
);
/**
* Binds texture-sampler pairs for use on the vertex shader.
* The textures must have been created with REFRESH_TEXTUREUSAGE_SAMPLER_BIT.
*
* \param renderPass a render pass handle
* \param firstSlot the vertex sampler slot to begin binding from
* \param textureSamplerBindings an array of texture-sampler binding structs
* \param bindingCount the number of texture-sampler pairs to bind from the array
*/
REFRESHAPI void Refresh_BindVertexSamplers(
Refresh_RenderPass *renderPass,
Uint32 firstSlot,
Refresh_TextureSamplerBinding *textureSamplerBindings,
Uint32 bindingCount
);
/**
* Binds storage textures for use on the vertex shader.
* These textures must have been created with REFRESH_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT.
*
* \param renderPass a render pass handle
* \param firstSlot the vertex storage texture slot to begin binding from
* \param storageTextureSlices an array of storage texture slices
* \param bindingCount the number of storage texture slices to bind from the array
*/
REFRESHAPI void Refresh_BindVertexStorageTextures(
Refresh_RenderPass *renderPass,
Uint32 firstSlot,
Refresh_TextureSlice *storageTextureSlices,
Uint32 bindingCount
);
/**
* Binds storage buffers for use on the vertex shader.
* These buffers must have been created with REFRESH_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT.
*
* \param renderPass a render pass handle
* \param firstSlot the vertex storage buffer slot to begin binding from
* \param storageBuffers an array of buffers
* \param bindingCount the number of buffers to bind from the array
*/
REFRESHAPI void Refresh_BindVertexStorageBuffers(
Refresh_RenderPass *renderPass,
Uint32 firstSlot,
Refresh_Buffer **storageBuffers,
Uint32 bindingCount
);
/**
* Binds texture-sampler pairs for use on the fragment shader.
* The textures must have been created with REFRESH_TEXTUREUSAGE_SAMPLER_BIT.
*
* \param renderPass a render pass handle
* \param firstSlot the fragment sampler slot to begin binding from
* \param textureSamplerBindings an array of texture-sampler binding structs
* \param bindingCount the number of texture-sampler pairs to bind from the array
*/
REFRESHAPI void Refresh_BindFragmentSamplers(
Refresh_RenderPass *renderPass,
Uint32 firstSlot,
Refresh_TextureSamplerBinding *textureSamplerBindings,
Uint32 bindingCount
);
/**
* Binds storage textures for use on the fragment shader.
* These textures must have been created with REFRESH_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT.
*
* \param renderPass a render pass handle
* \param firstSlot the fragment storage texture slot to begin binding from
* \param storageTextureSlices an array of storage texture slices
* \param bindingCount the number of storage texture slices to bind from the array
*/
REFRESHAPI void Refresh_BindFragmentStorageTextures(
Refresh_RenderPass *renderPass,
Uint32 firstSlot,
Refresh_TextureSlice *storageTextureSlices,
Uint32 bindingCount
);
/**
* Binds storage buffers for use on the fragment shader.
* These buffers must have been created with REFRESH_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT.
*
* \param renderPass a render pass handle
* \param firstSlot the fragment storage buffer slot to begin binding from
* \param storageBuffers an array of storage buffers
* \param bindingCount the number of storage buffers to bind from the array
*/
REFRESHAPI void Refresh_BindFragmentStorageBuffers(
Refresh_RenderPass *renderPass,
Uint32 firstSlot,
Refresh_Buffer **storageBuffers,
Uint32 bindingCount
);
/**
* Pushes data to a vertex uniform slot on the bound graphics pipeline.
* Subsequent draw calls will use this uniform data.
*
* \param renderPass a render pass handle
* \param slotIndex the vertex uniform slot to push data to
* \param data client data to write
* \param dataLengthInBytes the length of the data to write
*/
REFRESHAPI void Refresh_PushVertexUniformData(
Refresh_RenderPass *renderPass,
Uint32 slotIndex,
void *data,
Uint32 dataLengthInBytes
);
/**
* Pushes data to a fragment uniform slot on the bound graphics pipeline.
* Subsequent draw calls will use this uniform data.
*
* \param renderPass a render pass handle
* \param slotIndex the fragment uniform slot to push data to
* \param data client data to write
* \param dataLengthInBytes the length of the data to write
*/
REFRESHAPI void Refresh_PushFragmentUniformData(
Refresh_RenderPass *renderPass,
Uint32 slotIndex,
void *data,
Uint32 dataLengthInBytes
);
/* Drawing */
/**
* Draws data using bound graphics state with an index buffer and instancing enabled.
* You must not call this function before binding a graphics pipeline.
*
* \param renderPass a render pass handle
* \param baseVertex the starting offset to read from the vertex buffer
* \param startIndex the starting offset to read from the index buffer
* \param primitiveCount the number of primitives to draw
* \param instanceCount the number of instances that will be drawn
*/
REFRESHAPI void Refresh_DrawIndexedPrimitives(
Refresh_RenderPass *renderPass,
Uint32 baseVertex,
Uint32 startIndex,
Uint32 primitiveCount,
Uint32 instanceCount
);
/**
* Draws data using bound graphics state.
* You must not call this function before binding a graphics pipeline.
*
* \param renderPass a render pass handle
* \param vertexStart The starting offset to read from the vertex buffer
* \param primitiveCount The number of primitives to draw
*/
REFRESHAPI void Refresh_DrawPrimitives(
Refresh_RenderPass *renderPass,
Uint32 vertexStart,
Uint32 primitiveCount
);
/**
* Draws data using bound graphics state and with draw parameters set from a buffer.
* The buffer layout should match the layout of Refresh_IndirectDrawCommand.
* You must not call this function before binding a graphics pipeline.
*
* \param renderPass a render pass handle
* \param buffer a buffer containing draw parameters
* \param offsetInBytes the offset to start reading from the draw buffer
* \param drawCount the number of draw parameter sets that should be read from the draw buffer
* \param stride the byte stride between sets of draw parameters
*/
REFRESHAPI void Refresh_DrawPrimitivesIndirect(
Refresh_RenderPass *renderPass,
Refresh_Buffer *buffer,
Uint32 offsetInBytes,
Uint32 drawCount,
Uint32 stride
);
/**
* Draws data using bound graphics state with an index buffer enabled
* and with draw parameters set from a buffer.
* The buffer layout should match the layout of Refresh_IndexedIndirectDrawCommand.
* You must not call this function before binding a graphics pipeline.
*
* \param renderPass a render pass handle
* \param buffer a buffer containing draw parameters
* \param offsetInBytes the offset to start reading from the draw buffer
* \param drawCount the number of draw parameter sets that should be read from the draw buffer
* \param stride the byte stride between sets of draw parameters
*/
REFRESHAPI void Refresh_DrawIndexedPrimitivesIndirect(
Refresh_RenderPass *renderPass,
Refresh_Buffer *buffer,
Uint32 offsetInBytes,
Uint32 drawCount,
Uint32 stride
);
/**
* Ends the given render pass.
* All bound graphics state on the render pass command buffer is unset.
* The render pass handle is now invalid.
*
* \param renderPass a render pass handle
*/
REFRESHAPI void Refresh_EndRenderPass(
Refresh_RenderPass *renderPass
);
/* Compute Pass */
/**
* Begins a compute pass on a command buffer.
* A compute pass is defined by a set of texture slices and buffers that
* will be written to by compute pipelines.
* These textures and buffers must have been created with the COMPUTE_STORAGE_WRITE bit.
* If these resources will also be read during the pass, they must be created with the COMPUTE_STORAGE_READ bit.
* All operations related to compute pipelines must take place inside of a compute pass.
* You must not begin another compute pass, or a render pass or copy pass
* before ending the compute pass.
*
* \param commandBuffer a command buffer
* \param storageTextureBindings an array of writeable storage texture binding structs
* \param storageTextureBindingCount the number of storage textures to bind from the array
* \param storageBufferBindings an array of writeable storage buffer binding structs
* \param storageBufferBindingCount an array of read-write storage buffer binding structs
*
* \returns a compute pass handle
*
* \sa Refresh_EndComputePass
*/
REFRESHAPI Refresh_ComputePass* Refresh_BeginComputePass(
Refresh_CommandBuffer *commandBuffer,
Refresh_StorageTextureReadWriteBinding *storageTextureBindings,
Uint32 storageTextureBindingCount,
Refresh_StorageBufferReadWriteBinding *storageBufferBindings,
Uint32 storageBufferBindingCount
);
/**
* Binds a compute pipeline on a command buffer for use in compute dispatch.
*
* \param computePass a compute pass handle
* \param computePipeline a compute pipeline to bind
*/
REFRESHAPI void Refresh_BindComputePipeline(
Refresh_ComputePass *computePass,
Refresh_ComputePipeline *computePipeline
);
/**
* Binds storage textures as readonly for use on the compute shader.
* These textures must have been created with REFRESH_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT.
*
* \param computePass a compute pass handle
* \param firstSlot the compute storage texture slot to begin binding from
* \param storageTextureSlices an array of storage texture binding structs
* \param bindingCount the number of storage textures to bind from the array
*/
REFRESHAPI void Refresh_BindComputeStorageTextures(
Refresh_ComputePass *computePass,
Uint32 firstSlot,
Refresh_TextureSlice *storageTextureSlices,
Uint32 bindingCount
);
/**
* Binds storage buffers as readonly for use on the compute shader.
* These buffers must have been created with REFRESH_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT.
*
* \param computePass a compute pass handle
* \param firstSlot the compute storage buffer slot to begin binding from
* \param storageBuffers an array of storage buffer binding structs
* \param bindingCount the number of storage buffers to bind from the array
*/
REFRESHAPI void Refresh_BindComputeStorageBuffers(
Refresh_ComputePass *computePass,
Uint32 firstSlot,
Refresh_Buffer **storageBuffers,
Uint32 bindingCount
);
/**
* Pushes data to a uniform slot on the bound compute pipeline.
* Subsequent draw calls will use this uniform data.
*
* \param computePass a compute pass handle
* \param slotIndex the uniform slot to push data to
* \param data client data to write
* \param dataLengthInBytes the length of the data to write
*/
REFRESHAPI void Refresh_PushComputeUniformData(
Refresh_ComputePass *computePass,
Uint32 slotIndex,
void *data,
Uint32 dataLengthInBytes
);
/**
* Dispatches compute work.
* You must not call this function before binding a compute pipeline.
*
* A VERY IMPORTANT NOTE
* If you dispatch multiple times in a compute pass,
* and the dispatches write to the same resource region as each other,
* there is no guarantee of which order the writes will occur.
* If the write order matters, you MUST end the compute pass and begin another one.
*
* \param computePass a compute pass handle
* \param groupCountX number of local workgroups to dispatch in the X dimension
* \param groupCountY number of local workgroups to dispatch in the Y dimension
* \param groupCountZ number of local workgroups to dispatch in the Z dimension
*/
REFRESHAPI void Refresh_DispatchCompute(
Refresh_ComputePass *computePass,
Uint32 groupCountX,
Uint32 groupCountY,
Uint32 groupCountZ
);
/**
* Ends the current compute pass.
* All bound compute state on the command buffer is unset.
* The compute pass handle is now invalid.
*
* \param computePass a compute pass handle
*/
REFRESHAPI void Refresh_EndComputePass(
Refresh_ComputePass *computePass
);
/* TransferBuffer Data */
/**
* Maps a transfer buffer into application address space.
* You must unmap the transfer buffer before encoding upload commands.
*
* \param device a GPU context
* \param transferBuffer a transfer buffer
* \param cycle if SDL_TRUE, cycles the transfer buffer if it is bound
* \param ppData where to store the address of the mapped transfer buffer memory
*/
REFRESHAPI void Refresh_MapTransferBuffer(
Refresh_Device *device,
Refresh_TransferBuffer *transferBuffer,
SDL_bool cycle,
void **ppData
);
/**
* Unmaps a previously mapped transfer buffer.
*
* \param device a GPU context
* \param transferBuffer a previously mapped transfer buffer
*/
REFRESHAPI void Refresh_UnmapTransferBuffer(
Refresh_Device *device,
Refresh_TransferBuffer *transferBuffer
);
/**
* Immediately copies data from a pointer to a transfer buffer.
*
* \param device a GPU context
* \param data a pointer to data to copy into the transfer buffer
* \param transferBuffer a transfer buffer
* \param copyParams a struct containing parameters specifying copy offsets and size
* \param cycle if SDL_TRUE, cycles the transfer buffer if it is bound, otherwise overwrites the data.
*/
REFRESHAPI void Refresh_SetTransferData(
Refresh_Device *device,
void* data,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams,
SDL_bool cycle
);
/**
* Immediately copies data from a transfer buffer to a pointer.
*
* \param device a GPU context
* \param transferBuffer a transfer buffer
* \param data a data pointer
* \param copyParams a struct containing parameters specifying copy offsets and size
*/
REFRESHAPI void Refresh_GetTransferData(
Refresh_Device *device,
Refresh_TransferBuffer *transferBuffer,
void* data,
Refresh_BufferCopy *copyParams
);
/* Copy Pass */
/**
* Begins a copy pass on a command buffer.
* All operations related to copying to or from buffers or textures take place inside a copy pass.
* You must not begin another copy pass, or a render pass or compute pass
* before ending the copy pass.
*
* \param commandBuffer a command buffer
* \returns a copy pass handle
*/
REFRESHAPI Refresh_CopyPass* Refresh_BeginCopyPass(
Refresh_CommandBuffer *commandBuffer
);
/**
* Uploads data from a transfer buffer to a texture.
* The upload occurs on the GPU timeline.
* You may assume that the upload has finished in subsequent commands.
*
* You must align the data in the transfer buffer to a multiple of
* the texel size of the texture format.
*
* \param copyPass a copy pass handle
* \param transferBuffer a transfer buffer
* \param textureRegion a struct containing parameters specifying the texture region to upload data to
* \param copyParams a struct containing parameters specifying buffer offset, stride, and height
* \param cycle if SDL_TRUE, cycles the texture if the texture slice is bound, otherwise overwrites the data.
*/
REFRESHAPI void Refresh_UploadToTexture(
Refresh_CopyPass *copyPass,
Refresh_TransferBuffer *transferBuffer,
Refresh_TextureRegion *textureRegion,
Refresh_BufferImageCopy *copyParams,
SDL_bool cycle
);
/* Uploads data from a TransferBuffer to a Buffer. */
/**
* Uploads data from a transfer buffer to a buffer.
* The upload occurs on the GPU timeline.
* You may assume that the upload has finished in subsequent commands.
*
* \param copyPass a copy pass handle
* \param transferBuffer a transfer buffer
* \param buffer a buffer
* \param copyParams a struct containing offsets and length
* \param cycle if SDL_TRUE, cycles the buffer if it is bound, otherwise overwrites the data.
*/
REFRESHAPI void Refresh_UploadToBuffer(
Refresh_CopyPass *copyPass,
Refresh_TransferBuffer *transferBuffer,
Refresh_Buffer *buffer,
Refresh_BufferCopy *copyParams,
SDL_bool cycle
);
/**
* Performs a texture-to-texture copy.
* This copy occurs on the GPU timeline.
* You may assume the copy has finished in subsequent commands.
*
* \param copyPass a copy pass handle
* \param source a source texture region
* \param destination must be the same dimensions as the source region
* \param cycle if SDL_TRUE, cycles the destination texture if the destination texture slice is bound, otherwise overwrites the data.
*/
REFRESHAPI void Refresh_CopyTextureToTexture(
Refresh_CopyPass *copyPass,
Refresh_TextureRegion *source,
Refresh_TextureRegion *destination,
SDL_bool cycle
);
/* Copies data from a buffer to a buffer. */
/**
* Performs a buffer-to-buffer copy.
* This copy occurs on the GPU timeline.
* You may assume the copy has finished in subsequent commands.
*
* \param copyPass a copy pass handle
* \param source the buffer to copy from
* \param destination the buffer to copy to
* \param copyParams a struct containing offset and length data
* \param cycle if SDL_TRUE, cycles the destination buffer if it is bound, otherwise overwrites the data.
*/
REFRESHAPI void Refresh_CopyBufferToBuffer(
Refresh_CopyPass *copyPass,
Refresh_Buffer *source,
Refresh_Buffer *destination,
Refresh_BufferCopy *copyParams,
SDL_bool cycle
);
/**
* Generates mipmaps for the given texture.
*
* \param copyPass a copy pass handle
* \param texture a texture with more than 1 mip level
*/
REFRESHAPI void Refresh_GenerateMipmaps(
Refresh_CopyPass *copyPass,
Refresh_Texture *texture
);
/**
* Copies data from a texture to a transfer buffer on the GPU timeline.
* This data is not guaranteed to be copied until the command buffer fence is signaled.
*
* \param copyPass a copy pass handle
* \param textureRegion the texture region to download
* \param transferBuffer the transfer buffer to download into
* \param copyParams a struct containing parameters specifying buffer offset, stride, and height
*/
REFRESHAPI void Refresh_DownloadFromTexture(
Refresh_CopyPass *copyPass,
Refresh_TextureRegion *textureRegion,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferImageCopy *copyParams
);
/**
* Copies data from a buffer to a transfer buffer on the GPU timeline.
* This data is not guaranteed to be copied until the command buffer fence is signaled.
*
* \param copyPass a copy pass handle
* \param buffer the buffer to download
* \param transferBuffer the transfer buffer to download into
* \param copyParams a struct containing offsets and length
*/
REFRESHAPI void Refresh_DownloadFromBuffer(
Refresh_CopyPass *copyPass,
Refresh_Buffer *buffer,
Refresh_TransferBuffer *transferBuffer,
Refresh_BufferCopy *copyParams
);
/**
* Ends the current copy pass.
*
* \param copyPass a copy pass handle
*/
REFRESHAPI void Refresh_EndCopyPass(
Refresh_CopyPass *copyPass
);
/**
* Blits from a source texture region to a destination texture region.
* This function must not be called inside of any render, compute, or copy pass.
*
* \param commandBuffer a command buffer
* \param source the texture region to copy from
* \param destination the texture region to copy to
* \param filterMode the filter mode that will be used when blitting
* \param cycle if SDL_TRUE, cycles the destination texture if the destination texture slice is bound, otherwise overwrites the data.
*/
REFRESHAPI void Refresh_Blit(
Refresh_CommandBuffer *commandBuffer,
Refresh_TextureRegion *source,
Refresh_TextureRegion *destination,
Refresh_Filter filterMode,
SDL_bool cycle
);
/* Submission/Presentation */
/**
* Obtains whether or not a swapchain composition is supported by the GPU backend.
*
* \param device a GPU context
* \param window an SDL_Window
* \param swapchainComposition the swapchain composition to check
*
* \returns SDL_TRUE if supported, SDL_FALSE if unsupported (or on error)
*/
REFRESHAPI SDL_bool Refresh_SupportsSwapchainComposition(
Refresh_Device *device,
SDL_Window *window,
Refresh_SwapchainComposition swapchainComposition
);
/**
* Obtains whether or not a presentation mode is supported by the GPU backend.
*
* \param device a GPU context
* \param window an SDL_Window
* \param presentMode the presentation mode to check
*
* \returns SDL_TRUE if supported, SDL_FALSE if unsupported (or on error)
*/
REFRESHAPI SDL_bool Refresh_SupportsPresentMode(
Refresh_Device *device,
SDL_Window *window,
Refresh_PresentMode presentMode
);
/**
* Claims a window, creating a swapchain structure for it.
* This must be called before Refresh_AcquireSwapchainTexture is called using the window.
*
* \param device a GPU context
* \param window an SDL_Window
* \param swapchainComposition the desired composition of the swapchain
* \param presentMode the desired present mode for the swapchain
*
* \returns SDL_TRUE on success, otherwise SDL_FALSE.
*
* \sa Refresh_AcquireSwapchainTexture
* \sa Refresh_UnclaimWindow
*/
REFRESHAPI SDL_bool Refresh_ClaimWindow(
Refresh_Device *device,
SDL_Window *window,
Refresh_SwapchainComposition swapchainComposition,
Refresh_PresentMode presentMode
);
/**
* Unclaims a window, destroying its swapchain structure.
*
* \param device a GPU context
* \param window an SDL_Window that has been claimed
*
* \sa Refresh_ClaimWindow
*/
REFRESHAPI void Refresh_UnclaimWindow(
Refresh_Device *device,
SDL_Window *window
);
/**
* Changes the swapchain parameters for the given claimed window.
*
* \param device a GPU context
* \param window an SDL_Window that has been claimed
* \param swapchainComposition the desired composition of the swapchain
* \param presentMode the desired present mode for the swapchain
*/
REFRESHAPI void Refresh_SetSwapchainParameters(
Refresh_Device *device,
SDL_Window *window,
Refresh_SwapchainComposition swapchainComposition,
Refresh_PresentMode presentMode
);
/**
* Obtains the texture format of the swapchain for the given window.
*
* \param device a GPU context
* \param window an SDL_Window that has been claimed
*
* \returns the texture format of the swapchain
*/
REFRESHAPI Refresh_TextureFormat Refresh_GetSwapchainTextureFormat(
Refresh_Device *device,
SDL_Window *window
);
/**
* Acquire a command buffer.
* This command buffer is managed by the implementation and should not be freed by the user.
* A command buffer may only be used on the thread it was acquired on.
*
* \param device a GPU context
* \returns a command buffer
*
* \sa Refresh_Submit
* \sa Refresh_SubmitAndAcquireFence
*/
REFRESHAPI Refresh_CommandBuffer* Refresh_AcquireCommandBuffer(
Refresh_Device *device
);
/**
* Acquire a texture to use in presentation.
* When a swapchain texture is acquired on a command buffer,
* it will automatically be submitted for presentation when the command buffer is submitted.
* May return NULL under certain conditions. This is not necessarily an error.
* This texture is managed by the implementation and must not be freed by the user.
* You MUST NOT call this function from any thread other than the one that created the window.
*
* \param commandBuffer a command buffer
* \param window a window that has been claimed
* \param pWidth a pointer filled in with the swapchain width
* \param pHeight a pointer filled in with the swapchain height
* \returns a swapchain texture
*
* \sa Refresh_ClaimWindow
* \sa Refresh_Submit
* \sa Refresh_SubmitAndAcquireFence
*/
REFRESHAPI Refresh_Texture* Refresh_AcquireSwapchainTexture(
Refresh_CommandBuffer *commandBuffer,
SDL_Window *window,
Uint32 *pWidth,
Uint32 *pHeight
);
/**
* Submits a command buffer so its commands can be processed on the GPU.
* It is invalid to use the command buffer after this is called.
*
* \param commandBuffer a command buffer
*
* \sa Refresh_AcquireCommandBuffer
* \sa Refresh_AcquireSwapchainTexture
* \sa Refresh_SubmitAndAcquireFence
*/
REFRESHAPI void Refresh_Submit(
Refresh_CommandBuffer *commandBuffer
);
/**
* Submits a command buffer so its commands can be processed on the GPU,
* and acquires a fence associated with the command buffer.
* You must release this fence when it is no longer needed or it will cause a leak.
* It is invalid to use the command buffer after this is called.
*
* \param commandBuffer a command buffer
* \returns a fence associated with the command buffer
*
* \sa SDL_AcquireCommandBuffer
* \sa Refresh_AcquireSwapchainTexture
* \sa Refresh_Submit
* \sa Refresh_ReleaseFence
*/
REFRESHAPI Refresh_Fence* Refresh_SubmitAndAcquireFence(
Refresh_CommandBuffer *commandBuffer
);
/**
* Blocks the thread until the GPU is completely idle.
*
* \param device a GPU context
*
* \sa Refresh_WaitForFences
*/
REFRESHAPI void Refresh_Wait(
Refresh_Device *device
);
/**
* Blocks the thread until the given fences are signaled.
*
* \param device a GPU context
* \param waitAll if 0, wait for any fence to be signaled, if 1, wait for all fences to be signaled
* \param fenceCount the number of fences in the pFences array
* \param pFences an array of fences to wait on
*
* \sa Refresh_SubmitAndAcquireFence
* \sa Refresh_Wait
*/
REFRESHAPI void Refresh_WaitForFences(
Refresh_Device *device,
SDL_bool waitAll,
Uint32 fenceCount,
Refresh_Fence **pFences
);
/**
* Checks the status of a fence.
*
* \param device a GPU context
* \param fence a fence
* \returns SDL_TRUE if the fence is signaled, SDL_FALSE if it is not
*
* \sa Refresh_SubmitAndAcquireFence
*/
REFRESHAPI SDL_bool Refresh_QueryFence(
Refresh_Device *device,
Refresh_Fence *fence
);
/**
* Releases a fence obtained from Refresh_SubmitAndAcquireFence.
*
* \param device a GPU context
* \param fence a fence
*
* \sa Refresh_SubmitAndAcquireFence
*/
REFRESHAPI void Refresh_ReleaseFence(
Refresh_Device *device,
Refresh_Fence *fence
);
/* Format Info */
/**
* Obtains the texel block size for a texture format.
*
* \param textureFormat the texture format you want to know the texel size of
* \returns the texel block size of the texture format
*
* \sa Refresh_SetTransferData
* \sa Refresh_UploadToTexture
*/
REFRESHAPI Uint32 Refresh_TextureFormatTexelBlockSize(
Refresh_TextureFormat textureFormat
);
/**
* Determines whether a texture format is supported for a given type and usage.
*
* \param device a GPU context
* \param format the texture format to check
* \param type the type of texture (2D, 3D, Cube)
* \param usage a bitmask of all usage scenarios to check
* \returns whether the texture format is supported for this type and usage
*/
REFRESHAPI SDL_bool Refresh_IsTextureFormatSupported(
Refresh_Device *device,
Refresh_TextureFormat format,
Refresh_TextureType type,
Refresh_TextureUsageFlags usage
);
/**
* Determines the "best" sample count for a texture format, i.e.
* the highest supported sample count that is <= the desired sample count.
*
* \param device a GPU context
* \param format the texture format to check
* \param desiredSampleCount the sample count you want
* \returns a hardware-specific version of min(preferred, possible)
*/
REFRESHAPI Refresh_SampleCount Refresh_GetBestSampleCount(
Refresh_Device *device,
Refresh_TextureFormat format,
Refresh_SampleCount desiredSampleCount
);
/* Queries */
/**
* Begins an occlusion query.
*
* This function is included for compatibility with old render systems.
* If you are not supporting an old application, do NOT use this.
*
* \param commandBuffer a command buffer
* \param query an occlusion query object
*/
REFRESHAPI void Refresh_OcclusionQueryBegin(
Refresh_CommandBuffer *commandBuffer,
Refresh_OcclusionQuery *query
);
/**
* Ends an occlusion query.
* You must have called Refresh_OcclusionQueryBegin on the query beforehand.
*
* This function is included for compatibility with old render systems.
* If you are not supporting an old application, do NOT use this.
*
* \param commandBuffer a commandBuffer
* \param query an occlusion query object
*
* \sa Refresh_BeginQuery
*/
REFRESHAPI void Refresh_OcclusionQueryEnd(
Refresh_CommandBuffer *commandBuffer,
Refresh_OcclusionQuery *query
);
/**
* Checks if an occlusion query is complete and fills in the pixel count of the query.
*
* This function is included for compatibility with old render systems.
* If you are not supporting an old application, do NOT use this.
*
* \param device a GPU context
* \param query an occlusion query object
* \param pixelCount a pointer to be filled with the pixel count
* \returns SDL_TRUE if the occlusion query is complete, SDL_FALSE otherwise
*/
REFRESHAPI SDL_bool Refresh_OcclusionQueryPixelCount(
Refresh_Device *device,
Refresh_OcclusionQuery *query,
Uint32 *pixelCount
);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* REFRESH_H */