Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shader Extension Proposal #202

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ add_definitions(
-DFNA3D_DRIVER_VULKAN
-DFNA3D_DRIVER_OPENGL
)
if(BUILD_SDL3)
add_definitions(-DFNA3D_DRIVER_SDL)
endif()
add_definitions(
-DMOJOSHADER_NO_VERSION_INCLUDE
-DMOJOSHADER_USE_SDL_STDLIB
Expand Down Expand Up @@ -101,6 +104,7 @@ add_library(FNA3D
src/FNA3D.c
src/FNA3D_Driver_D3D11.c
src/FNA3D_Driver_OpenGL.c
src/FNA3D_Driver_SDL.c
src/FNA3D_Driver_Vulkan.c
src/FNA3D_Image.c
src/FNA3D_CommandBuffer.c
Expand Down
127 changes: 122 additions & 5 deletions include/FNA3D.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ typedef enum FNA3D_CubeMapFace
typedef enum FNA3D_BufferUsage
{
FNA3D_BUFFERUSAGE_NONE,
FNA3D_BUFFERUSAGE_WRITEONLY
FNA3D_BUFFERUSAGE_WRITEONLY,
FNA3D_BUFFERUSAGE_COMPUTE_EXT /* SDL shader extension only */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean 'usable by compute AND write only'? Or is it a bit

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value is actually completely ignored on every backend, so setting COMPUTE_EXT on the SDL backend is the only place this would actually matter.

} FNA3D_BufferUsage;

typedef enum FNA3D_SetDataOptions
Expand Down Expand Up @@ -302,6 +303,14 @@ typedef enum FNA3D_VertexElementUsage
FNA3D_VERTEXELEMENTUSAGE_TESSELATEFACTOR
} FNA3D_VertexElementUsage;

typedef enum FNA3D_TextureUsageFlagBits
{
FNA3D_TEXTUREUSAGE_RENDERTARGET_BIT = 0x00000001,
FNA3D_TEXTUREUSAGE_COMPUTE_BIT = 0x00000002,
} FNA3D_TextureUsageFlagBits;

typedef uint8_t FNA3D_TextureUsageFlags;

/* Structures, should match XNA 4.0 */

typedef struct FNA3D_Color
Expand Down Expand Up @@ -888,7 +897,8 @@ FNA3DAPI int32_t FNA3D_GetBackbufferMultiSampleCount(FNA3D_Device *device);
* width: The width of the texture image.
* height: The height of the texture image.
* levelCount: The number of mipmap levels to allocate.
* isRenderTarget: Set this to 1 when using this with SetRenderTargets.
* usageFlags: Must have RENDERTARGET_BIT when using with SetRenderTargets.
* Must have COMPUTE_BIT when using with BindComputeTexturesEXT.
*
* Returns an allocated FNA3D_Texture* object. Note that the contents of the
* texture are undefined, so you must call SetData at least once before drawing!
Expand All @@ -899,7 +909,7 @@ FNA3DAPI FNA3D_Texture* FNA3D_CreateTexture2D(
int32_t width,
int32_t height,
int32_t levelCount,
uint8_t isRenderTarget
FNA3D_TextureUsageFlags usageFlags
);

/* Creates a 3D texture to be applied to VerifySampler.
Expand Down Expand Up @@ -927,7 +937,8 @@ FNA3DAPI FNA3D_Texture* FNA3D_CreateTexture3D(
* format: The pixel format of the texture data.
* size: The length of a single edge of the texture cube.
* levelCount: The number of mipmap levels to allocate.
* isRenderTarget: Set this to 1 when using this with SetRenderTargets.
* usageFlags: Must have RENDERTARGET_BIT when using with SetRenderTargets.
* Must have COMPUTE_BIT when using with BindComputeTexturesEXT.
*
* Returns an allocated FNA3D_Texture* object. Note that the contents of the
* texture are undefined, so you must call SetData at least once before drawing!
Expand All @@ -937,7 +948,7 @@ FNA3DAPI FNA3D_Texture* FNA3D_CreateTextureCube(
FNA3D_SurfaceFormat format,
int32_t size,
int32_t levelCount,
uint8_t isRenderTarget
FNA3D_TextureUsageFlags usageFlags
);

/* Sends a texture to be destroyed by the renderer. Note that we call it
Expand Down Expand Up @@ -1538,6 +1549,112 @@ FNA3DAPI void FNA3D_SetStringMarker(FNA3D_Device *device, const char *text);
*/
FNA3DAPI void FNA3D_SetTextureName(FNA3D_Device *device, FNA3D_Texture *texture, const char *text);

/* Shader Extension
*
* These functions are ONLY valid with the SDL backend.
*/

typedef struct SDL_GpuGraphicsShaderInfo SDL_GpuGraphicsShaderInfo;
typedef struct SDL_GpuComputeShaderInfo SDL_GpuComputeShaderInfo;
typedef struct SDL_GpuComputeBufferBinding SDL_GpuComputeBufferBinding;
typedef struct SDL_GpuComputeTextureBinding SDL_GpuComputeTextureBinding;

/* Binds a vertex-fragment shader pair to be used with draw calls.
* If you call ApplyEffect, the shaders will be treated as unbound
* and it will become invalid to call any of the graphics shader EXT functions.
*
* vertShaderInfo: A struct containing the vertex shader module to bind and relevant metadata.
* fragShaderInfo: A struct containing the fragment shader module to bind and relevant metadata.
*/
FNA3DAPI void FNA3D_BindGraphicsShadersEXT(
FNA3D_Device *device,
SDL_GpuGraphicsShaderInfo *vertShaderInfo,
SDL_GpuGraphicsShaderInfo *fragShaderInfo
);

/* Pushes vertex uniform data to be used with subsequent draw calls.
* You may only call this after FNA3D_BindGraphicsShadersEXT has been called.
*
* data: client data to write into the uniform buffer
* dataLengthInBytes: the length of the client data to write
*/
FNA3DAPI void FNA3D_PushVertexShaderUniformsEXT(
FNA3D_Device *device,
void *data,
uint32_t dataLengthInBytes
);

/* Pushes fragment uniform data to be used with subsequent draw calls.
* You may only call this after FNA3D_BindGraphicsShadersEXT has been called.
*
* data: client data to write into the uniform buffer
* dataLengthInBytes: the length of the client data to write
*/
FNA3DAPI void FNA3D_PushFragmentShaderUniformsEXT(
FNA3D_Device *device,
void *data,
uint32_t dataLengthInBytes
);

/* Binds a compute shader to be used with compute dispatch calls.
* Note that this will break the render pass and unbind the graphics shaders,
* so interleaving this with draw calls will have bad performance.
*
* computeShaderInfo: A struct containing the compute shader module to bind and relevant metadata.
*/
FNA3DAPI void FNA3D_BindComputeShaderEXT(
FNA3D_Device *device,
SDL_GpuComputeShaderInfo *computeShaderInfo
);

/* Binds buffers for use with the bound compute pipeline.
* You may only call this function after FNA3D_BindComputeShaderEXT has been called.
*
* pBindings: An array of structs containing buffer and cycle option pairs.
* Must be at least as long as the buffer bindings specified in the compute shader.
*/
FNA3DAPI void FNA3D_BindComputeBuffersEXT(
FNA3D_Device *device,
SDL_GpuComputeBufferBinding *pBindings
);

/* Binds textures for use with the bound compute pipeline.
* You may only call this function after FNA3D_BindComputeShaderEXT has been called.
*
* pBindings: An array of structs containing texture and cycle option pairs.
* Must be at least as long as the texture bindings specified in the compute shader.
*/
FNA3DAPI void FNA3D_BindComputeTexturesEXT(
FNA3D_Device *device,
SDL_GpuComputeTextureBinding *pBindings
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a blessed way to feed FNA3D textures in to this? Or would you use a SysTexture?
From looking at this it seems like in this proposal, fragment/vertex shaders ('graphics' shaders) can only consume FNA3D textures, and compute shaders can only consume raw SDL_Gpu textures.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FNA3D texture handles are just sdl_gpu texture handles, but I agree that this is awkward... I'll just wrap the SDL struct and handle it in the implementation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I was wrong and FNA3D_Driver_SDL was wrapping the texture handles. So nice catch!

);

/* Pushes compute uniform data to be used with subsequent compute dispatches.
* You may only call this after FNA3D_BindComputeShaderEXT has been called.
*
* data: client data to write into the uniform buffer
* dataLengthInBytes: the length of the client data to write
*/
FNA3DAPI void FNA3D_PushComputeShaderUniformsEXT(
FNA3D_Device *device,
void *data,
uint32_t dataLengthInBytes
);

/* Dispatches compute work.
* You may only call this after FNA3D_BindComputeShaderEXT has been called.
*
* groupCountX: number of local workgroups to dispatch in the X dimension
* groupCountY: number of local workgroups to dispatch in the Y dimension
* groupCountZ: number of local workgroups to dispatch in the Z dimension
*/
FNA3DAPI void FNA3D_DispatchComputeEXT(
FNA3D_Device *device,
uint32_t groupCountX,
uint32_t groupCountY,
uint32_t groupCountZ
);

#ifdef __cplusplus
}
#endif /* __cplusplus */
Expand Down
27 changes: 23 additions & 4 deletions src/FNA3D.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
/* Drivers */

static const FNA3D_Driver *drivers[] = {
#if FNA3D_DRIVER_SDL
&SDLGPUDriver,
#endif
#if FNA3D_DRIVER_D3D11
&D3D11Driver,
#endif
Expand Down Expand Up @@ -627,7 +630,7 @@ FNA3D_Texture* FNA3D_CreateTexture2D(
int32_t width,
int32_t height,
int32_t levelCount,
uint8_t isRenderTarget
FNA3D_TextureUsageFlags usageFlags
) {
/* We're stuck tracing _after_ the call instead of _before_, because
* of threading issues. This can cause timing issues!
Expand All @@ -643,7 +646,7 @@ FNA3D_Texture* FNA3D_CreateTexture2D(
width,
height,
levelCount,
isRenderTarget
usageFlags
);
TRACE_CREATETEXTURE2D
return result;
Expand Down Expand Up @@ -682,7 +685,7 @@ FNA3D_Texture* FNA3D_CreateTextureCube(
FNA3D_SurfaceFormat format,
int32_t size,
int32_t levelCount,
uint8_t isRenderTarget
FNA3D_TextureUsageFlags usageFlags
) {
/* We're stuck tracing _after_ the call instead of _before_, because
* of threading issues. This can cause timing issues!
Expand All @@ -697,7 +700,7 @@ FNA3D_Texture* FNA3D_CreateTextureCube(
format,
size,
levelCount,
isRenderTarget
usageFlags
);
TRACE_CREATETEXTURECUBE
return result;
Expand Down Expand Up @@ -1530,4 +1533,20 @@ FNA3D_Texture* FNA3D_CreateSysTextureEXT(
);
}

void FNA3D_BindGraphicsShadersEXT(
FNA3D_Device *device,
SDL_GpuGraphicsShaderInfo *vertShaderInfo,
SDL_GpuGraphicsShaderInfo *fragShaderInfo
) {
if (device == NULL)
{
return;
}
device->BindGraphicsShadersEXT(
device->driverData,
vertShaderInfo,
fragShaderInfo
);
}

/* vim: set noexpandtab shiftwidth=8 tabstop=8: */
63 changes: 60 additions & 3 deletions src/FNA3D_Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ struct FNA3D_Device
int32_t width,
int32_t height,
int32_t levelCount,
uint8_t isRenderTarget
FNA3D_TextureUsageFlags usageFlags
);
FNA3D_Texture* (*CreateTexture3D)(
FNA3D_Renderer *driverData,
Expand All @@ -470,7 +470,7 @@ struct FNA3D_Device
FNA3D_SurfaceFormat format,
int32_t size,
int32_t levelCount,
uint8_t isRenderTarget
FNA3D_TextureUsageFlags usageFlags
);
void (*AddDisposeTexture)(
FNA3D_Renderer *driverData,
Expand Down Expand Up @@ -732,6 +732,54 @@ struct FNA3D_Device
FNA3D_SysTextureEXT *externalTextureInfo
);

/* Shader Extension */

void (*BindGraphicsShadersEXT)(
FNA3D_Renderer *driverData,
SDL_GpuGraphicsShaderInfo *vertShaderInfo,
SDL_GpuGraphicsShaderInfo *fragShaderInfo
);

void (*PushVertexShaderUniformsEXT)(
FNA3D_Renderer *driverData,
void *data,
uint32_t dataLengthInBytes
);

void (*PushFragmentShaderUniformsEXT)(
FNA3D_Renderer *driverData,
void *data,
uint32_t dataLengthInBytes
);

void (*BindComputeShaderEXT)(
FNA3D_Renderer *driverData,
SDL_GpuComputeShaderInfo *computeShaderInfo
);

void (*BindComputeBuffersEXT)(
FNA3D_Renderer *driverData,
SDL_GpuComputeBufferBinding *pBindings
);

void (*BindComputeTexturesEXT)(
FNA3D_Renderer *driverData,
SDL_GpuComputeTextureBinding *pBindings
);

void (*PushComputeShaderUniformsEXT)(
FNA3D_Renderer *driverData,
void *data,
uint32_t dataLengthInBytes
);

void (*DispatchComputeEXT)(
FNA3D_Renderer *driverData,
uint32_t groupCountX,
uint32_t groupCountY,
uint32_t groupCountZ
);

/* Opaque pointer for the Driver */
FNA3D_Renderer *driverData;
};
Expand Down Expand Up @@ -813,7 +861,15 @@ struct FNA3D_Device
ASSIGN_DRIVER_FUNC(SetStringMarker, name) \
ASSIGN_DRIVER_FUNC(SetTextureName, name) \
ASSIGN_DRIVER_FUNC(GetSysRenderer, name) \
ASSIGN_DRIVER_FUNC(CreateSysTexture, name)
ASSIGN_DRIVER_FUNC(CreateSysTexture, name) \
ASSIGN_DRIVER_FUNC(BindGraphicsShadersEXT, name) \
ASSIGN_DRIVER_FUNC(PushVertexShaderUniformsEXT, name) \
ASSIGN_DRIVER_FUNC(PushFragmentShaderUniformsEXT, name) \
ASSIGN_DRIVER_FUNC(BindComputeShaderEXT, name) \
ASSIGN_DRIVER_FUNC(BindComputeTexturesEXT, name) \
ASSIGN_DRIVER_FUNC(BindComputeBuffersEXT, name) \
ASSIGN_DRIVER_FUNC(PushComputeShaderUniformsEXT, name) \
ASSIGN_DRIVER_FUNC(DispatchComputeEXT, name)

typedef struct FNA3D_Driver
{
Expand All @@ -828,6 +884,7 @@ typedef struct FNA3D_Driver
FNA3D_SHAREDINTERNAL FNA3D_Driver VulkanDriver;
FNA3D_SHAREDINTERNAL FNA3D_Driver D3D11Driver;
FNA3D_SHAREDINTERNAL FNA3D_Driver OpenGLDriver;
FNA3D_SHAREDINTERNAL FNA3D_Driver SDLGPUDriver;
FNA3D_SHAREDINTERNAL FNA3D_Driver GNMXDriver;

#endif /* FNA3D_DRIVER_H */
Expand Down
Loading
Loading