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

View File

@ -390,6 +390,18 @@ struct Refresh_Device
Refresh_CommandBuffer *commandBuffer 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)( void(*BindGraphicsPipeline)(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
Refresh_CommandBuffer *commandBuffer, Refresh_CommandBuffer *commandBuffer,
@ -495,6 +507,8 @@ struct Refresh_Device
ASSIGN_DRIVER_FUNC(QueueDestroyGraphicsPipeline, name) \ ASSIGN_DRIVER_FUNC(QueueDestroyGraphicsPipeline, name) \
ASSIGN_DRIVER_FUNC(BeginRenderPass, name) \ ASSIGN_DRIVER_FUNC(BeginRenderPass, name) \
ASSIGN_DRIVER_FUNC(EndRenderPass, name) \ ASSIGN_DRIVER_FUNC(EndRenderPass, name) \
ASSIGN_DRIVER_FUNC(SetViewportState, name) \
ASSIGN_DRIVER_FUNC(SetScissorState, name) \
ASSIGN_DRIVER_FUNC(BindGraphicsPipeline, name) \ ASSIGN_DRIVER_FUNC(BindGraphicsPipeline, name) \
ASSIGN_DRIVER_FUNC(BindVertexBuffers, name) \ ASSIGN_DRIVER_FUNC(BindVertexBuffers, name) \
ASSIGN_DRIVER_FUNC(BindIndexBuffer, name) \ ASSIGN_DRIVER_FUNC(BindIndexBuffer, name) \

View File

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