viewport and scissor ABI break

updatetemplate
cosmonaut 2022-03-04 12:30:33 -08:00
parent 9422d4975f
commit f6b96fe34b
4 changed files with 245 additions and 62 deletions

View File

@ -485,14 +485,6 @@ typedef struct Refresh_ComputeShaderInfo
uint32_t imageBindingCount;
} Refresh_ComputeShaderInfo;
typedef struct Refresh_ViewportState
{
const Refresh_Viewport *viewports;
uint32_t viewportCount;
const Refresh_Rect *scissors;
uint32_t scissorCount;
} Refresh_ViewportState;
typedef struct Refresh_RasterizerState
{
uint8_t depthClampEnable;
@ -546,7 +538,6 @@ typedef struct Refresh_GraphicsPipelineCreateInfo
Refresh_GraphicsShaderInfo fragmentShaderInfo;
Refresh_VertexInputState vertexInputState;
Refresh_PrimitiveType primitiveType;
Refresh_ViewportState viewportState;
Refresh_RasterizerState rasterizerState;
Refresh_MultisampleState multisampleState;
Refresh_DepthStencilState depthStencilState;
@ -991,6 +982,7 @@ REFRESHAPI void Refresh_QueueDestroyGraphicsPipeline(
/* Graphics State */
/* Begins a render pass.
* This will also set a default viewport and scissor state.
*
* renderArea:
* The area affected by the render pass.
@ -1024,6 +1016,20 @@ REFRESHAPI void Refresh_BindGraphicsPipeline(
Refresh_GraphicsPipeline *graphicsPipeline
);
/* Sets the current viewport state. */
REFRESHAPI void Refresh_SetViewportState(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,
Refresh_Viewport *viewport
);
/* Sets the current scissor state. */
REFRESHAPI void Refresh_SetScissorState(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,
Refresh_Rect *scissor
);
/* Binds vertex buffers for use with subsequent draw calls. */
REFRESHAPI void Refresh_BindVertexBuffers(
Refresh_Device *device,

View File

@ -601,6 +601,32 @@ void Refresh_EndRenderPass(
);
}
void Refresh_SetViewportState(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,
Refresh_Viewport *viewport
) {
NULL_RETURN(device)
device->SetViewportState(
device->driverData,
commandBuffer,
viewport
);
}
void Refresh_SetScissorState(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,
Refresh_Rect *scissor
) {
NULL_RETURN(device)
device->SetScissorState(
device->driverData,
commandBuffer,
scissor
);
}
void Refresh_BindGraphicsPipeline(
Refresh_Device *device,
Refresh_CommandBuffer *commandBuffer,

View File

@ -390,6 +390,18 @@ struct Refresh_Device
Refresh_CommandBuffer *commandBuffer
);
void(*SetViewportState)(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_Viewport *viewport
);
void(*SetScissorState)(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_Rect *scissor
);
void(*BindGraphicsPipeline)(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
@ -495,6 +507,8 @@ struct Refresh_Device
ASSIGN_DRIVER_FUNC(QueueDestroyGraphicsPipeline, name) \
ASSIGN_DRIVER_FUNC(BeginRenderPass, name) \
ASSIGN_DRIVER_FUNC(EndRenderPass, name) \
ASSIGN_DRIVER_FUNC(SetViewportState, name) \
ASSIGN_DRIVER_FUNC(SetScissorState, name) \
ASSIGN_DRIVER_FUNC(BindGraphicsPipeline, name) \
ASSIGN_DRIVER_FUNC(BindVertexBuffers, name) \
ASSIGN_DRIVER_FUNC(BindIndexBuffer, name) \

View File

@ -1495,6 +1495,9 @@ typedef struct VulkanCommandBuffer
uint32_t boundDescriptorSetDataCount;
uint32_t boundDescriptorSetDataCapacity;
VkViewport currentViewport;
VkRect2D currentScissor;
/* Track used resources */
VulkanBuffer **usedBuffers;
@ -5763,8 +5766,6 @@ static Refresh_GraphicsPipeline* VULKAN_CreateGraphicsPipeline(
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo;
VkPipelineViewportStateCreateInfo viewportStateCreateInfo;
VkViewport *viewports = SDL_stack_alloc(VkViewport, pipelineCreateInfo->viewportState.viewportCount);
VkRect2D *scissors = SDL_stack_alloc(VkRect2D, pipelineCreateInfo->viewportState.scissorCount);
VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo;
@ -5780,6 +5781,13 @@ static Refresh_GraphicsPipeline* VULKAN_CreateGraphicsPipeline(
pipelineCreateInfo->attachmentInfo.colorAttachmentCount
);
static const VkDynamicState dynamicStates[] =
{
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo;
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
/* Create a "compatible" render pass */
@ -5789,6 +5797,14 @@ static Refresh_GraphicsPipeline* VULKAN_CreateGraphicsPipeline(
pipelineCreateInfo->attachmentInfo
);
/* Dynamic state */
dynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicStateCreateInfo.pNext = NULL;
dynamicStateCreateInfo.flags = 0;
dynamicStateCreateInfo.dynamicStateCount = SDL_arraysize(dynamicStates);
dynamicStateCreateInfo.pDynamicStates = dynamicStates;
/* Shader stages */
graphicsPipeline->vertexShaderModule = (VulkanShaderModule*) pipelineCreateInfo->vertexShaderInfo.shaderModule;
@ -5868,31 +5884,15 @@ static Refresh_GraphicsPipeline* VULKAN_CreateGraphicsPipeline(
/* Viewport */
for (i = 0; i < pipelineCreateInfo->viewportState.viewportCount; i += 1)
{
viewports[i].x = pipelineCreateInfo->viewportState.viewports[i].x;
viewports[i].y = pipelineCreateInfo->viewportState.viewports[i].y;
viewports[i].width = pipelineCreateInfo->viewportState.viewports[i].w;
viewports[i].height = pipelineCreateInfo->viewportState.viewports[i].h;
viewports[i].minDepth = pipelineCreateInfo->viewportState.viewports[i].minDepth;
viewports[i].maxDepth = pipelineCreateInfo->viewportState.viewports[i].maxDepth;
}
for (i = 0; i < pipelineCreateInfo->viewportState.scissorCount; i += 1)
{
scissors[i].offset.x = pipelineCreateInfo->viewportState.scissors[i].x;
scissors[i].offset.y = pipelineCreateInfo->viewportState.scissors[i].y;
scissors[i].extent.width = pipelineCreateInfo->viewportState.scissors[i].w;
scissors[i].extent.height = pipelineCreateInfo->viewportState.scissors[i].h;
}
/* NOTE: viewport and scissor are dynamic, and must be set using the command buffer */
viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportStateCreateInfo.pNext = NULL;
viewportStateCreateInfo.flags = 0;
viewportStateCreateInfo.viewportCount = pipelineCreateInfo->viewportState.viewportCount;
viewportStateCreateInfo.pViewports = viewports;
viewportStateCreateInfo.scissorCount = pipelineCreateInfo->viewportState.scissorCount;
viewportStateCreateInfo.pScissors = scissors;
viewportStateCreateInfo.viewportCount = 1;
viewportStateCreateInfo.pViewports = NULL;
viewportStateCreateInfo.scissorCount = 1;
viewportStateCreateInfo.pScissors = NULL;
/* Rasterization */
@ -6071,7 +6071,7 @@ static Refresh_GraphicsPipeline* VULKAN_CreateGraphicsPipeline(
vkPipelineCreateInfo.pMultisampleState = &multisampleStateCreateInfo;
vkPipelineCreateInfo.pDepthStencilState = &depthStencilStateCreateInfo;
vkPipelineCreateInfo.pColorBlendState = &colorBlendStateCreateInfo;
vkPipelineCreateInfo.pDynamicState = VK_NULL_HANDLE;
vkPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
vkPipelineCreateInfo.layout = graphicsPipeline->pipelineLayout->pipelineLayout;
vkPipelineCreateInfo.renderPass = transientRenderPass;
vkPipelineCreateInfo.subpass = 0;
@ -7786,7 +7786,9 @@ static VkFramebuffer VULKAN_INTERNAL_FetchFramebuffer(
VkRenderPass renderPass,
Refresh_ColorAttachmentInfo *colorAttachmentInfos,
uint32_t colorAttachmentCount,
Refresh_DepthStencilAttachmentInfo *depthStencilAttachmentInfo
Refresh_DepthStencilAttachmentInfo *depthStencilAttachmentInfo,
uint32_t width,
uint32_t height
) {
VkFramebuffer framebuffer;
VkFramebufferCreateInfo framebufferInfo;
@ -7794,10 +7796,7 @@ static VkFramebuffer VULKAN_INTERNAL_FetchFramebuffer(
VkImageView imageViewAttachments[2 * MAX_COLOR_TARGET_BINDINGS + 1];
FramebufferHash hash;
VulkanRenderTarget *renderTarget;
VulkanTexture *texture;
uint32_t attachmentCount = 0;
uint32_t maxWidth = 0;
uint32_t maxHeight = 0;
uint32_t i;
SDL_LockMutex(renderer->framebufferFetchLock);
@ -7821,8 +7820,6 @@ static VkFramebuffer VULKAN_INTERNAL_FetchFramebuffer(
colorAttachmentInfos[i].sampleCount
);
texture = (VulkanTexture*) colorAttachmentInfos[i].texture;
hash.colorAttachmentViews[i] = (
renderTarget->view
);
@ -7833,16 +7830,6 @@ static VkFramebuffer VULKAN_INTERNAL_FetchFramebuffer(
renderTarget->multisampleTexture->view
);
}
if (texture->dimensions.width > maxWidth)
{
maxWidth = texture->dimensions.width;
}
if (texture->dimensions.height > maxHeight)
{
maxHeight = texture->dimensions.height;
}
}
if (depthStencilAttachmentInfo == NULL)
@ -7860,20 +7847,10 @@ static VkFramebuffer VULKAN_INTERNAL_FetchFramebuffer(
REFRESH_SAMPLECOUNT_1
);
hash.depthStencilAttachmentView = renderTarget->view;
if (texture->dimensions.width > maxWidth)
{
maxWidth = texture->dimensions.width;
}
if (texture->dimensions.height > maxHeight)
{
maxHeight = texture->dimensions.height;
}
}
hash.width = maxWidth;
hash.height = maxHeight;
hash.width = width;
hash.height = height;
framebuffer = FramebufferHashArray_Fetch(
&renderer->framebufferHashArray,
@ -7964,6 +7941,84 @@ static VkFramebuffer VULKAN_INTERNAL_FetchFramebuffer(
return framebuffer;
}
static void VULKAN_INTERNAL_SetCurrentViewport(
VulkanCommandBuffer *commandBuffer,
Refresh_Viewport *viewport
) {
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
vulkanCommandBuffer->currentViewport.x = viewport->x;
vulkanCommandBuffer->currentViewport.y = viewport->y;
vulkanCommandBuffer->currentViewport.width = viewport->w;
vulkanCommandBuffer->currentViewport.height = viewport->h;
vulkanCommandBuffer->currentViewport.minDepth = viewport->minDepth;
vulkanCommandBuffer->currentViewport.maxDepth = viewport->maxDepth;
}
static void VULKAN_SetViewportState(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_Viewport *viewport
) {
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
if (!vulkanCommandBuffer->renderPassInProgress)
{
Refresh_LogError("Illegal to set viewport state outside of a render pass!");
return;
}
VULKAN_INTERNAL_SetCurrentViewport(
vulkanCommandBuffer,
viewport
);
renderer->vkCmdSetViewport(
vulkanCommandBuffer->commandBuffer,
0,
1,
&vulkanCommandBuffer->currentViewport
);
}
static void VULKAN_INTERNAL_SetCurrentScissor(
VulkanCommandBuffer *vulkanCommandBuffer,
Refresh_Rect *scissor
) {
vulkanCommandBuffer->currentScissor.offset.x = scissor->x;
vulkanCommandBuffer->currentScissor.offset.y = scissor->y;
vulkanCommandBuffer->currentScissor.extent.width = scissor->w;
vulkanCommandBuffer->currentScissor.extent.height = scissor->h;
}
static void VULKAN_SetScissorState(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
Refresh_Rect *scissor
) {
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
if (!vulkanCommandBuffer->renderPassInProgress)
{
Refresh_LogError("Illegal to set scissor state outside of a render pass!");
return;
}
VULKAN_INTERNAL_SetCurrentScissor(
vulkanCommandBuffer,
scissor
);
renderer->vkCmdSetScissor(
vulkanCommandBuffer->commandBuffer,
0,
1,
&vulkanCommandBuffer->currentScissor
);
}
static void VULKAN_BeginRenderPass(
Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer,
@ -7982,6 +8037,10 @@ static void VULKAN_BeginRenderPass(
uint32_t clearCount = colorAttachmentCount;
uint32_t i;
VkImageAspectFlags depthAspectFlags;
Refresh_Viewport defaultViewport;
Refresh_Rect defaultScissor;
uint32_t framebufferWidth = UINT32_MAX;
uint32_t framebufferHeight = UINT32_MAX;
if (colorAttachmentCount == 0 && depthStencilAttachmentInfo == NULL)
{
@ -7989,6 +8048,38 @@ static void VULKAN_BeginRenderPass(
return;
}
/* The framebuffer cannot be larger than the smallest attachment. */
for (i = 0; i < colorAttachmentCount; i += 1)
{
texture = (VulkanTexture*) colorAttachmentInfos[i].texture;
if (texture->dimensions.width < framebufferWidth)
{
framebufferWidth = texture->dimensions.width;
}
if (texture->dimensions.height < framebufferHeight)
{
framebufferHeight = texture->dimensions.height;
}
}
if (depthStencilAttachmentInfo != NULL)
{
if (texture->dimensions.width < framebufferWidth)
{
framebufferWidth = texture->dimensions.width;
}
if (texture->dimensions.height < framebufferHeight)
{
framebufferHeight = texture->dimensions.height;
}
}
/* Fetch required render objects */
renderPass = VULKAN_INTERNAL_FetchRenderPass(
renderer,
colorAttachmentInfos,
@ -8001,7 +8092,9 @@ static void VULKAN_BeginRenderPass(
renderPass,
colorAttachmentInfos,
colorAttachmentCount,
depthStencilAttachmentInfo
depthStencilAttachmentInfo,
framebufferWidth,
framebufferHeight
);
/* Layout transitions */
@ -8103,6 +8196,30 @@ static void VULKAN_BeginRenderPass(
(VulkanTexture*) colorAttachmentInfos[i].texture;
}
vulkanCommandBuffer->renderPassColorTargetCount = colorAttachmentCount;
/* Set sensible default viewport state */
defaultViewport.x = 0;
defaultViewport.y = 0;
defaultViewport.w = framebufferWidth;
defaultViewport.h = framebufferHeight;
defaultViewport.minDepth = 0;
defaultViewport.maxDepth = 1;
VULKAN_INTERNAL_SetCurrentViewport(
vulkanCommandBuffer,
&defaultViewport
);
defaultScissor.x = 0;
defaultScissor.y = 0;
defaultScissor.w = framebufferWidth;
defaultScissor.h = framebufferHeight;
VULKAN_INTERNAL_SetCurrentScissor(
vulkanCommandBuffer,
&defaultScissor
);
}
static void VULKAN_EndRenderPass(
@ -8175,6 +8292,12 @@ static void VULKAN_BindGraphicsPipeline(
VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer;
VulkanGraphicsPipeline* pipeline = (VulkanGraphicsPipeline*) graphicsPipeline;
if (!vulkanCommandBuffer->renderPassInProgress)
{
Refresh_LogError("Illegal to bind a graphics pipeline outside of a render pass!");
return;
}
if ( vulkanCommandBuffer->vertexUniformBuffer != renderer->dummyVertexUniformBuffer &&
vulkanCommandBuffer->vertexUniformBuffer != NULL
) {
@ -8239,6 +8362,20 @@ static void VULKAN_BindGraphicsPipeline(
vulkanCommandBuffer->currentGraphicsPipeline = pipeline;
VULKAN_INTERNAL_TrackGraphicsPipeline(renderer, vulkanCommandBuffer, pipeline);
renderer->vkCmdSetViewport(
vulkanCommandBuffer->commandBuffer,
0,
1,
&vulkanCommandBuffer->currentViewport
);
renderer->vkCmdSetScissor(
vulkanCommandBuffer->commandBuffer,
0,
1,
&vulkanCommandBuffer->currentScissor
);
}
static void VULKAN_BindVertexBuffers(