vk: Add clear load-op for render passes
This commit is contained in:
@@ -323,6 +323,8 @@ VkResult VKAPI vkCreateDevice(
|
||||
|
||||
pthread_mutex_init(&device->mutex, NULL);
|
||||
|
||||
anv_device_init_meta(device);
|
||||
|
||||
*pDevice = (VkDevice) device;
|
||||
|
||||
return VK_SUCCESS;
|
||||
@@ -1739,7 +1741,9 @@ VkResult VKAPI vkCreateCommandBuffer(
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
cmd_buffer->device = device;
|
||||
|
||||
cmd_buffer->rs_state = NULL;
|
||||
cmd_buffer->vp_state = NULL;
|
||||
|
||||
result = anv_batch_init(&cmd_buffer->batch, device);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
@@ -2008,7 +2012,9 @@ void VKAPI vkCmdBindDynamicStateObject(
|
||||
switch (stateBindPoint) {
|
||||
case VK_STATE_BIND_POINT_VIEWPORT:
|
||||
vp_state = (struct anv_dynamic_vp_state *) dynamicState;
|
||||
|
||||
/* We emit state immediately, but set cmd_buffer->vp_state to indicate
|
||||
* that vp state has been set in this command buffer. */
|
||||
cmd_buffer->vp_state = vp_state;
|
||||
anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_SCISSOR_STATE_POINTERS,
|
||||
.ScissorRectPointer = vp_state->scissor.offset);
|
||||
anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_VIEWPORT_STATE_POINTERS_CC,
|
||||
@@ -2571,6 +2577,27 @@ VkResult VKAPI vkCreateFramebuffer(
|
||||
framebuffer->height = pCreateInfo->height;
|
||||
framebuffer->layers = pCreateInfo->layers;
|
||||
|
||||
vkCreateDynamicViewportState((VkDevice) device,
|
||||
&(VkDynamicVpStateCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DYNAMIC_VP_STATE_CREATE_INFO,
|
||||
.viewportAndScissorCount = 2,
|
||||
.pViewports = (VkViewport[]) {
|
||||
{
|
||||
.originX = 0,
|
||||
.originY = 0,
|
||||
.width = pCreateInfo->width,
|
||||
.height = pCreateInfo->height,
|
||||
.minDepth = 0,
|
||||
.maxDepth = 1
|
||||
},
|
||||
},
|
||||
.pScissors = (VkRect[]) {
|
||||
{ { 0, 0 },
|
||||
{ pCreateInfo->width, pCreateInfo->height } },
|
||||
}
|
||||
},
|
||||
&framebuffer->vp_state);
|
||||
|
||||
*pFramebuffer = (VkFramebuffer) framebuffer;
|
||||
|
||||
return VK_SUCCESS;
|
||||
@@ -2583,16 +2610,29 @@ VkResult VKAPI vkCreateRenderPass(
|
||||
{
|
||||
struct anv_device *device = (struct anv_device *) _device;
|
||||
struct anv_render_pass *pass;
|
||||
size_t size;
|
||||
|
||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
|
||||
|
||||
pass = anv_device_alloc(device, sizeof(*pass), 8,
|
||||
size = sizeof(*pass) +
|
||||
pCreateInfo->layers * sizeof(struct anv_render_pass_layer);
|
||||
pass = anv_device_alloc(device, size, 8,
|
||||
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||
if (pass == NULL)
|
||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
pass->render_area = pCreateInfo->renderArea;
|
||||
|
||||
pass->num_layers = pCreateInfo->layers;
|
||||
|
||||
pass->num_clear_layers = 0;
|
||||
for (uint32_t i = 0; i < pCreateInfo->layers; i++) {
|
||||
pass->layers[i].color_load_op = pCreateInfo->pColorLoadOps[i];
|
||||
pass->layers[i].clear_color = pCreateInfo->pColorLoadClearValues[i];
|
||||
if (pass->layers[i].color_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
|
||||
pass->num_clear_layers++;
|
||||
}
|
||||
|
||||
*pRenderPass = (VkRenderPass) pass;
|
||||
|
||||
return VK_SUCCESS;
|
||||
@@ -2617,6 +2657,8 @@ void VKAPI vkCmdBeginRenderPass(
|
||||
pass->render_area.offset.x + pass->render_area.extent.width - 1,
|
||||
.DrawingRectangleOriginY = 0,
|
||||
.DrawingRectangleOriginX = 0);
|
||||
|
||||
anv_cmd_buffer_clear(cmd_buffer, pass);
|
||||
}
|
||||
|
||||
void VKAPI vkCmdEndRenderPass(
|
||||
|
@@ -29,6 +29,253 @@
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#define GLSL(src) "#version 330\n" #src
|
||||
|
||||
void
|
||||
anv_device_init_meta(struct anv_device *device)
|
||||
{
|
||||
VkPipelineIaStateCreateInfo ia_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO,
|
||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
|
||||
.disableVertexReuse = false,
|
||||
.primitiveRestartEnable = false,
|
||||
.primitiveRestartIndex = 0
|
||||
};
|
||||
|
||||
/* We don't use a vertex shader for clearing, but instead build and pass
|
||||
* the VUEs directly to the rasterization backend.
|
||||
*/
|
||||
static const char fs_source[] = GLSL(
|
||||
out vec4 f_color;
|
||||
flat in vec4 v_color;
|
||||
void main()
|
||||
{
|
||||
f_color = v_color;
|
||||
});
|
||||
|
||||
VkShader fs;
|
||||
vkCreateShader((VkDevice) device,
|
||||
&(VkShaderCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
|
||||
.codeSize = sizeof(fs_source),
|
||||
.pCode = fs_source,
|
||||
.flags = 0
|
||||
},
|
||||
&fs);
|
||||
|
||||
VkPipelineShaderStageCreateInfo fs_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.pNext = &ia_create_info,
|
||||
.shader = {
|
||||
.stage = VK_SHADER_STAGE_FRAGMENT,
|
||||
.shader = fs,
|
||||
.linkConstBufferCount = 0,
|
||||
.pLinkConstBufferInfo = NULL,
|
||||
.pSpecializationInfo = NULL
|
||||
}
|
||||
};
|
||||
|
||||
/* We use instanced rendering to clear multiple render targets. We have two
|
||||
* vertex buffers: the first vertex buffer holds per-vertex data and
|
||||
* provides the vertices for the clear rectangle. The second one holds
|
||||
* per-instance data, which consists of the VUE header (which selects the
|
||||
* layer) and the color (Vulkan supports per-RT clear colors).
|
||||
*/
|
||||
VkPipelineVertexInputCreateInfo vi_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO,
|
||||
.pNext = &fs_create_info,
|
||||
.bindingCount = 2,
|
||||
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
|
||||
{
|
||||
.binding = 0,
|
||||
.strideInBytes = 8,
|
||||
.stepRate = VK_VERTEX_INPUT_STEP_RATE_VERTEX
|
||||
},
|
||||
{
|
||||
.binding = 1,
|
||||
.strideInBytes = 32,
|
||||
.stepRate = VK_VERTEX_INPUT_STEP_RATE_INSTANCE
|
||||
},
|
||||
},
|
||||
.attributeCount = 3,
|
||||
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
|
||||
{
|
||||
/* VUE Header */
|
||||
.location = 0,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_UINT,
|
||||
.offsetInBytes = 0
|
||||
},
|
||||
{
|
||||
/* Position */
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
.offsetInBytes = 0
|
||||
},
|
||||
{
|
||||
/* Color */
|
||||
.location = 2,
|
||||
.binding = 1,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offsetInBytes = 16
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VkPipelineRsStateCreateInfo rs_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO,
|
||||
.pNext = &vi_create_info,
|
||||
.depthClipEnable = true,
|
||||
.rasterizerDiscardEnable = false,
|
||||
.fillMode = VK_FILL_MODE_SOLID,
|
||||
.cullMode = VK_CULL_MODE_NONE,
|
||||
.frontFace = VK_FRONT_FACE_CCW
|
||||
};
|
||||
|
||||
anv_pipeline_create((VkDevice) device,
|
||||
&(VkGraphicsPipelineCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.pNext = &rs_create_info,
|
||||
.flags = 0,
|
||||
.layout = 0
|
||||
},
|
||||
&(struct anv_pipeline_create_info) {
|
||||
.use_repclear = true,
|
||||
.disable_viewport = true,
|
||||
.use_rectlist = true
|
||||
},
|
||||
&device->clear_state.pipeline);
|
||||
|
||||
vkDestroyObject((VkDevice) device, VK_OBJECT_TYPE_SHADER, fs);
|
||||
|
||||
vkCreateDynamicRasterState((VkDevice) device,
|
||||
&(VkDynamicRsStateCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DYNAMIC_RS_STATE_CREATE_INFO,
|
||||
},
|
||||
&device->clear_state.rs_state);
|
||||
}
|
||||
|
||||
struct anv_saved_state {
|
||||
struct {
|
||||
struct anv_buffer *buffer;
|
||||
VkDeviceSize offset;
|
||||
} vb[2];
|
||||
struct anv_pipeline *pipeline;
|
||||
};
|
||||
|
||||
static void
|
||||
anv_cmd_buffer_save(struct anv_cmd_buffer *cmd_buffer, struct anv_saved_state *state)
|
||||
{
|
||||
memcpy(state->vb, cmd_buffer->vb, sizeof(state->vb));
|
||||
state->pipeline = cmd_buffer->pipeline;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_cmd_buffer_restore(struct anv_cmd_buffer *cmd_buffer, struct anv_saved_state *state)
|
||||
{
|
||||
memcpy(cmd_buffer->vb, state->vb, sizeof(state->vb));
|
||||
cmd_buffer->pipeline = state->pipeline;
|
||||
|
||||
cmd_buffer->vb_dirty |= (1 << ARRAY_SIZE(state->vb)) - 1;
|
||||
cmd_buffer->dirty |= ANV_CMD_BUFFER_PIPELINE_DIRTY;
|
||||
}
|
||||
|
||||
void
|
||||
anv_cmd_buffer_clear(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_render_pass *pass)
|
||||
{
|
||||
struct anv_device *device = cmd_buffer->device;
|
||||
struct anv_framebuffer *fb = cmd_buffer->framebuffer;
|
||||
struct anv_saved_state saved_state;
|
||||
struct anv_state state;
|
||||
uint32_t size;
|
||||
|
||||
struct instance_data {
|
||||
struct {
|
||||
uint32_t Reserved;
|
||||
uint32_t RTAIndex;
|
||||
uint32_t ViewportIndex;
|
||||
float PointWidth;
|
||||
} vue_header;
|
||||
float color[4];
|
||||
} *instance_data;
|
||||
|
||||
const float vertex_data[] = {
|
||||
/* Rect-list coordinates */
|
||||
0.0, 0.0,
|
||||
fb->width, 0.0,
|
||||
fb->width, fb->height,
|
||||
|
||||
/* Align to 16 bytes */
|
||||
0.0, 0.0,
|
||||
};
|
||||
|
||||
size = sizeof(vertex_data) + pass->num_clear_layers * sizeof(instance_data[0]);
|
||||
state = anv_state_stream_alloc(&cmd_buffer->surface_state_stream, size, 16);
|
||||
|
||||
memcpy(state.map, vertex_data, sizeof(vertex_data));
|
||||
instance_data = state.map + sizeof(vertex_data);
|
||||
|
||||
for (uint32_t i = 0; i < pass->num_layers; i++) {
|
||||
if (pass->layers[i].color_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
||||
*instance_data++ = (struct instance_data) {
|
||||
.vue_header = {
|
||||
.RTAIndex = i,
|
||||
.ViewportIndex = 0,
|
||||
.PointWidth = 0.0
|
||||
},
|
||||
.color = {
|
||||
pass->layers[i].clear_color.color.floatColor[0],
|
||||
pass->layers[i].clear_color.color.floatColor[1],
|
||||
pass->layers[i].clear_color.color.floatColor[2],
|
||||
pass->layers[i].clear_color.color.floatColor[3],
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
struct anv_buffer vertex_buffer = {
|
||||
.device = cmd_buffer->device,
|
||||
.size = size,
|
||||
.bo = &device->surface_state_block_pool.bo,
|
||||
.offset = state.offset
|
||||
};
|
||||
|
||||
anv_cmd_buffer_save(cmd_buffer, &saved_state);
|
||||
|
||||
vkCmdBindVertexBuffers((VkCmdBuffer) cmd_buffer, 0, 2,
|
||||
(VkBuffer[]) {
|
||||
(VkBuffer) &vertex_buffer,
|
||||
(VkBuffer) &vertex_buffer
|
||||
},
|
||||
(VkDeviceSize[]) {
|
||||
0,
|
||||
sizeof(vertex_data)
|
||||
});
|
||||
|
||||
if ((VkPipeline) cmd_buffer->pipeline != device->clear_state.pipeline)
|
||||
vkCmdBindPipeline((VkCmdBuffer) cmd_buffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS, device->clear_state.pipeline);
|
||||
|
||||
/* We don't need anything here, only set if not already set. */
|
||||
if (cmd_buffer->rs_state == NULL)
|
||||
vkCmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
|
||||
VK_STATE_BIND_POINT_RASTER,
|
||||
device->clear_state.rs_state);
|
||||
|
||||
if (cmd_buffer->vp_state == NULL)
|
||||
vkCmdBindDynamicStateObject((VkCmdBuffer) cmd_buffer,
|
||||
VK_STATE_BIND_POINT_VIEWPORT,
|
||||
cmd_buffer->framebuffer->vp_state);
|
||||
|
||||
vkCmdDraw((VkCmdBuffer) cmd_buffer, 0, 3, 0, pass->num_clear_layers);
|
||||
|
||||
/* Restore API state */
|
||||
anv_cmd_buffer_restore(cmd_buffer, &saved_state);
|
||||
|
||||
}
|
||||
|
||||
void VKAPI vkCmdCopyBuffer(
|
||||
VkCmdBuffer cmdBuffer,
|
||||
VkBuffer srcBuffer,
|
||||
|
@@ -245,6 +245,11 @@ struct anv_instance {
|
||||
struct anv_physical_device physicalDevice;
|
||||
};
|
||||
|
||||
struct anv_clear_state {
|
||||
VkPipeline pipeline;
|
||||
VkDynamicRsState rs_state;
|
||||
};
|
||||
|
||||
struct anv_device {
|
||||
struct anv_instance * instance;
|
||||
uint32_t chipset_id;
|
||||
@@ -261,6 +266,8 @@ struct anv_device {
|
||||
struct anv_block_pool surface_state_block_pool;
|
||||
struct anv_state_pool surface_state_pool;
|
||||
|
||||
struct anv_clear_state clear_state;
|
||||
|
||||
struct anv_compiler * compiler;
|
||||
struct anv_aub_writer * aub_writer;
|
||||
pthread_mutex_t mutex;
|
||||
@@ -486,6 +493,7 @@ struct anv_cmd_buffer {
|
||||
struct anv_pipeline * pipeline;
|
||||
struct anv_framebuffer * framebuffer;
|
||||
struct anv_dynamic_rs_state * rs_state;
|
||||
struct anv_dynamic_vp_state * vp_state;
|
||||
};
|
||||
|
||||
void anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer);
|
||||
@@ -604,12 +612,30 @@ struct anv_framebuffer {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t layers;
|
||||
|
||||
/* Viewport for clears */
|
||||
VkDynamicVpState vp_state;
|
||||
};
|
||||
|
||||
struct anv_render_pass_layer {
|
||||
VkAttachmentLoadOp color_load_op;
|
||||
VkClearColor clear_color;
|
||||
};
|
||||
|
||||
struct anv_render_pass {
|
||||
VkRect render_area;
|
||||
|
||||
uint32_t num_clear_layers;
|
||||
uint32_t num_layers;
|
||||
struct anv_render_pass_layer layers[0];
|
||||
};
|
||||
|
||||
void anv_device_init_meta(struct anv_device *device);
|
||||
|
||||
void
|
||||
anv_cmd_buffer_clear(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_render_pass *pass);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Reference in New Issue
Block a user