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);
|
pthread_mutex_init(&device->mutex, NULL);
|
||||||
|
|
||||||
|
anv_device_init_meta(device);
|
||||||
|
|
||||||
*pDevice = (VkDevice) device;
|
*pDevice = (VkDevice) device;
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
@@ -1739,7 +1741,9 @@ VkResult VKAPI vkCreateCommandBuffer(
|
|||||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||||
|
|
||||||
cmd_buffer->device = device;
|
cmd_buffer->device = device;
|
||||||
|
cmd_buffer->rs_state = NULL;
|
||||||
|
cmd_buffer->vp_state = NULL;
|
||||||
|
|
||||||
result = anv_batch_init(&cmd_buffer->batch, device);
|
result = anv_batch_init(&cmd_buffer->batch, device);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -2008,7 +2012,9 @@ void VKAPI vkCmdBindDynamicStateObject(
|
|||||||
switch (stateBindPoint) {
|
switch (stateBindPoint) {
|
||||||
case VK_STATE_BIND_POINT_VIEWPORT:
|
case VK_STATE_BIND_POINT_VIEWPORT:
|
||||||
vp_state = (struct anv_dynamic_vp_state *) dynamicState;
|
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,
|
anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_SCISSOR_STATE_POINTERS,
|
||||||
.ScissorRectPointer = vp_state->scissor.offset);
|
.ScissorRectPointer = vp_state->scissor.offset);
|
||||||
anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_VIEWPORT_STATE_POINTERS_CC,
|
anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_VIEWPORT_STATE_POINTERS_CC,
|
||||||
@@ -2571,6 +2577,27 @@ VkResult VKAPI vkCreateFramebuffer(
|
|||||||
framebuffer->height = pCreateInfo->height;
|
framebuffer->height = pCreateInfo->height;
|
||||||
framebuffer->layers = pCreateInfo->layers;
|
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;
|
*pFramebuffer = (VkFramebuffer) framebuffer;
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
@@ -2583,16 +2610,29 @@ VkResult VKAPI vkCreateRenderPass(
|
|||||||
{
|
{
|
||||||
struct anv_device *device = (struct anv_device *) _device;
|
struct anv_device *device = (struct anv_device *) _device;
|
||||||
struct anv_render_pass *pass;
|
struct anv_render_pass *pass;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO);
|
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);
|
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
|
||||||
if (pass == NULL)
|
if (pass == NULL)
|
||||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||||
|
|
||||||
pass->render_area = pCreateInfo->renderArea;
|
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;
|
*pRenderPass = (VkRenderPass) pass;
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
@@ -2617,6 +2657,8 @@ void VKAPI vkCmdBeginRenderPass(
|
|||||||
pass->render_area.offset.x + pass->render_area.extent.width - 1,
|
pass->render_area.offset.x + pass->render_area.extent.width - 1,
|
||||||
.DrawingRectangleOriginY = 0,
|
.DrawingRectangleOriginY = 0,
|
||||||
.DrawingRectangleOriginX = 0);
|
.DrawingRectangleOriginX = 0);
|
||||||
|
|
||||||
|
anv_cmd_buffer_clear(cmd_buffer, pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKAPI vkCmdEndRenderPass(
|
void VKAPI vkCmdEndRenderPass(
|
||||||
|
@@ -29,6 +29,253 @@
|
|||||||
|
|
||||||
#include "private.h"
|
#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(
|
void VKAPI vkCmdCopyBuffer(
|
||||||
VkCmdBuffer cmdBuffer,
|
VkCmdBuffer cmdBuffer,
|
||||||
VkBuffer srcBuffer,
|
VkBuffer srcBuffer,
|
||||||
|
@@ -245,6 +245,11 @@ struct anv_instance {
|
|||||||
struct anv_physical_device physicalDevice;
|
struct anv_physical_device physicalDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct anv_clear_state {
|
||||||
|
VkPipeline pipeline;
|
||||||
|
VkDynamicRsState rs_state;
|
||||||
|
};
|
||||||
|
|
||||||
struct anv_device {
|
struct anv_device {
|
||||||
struct anv_instance * instance;
|
struct anv_instance * instance;
|
||||||
uint32_t chipset_id;
|
uint32_t chipset_id;
|
||||||
@@ -261,6 +266,8 @@ struct anv_device {
|
|||||||
struct anv_block_pool surface_state_block_pool;
|
struct anv_block_pool surface_state_block_pool;
|
||||||
struct anv_state_pool surface_state_pool;
|
struct anv_state_pool surface_state_pool;
|
||||||
|
|
||||||
|
struct anv_clear_state clear_state;
|
||||||
|
|
||||||
struct anv_compiler * compiler;
|
struct anv_compiler * compiler;
|
||||||
struct anv_aub_writer * aub_writer;
|
struct anv_aub_writer * aub_writer;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
@@ -486,6 +493,7 @@ struct anv_cmd_buffer {
|
|||||||
struct anv_pipeline * pipeline;
|
struct anv_pipeline * pipeline;
|
||||||
struct anv_framebuffer * framebuffer;
|
struct anv_framebuffer * framebuffer;
|
||||||
struct anv_dynamic_rs_state * rs_state;
|
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);
|
void anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer);
|
||||||
@@ -604,12 +612,30 @@ struct anv_framebuffer {
|
|||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint32_t layers;
|
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 {
|
struct anv_render_pass {
|
||||||
VkRect render_area;
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user