Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
51 changes: 35 additions & 16 deletions extensions/pl_draw_backend_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -706,13 +706,13 @@ pl__use_nearest_sampler(const plDrawList2D* ptDrawlist, const plDrawCommand* tCm
void
pl_use_nearest_sampler(plDrawLayer2D* ptLayer)
{
gptDraw->add_callback(ptLayer, pl__use_nearest_sampler, NULL, 0);
gptDraw->add_2d_callback(ptLayer, pl__use_nearest_sampler, NULL, 0);
}

void
pl_use_linear_sampler(plDrawLayer2D* ptLayer)
{
gptDraw->add_callback(ptLayer, plDrawCallbackResetRenderState, NULL, 0);
gptDraw->add_2d_callback(ptLayer, plDrawCallbackResetRenderState, NULL, 0);
}

void
Expand Down Expand Up @@ -837,24 +837,15 @@ pl_submit_2d_drawlist(plDrawList2D* ptDrawlist, plRenderEncoder* ptEncoder, floa
gptGfx->bind_vertex_buffer(ptEncoder, ptBufferInfo->tVertexBuffer);
gptGfx->bind_shader(ptEncoder, tCurrentShader);

// track if user shader callback has bound a custom shader (to prevent automatic shader switching)
bool bUserShaderActive = false;

const uint32_t uCmdCount = pl_sb_size(ptDrawlist->sbtDrawCommands);
for(uint32_t i = 0u; i < uCmdCount; i++)
{
plDrawCommand cmd = ptDrawlist->sbtDrawCommands[i];

if(cmd.bSdf && !bSdf)
{
gptGfx->bind_shader(ptEncoder, ptEntry->tSecondaryPipeline);
tCurrentShader = ptEntry->tSecondaryPipeline;
bSdf = true;
}
else if(!cmd.bSdf && bSdf)
{
gptGfx->bind_shader(ptEncoder, ptEntry->tRegularPipeline);
tCurrentShader = ptEntry->tRegularPipeline;
bSdf = false;
}

// regular callback (state changes like sampler switching)
if(cmd.tUserCallback != NULL)
{
if(cmd.tUserCallback == plDrawCallbackResetRenderState)
Expand All @@ -863,13 +854,38 @@ pl_submit_2d_drawlist(plDrawList2D* ptDrawlist, plRenderEncoder* ptEncoder, floa
gptGfx->bind_vertex_buffer(ptEncoder, ptBufferInfo->tVertexBuffer);
gptGfx->bind_shader(ptEncoder, tCurrentShader);
gptDrawBackendCtx->tCurrentSamplerBindGroup = gptDrawBackendCtx->tFontSamplerBindGroup;

bUserShaderActive = false;
}
else
{
cmd.tUserCallback(ptDrawlist, &cmd);
}
}
// user shader (binds custom shader, suppresses bSdf switching)
else if(cmd.ptUserShader != NULL)
{
gptGfx->bind_shader(ptEncoder, *cmd.ptUserShader);
tCurrentShader = *cmd.ptUserShader;
bUserShaderActive = true;
}
else
{
// only switch shaders for actual draw commands when no user shader is active
if(!bUserShaderActive)
{
if(cmd.bSdf && !bSdf)
{
gptGfx->bind_shader(ptEncoder, ptEntry->tSecondaryPipeline);
tCurrentShader = ptEntry->tSecondaryPipeline;
bSdf = true;
}
else if(!cmd.bSdf && bSdf)
{
gptGfx->bind_shader(ptEncoder, ptEntry->tRegularPipeline);
tCurrentShader = ptEntry->tRegularPipeline;
bSdf = false;
}
}

if(pl_rect_width(&cmd.tClip) == 0)
{
Expand Down Expand Up @@ -904,7 +920,10 @@ pl_submit_2d_drawlist(plDrawList2D* ptDrawlist, plRenderEncoder* ptEncoder, floa
gptGfx->set_scissor_region(ptEncoder, &tScissor);
}

// use font atlas texture as fallback when no texture specified
plBindGroupHandle tTexture = {.uData = cmd.tTextureId};
if(tTexture.uData == 0)
tTexture.uData = gptDraw->get_current_font_atlas()->tTexture;
plBindGroupHandle atBindGroups[] = {
gptDrawBackendCtx->tCurrentSamplerBindGroup,
tTexture
Expand Down
23 changes: 20 additions & 3 deletions extensions/pl_draw_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ void
pl_add_2d_callback(plDrawLayer2D* ptLayer, plDrawCallback tCallback, void* pUserData, uint32_t uUserDataSize)
{

plDrawCommand tNewDrawCommand =
plDrawCommand tNewDrawCommand =
{
.tUserCallback = tCallback,
.uUserCallbackDataSize = uUserDataSize,
Expand All @@ -647,6 +647,23 @@ pl_add_2d_callback(plDrawLayer2D* ptLayer, plDrawCallback tCallback, void* pUser
ptLayer->ptLastCommand = NULL;
}

void
pl_set_2d_shader(plDrawLayer2D* ptLayer, plShaderHandle* ptShader)
{
// create a shader-only command (no draw data, just shader switch)
// backend will bind this shader when processing the command stream
plDrawCommand tNewDrawCommand =
{
.ptUserShader = ptShader // NULL clears user shader, non-NULL activates it
};
pl_sb_push(ptLayer->sbtCommandBuffer, tNewDrawCommand);

// force next draw primitive to create a new command rather than
// merging with the previous one - ensures draws after shader switch
// get their own commands that will use the new shader
ptLayer->ptLastCommand = NULL;
}

static void
pl_add_line(plDrawLayer2D* ptLayer, plVec2 p0, plVec2 p1, plDrawLineOptions tOptions)
{
Expand Down Expand Up @@ -3874,7 +3891,7 @@ pl_load_draw_ext(plApiRegistryI* ptApiRegistry, bool bReload)
.get_clip_rect = pl_get_clip_rect,
.add_line = pl_add_line,
.add_lines = pl_add_lines,
.add_callback = pl_add_2d_callback,
.add_2d_callback = pl_add_2d_callback,
.add_text = pl_add_text_ex,
.add_text_clipped = pl_add_text_clipped_ex,
.add_triangle = pl_add_triangle,
Expand All @@ -3896,7 +3913,7 @@ pl_load_draw_ext(plApiRegistryI* ptApiRegistry, bool bReload)
.add_image_quad_ex = pl_add_image_quad_ex,
.add_bezier_quad = pl_add_bezier_quad,
.add_bezier_cubic = pl_add_bezier_cubic,
.add_callback = pl_add_2d_callback
.set_2d_shader = pl_set_2d_shader
};
pl_set_api(ptApiRegistry, plDrawI, &tApi);

Expand Down
8 changes: 6 additions & 2 deletions extensions/pl_draw_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ typedef struct _plFontConfig plFontConfig; // configuration for loading
typedef struct _plFontChar plFontChar; // internal type
typedef struct _plFontGlyph plFontGlyph; // internal type
typedef struct _plFontCustomRect plFontCustomRect; // internal type
typedef struct _plRenderEncoder plRenderEncoder; // pl_graphics_ext.h
typedef union plShaderHandle plShaderHandle; // pl_graphics_ext.h

// advanced callbacks (you probably shouldn't be using this, mostly for backends)
typedef void (*plDrawCallback)(const plDrawList2D*, const plDrawCommand*);
Expand Down Expand Up @@ -182,7 +184,8 @@ typedef struct _plDrawI
const plRect* (*get_clip_rect) (plDrawList2D*);

// advanced (you probably shouldn't be using this, mostly for backends)
void (*add_callback)(plDrawLayer2D*, plDrawCallback, void* userData, uint32_t userDataSize); // userDataSize not setup yet
void (*add_2d_callback)(plDrawLayer2D*, plDrawCallback, void* userData, uint32_t userDataSize);
void (*set_2d_shader)(plDrawLayer2D*, plShaderHandle*);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~3D~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -417,7 +420,8 @@ typedef struct _plDrawCommand
plTextureID tTextureId;
plRect tClip;
bool bSdf;
plDrawCallback tUserCallback;
plDrawCallback tUserCallback;
plShaderHandle* ptUserShader;
void* pUserCallbackData;
uint32_t uUserCallbackDataSize;
} plDrawCommand;
Expand Down
Loading