implement Clear

pull/8/head
cosmonaut 2020-12-28 22:19:46 -08:00
parent ee91cca9f6
commit cea9b853a4
4 changed files with 135 additions and 16 deletions

View File

@ -98,7 +98,7 @@ typedef enum REFRESH_StoreOp
typedef enum REFRESH_ClearOptions
{
REFRESH_CLEAROPTIONS_TARGET = 1,
REFRESH_CLEAROPTIONS_COLOR = 1,
REFRESH_CLEAROPTIONS_DEPTH = 2,
REFRESH_CLEAROPTIONS_STENCIL = 4,
} REFRESH_ClearOptions;
@ -619,21 +619,26 @@ REFRESHAPI void REFRESH_DestroyDevice(REFRESH_Device *device);
/* Drawing */
/* Clears the targets of the currently bound framebuffer.
* If fewer colors are passed than the number of color targets in the
* framebuffer, this function will clear the first n color targets.
*
* NOTE:
* It is generally recommended to clear in BeginRenderPass
* rather than by calling this function.
* rather than by calling this function unless necessary.
*
* options: Bitflags to specify color/depth/stencil buffers for clearing.
* colors: The new values of the cleared color buffers.
* colorCount: The amount of cleared color buffers.
* depth: The new value of the cleared depth buffer.
* stencil: The new value of the cleared stencil buffer.
* clearRect: Area to clear.
* options: Bitflags to specify color/depth/stencil buffers for clearing.
* colors: An array of color values for the cleared color buffers.
* colorCount: The number of colors in the above array.
* depth: The new value of the cleared depth buffer.
* stencil: The new value of the cleared stencil buffer.
*/
REFRESHAPI void REFRESH_Clear(
REFRESH_Device *device,
REFRESH_Rect *clearRect,
REFRESH_ClearOptions options,
REFRESH_Vec4 **colors,
uint32_t colorCount,
REFRESH_Color *colors,
uint32_t colorCount,
float depth,
int32_t stencil
);

View File

@ -149,14 +149,23 @@ void REFRESH_DestroyDevice(REFRESH_Device *device)
void REFRESH_Clear(
REFRESH_Device *device,
REFRESH_Rect *clearRect,
REFRESH_ClearOptions options,
REFRESH_Vec4 **colors,
uint32_t colorCount,
REFRESH_Color *colors,
uint32_t colorCount,
float depth,
int32_t stencil
) {
NULL_RETURN(device);
device->Clear(device->driverData, options, colors, colorCount, depth, stencil);
device->Clear(
device->driverData,
clearRect,
options,
colors,
colorCount,
depth,
stencil
);
}
void REFRESH_DrawIndexedPrimitives(

View File

@ -170,8 +170,9 @@ struct REFRESH_Device
void (*Clear)(
REFRESH_Renderer *driverData,
REFRESH_Rect *clearRect,
REFRESH_ClearOptions options,
REFRESH_Vec4 **colors,
REFRESH_Color *colors,
uint32_t colorCount,
float depth,
int32_t stencil

View File

@ -738,6 +738,8 @@ typedef struct VulkanFramebuffer
VulkanColorTarget *colorTargets[MAX_COLOR_TARGET_BINDINGS];
uint32_t colorTargetCount;
VulkanDepthStencilTarget *depthStencilTarget;
uint32_t width;
uint32_t height;
} VulkanFramebuffer;
/* Cache structures */
@ -3253,13 +3255,112 @@ static void VULKAN_DestroyDevice(
static void VULKAN_Clear(
REFRESH_Renderer *driverData,
REFRESH_Rect *clearRect,
REFRESH_ClearOptions options,
REFRESH_Vec4 **colors,
uint32_t colorCount,
REFRESH_Color *colors,
uint32_t colorCount,
float depth,
int32_t stencil
) {
SDL_assert(0);
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
uint32_t attachmentCount, i;
VkClearAttachment clearAttachments[MAX_COLOR_TARGET_BINDINGS + 1];
VkClearRect vulkanClearRect;
VkClearValue clearValues[4];
uint8_t shouldClearColor = options & REFRESH_CLEAROPTIONS_COLOR;
uint8_t shouldClearDepth = options & REFRESH_CLEAROPTIONS_DEPTH;
uint8_t shouldClearStencil = options & REFRESH_CLEAROPTIONS_STENCIL;
uint8_t shouldClearDepthStencil = (
(shouldClearDepth || shouldClearStencil) &&
renderer->currentFramebuffer->depthStencilTarget != NULL
);
if (!shouldClearColor && !shouldClearDepthStencil)
{
return;
}
vulkanClearRect.baseArrayLayer = 0;
vulkanClearRect.layerCount = 1;
vulkanClearRect.rect.offset.x = clearRect->x;
vulkanClearRect.rect.offset.y = clearRect->y;
vulkanClearRect.rect.extent.width = clearRect->w;
vulkanClearRect.rect.extent.height = clearRect->h;
attachmentCount = 0;
if (shouldClearColor)
{
for (i = 0; i < colorCount; i += 1)
{
clearValues[i].color.float32[0] = colors[i].r / 255.0f;
clearValues[i].color.float32[1] = colors[i].g / 255.0f;
clearValues[i].color.float32[2] = colors[i].b / 255.0f;
clearValues[i].color.float32[3] = colors[i].a / 255.0f;
}
for (i = 0; i < colorCount; i += 1)
{
clearAttachments[attachmentCount].aspectMask =
VK_IMAGE_ASPECT_COLOR_BIT;
clearAttachments[attachmentCount].colorAttachment =
attachmentCount;
clearAttachments[attachmentCount].clearValue =
clearValues[attachmentCount];
attachmentCount += 1;
/* Do NOT clear the multisample image here!
* Vulkan treats them both as the same color attachment.
* Vulkan is a very good and not confusing at all API.
*/
}
}
if (shouldClearDepthStencil)
{
clearAttachments[attachmentCount].aspectMask = 0;
clearAttachments[attachmentCount].colorAttachment = 0;
if (shouldClearDepth)
{
if (depth < 0.0f)
{
depth = 0.0f;
}
else if (depth > 1.0f)
{
depth = 1.0f;
}
clearAttachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
clearAttachments[attachmentCount].clearValue.depthStencil.depth = depth;
}
else
{
clearAttachments[attachmentCount].clearValue.depthStencil.depth = 0.0f;
}
if (shouldClearStencil)
{
clearAttachments[attachmentCount].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
clearAttachments[attachmentCount].clearValue.depthStencil.stencil = stencil;
}
else
{
clearAttachments[attachmentCount].clearValue.depthStencil.stencil = 0;
}
attachmentCount += 1;
}
RECORD_CMD(renderer->vkCmdClearAttachments(
renderer->currentCommandBuffer,
attachmentCount,
clearAttachments,
1,
&vulkanClearRect
));
}
static void VULKAN_DrawInstancedPrimitives(
@ -4474,6 +4575,9 @@ static REFRESH_Framebuffer* VULKAN_CreateFramebuffer(
vulkanFramebuffer->depthStencilTarget =
(VulkanDepthStencilTarget*) framebufferCreateInfo->pDepthStencilTarget;
vulkanFramebuffer->width = framebufferCreateInfo->width;
vulkanFramebuffer->height = framebufferCreateInfo->height;
SDL_stack_free(imageViews);
return (REFRESH_Framebuffer*) vulkanFramebuffer;
}