blob: 0469c57dabf080a30fd7ffc14e02e8ba6038d3c1 [file] [log] [blame]
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "anv_meta.h"
#include "anv_meta_clear.h"
#include "anv_private.h"
#include "glsl/nir/nir_builder.h"
/** Vertex attributes for color clears. */
struct color_clear_vattrs {
struct anv_vue_header vue_header;
float position[2]; /**< 3DPRIM_RECTLIST */
VkClearColorValue color;
};
/** Vertex attributes for depthstencil clears. */
struct depthstencil_clear_vattrs {
struct anv_vue_header vue_header;
float position[2]; /*<< 3DPRIM_RECTLIST */
};
static void
meta_clear_begin(struct anv_meta_saved_state *saved_state,
struct anv_cmd_buffer *cmd_buffer)
{
anv_meta_save(saved_state, cmd_buffer,
(1 << VK_DYNAMIC_STATE_VIEWPORT) |
(1 << VK_DYNAMIC_STATE_SCISSOR) |
(1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE));
cmd_buffer->state.dynamic.viewport.count = 0;
cmd_buffer->state.dynamic.scissor.count = 0;
}
static void
meta_clear_end(struct anv_meta_saved_state *saved_state,
struct anv_cmd_buffer *cmd_buffer)
{
anv_meta_restore(saved_state, cmd_buffer);
}
static void
build_color_shaders(struct nir_shader **out_vs,
struct nir_shader **out_fs)
{
nir_builder vs_b;
nir_builder fs_b;
nir_builder_init_simple_shader(&vs_b, NULL, MESA_SHADER_VERTEX, NULL);
nir_builder_init_simple_shader(&fs_b, NULL, MESA_SHADER_FRAGMENT, NULL);
const struct glsl_type *position_type = glsl_vec4_type();
const struct glsl_type *color_type = glsl_vec4_type();
nir_variable *vs_in_pos =
nir_variable_create(vs_b.shader, nir_var_shader_in, position_type,
"a_position");
vs_in_pos->data.location = VERT_ATTRIB_GENERIC0;
nir_variable *vs_out_pos =
nir_variable_create(vs_b.shader, nir_var_shader_out, position_type,
"gl_Position");
vs_out_pos->data.location = VARYING_SLOT_POS;
nir_variable *vs_in_color =
nir_variable_create(vs_b.shader, nir_var_shader_in, color_type,
"a_color");
vs_in_color->data.location = VERT_ATTRIB_GENERIC1;
nir_variable *vs_out_color =
nir_variable_create(vs_b.shader, nir_var_shader_out, color_type,
"v_color");
vs_out_color->data.location = VARYING_SLOT_VAR0;
vs_out_color->data.interpolation = INTERP_QUALIFIER_FLAT;
nir_variable *fs_in_color =
nir_variable_create(fs_b.shader, nir_var_shader_in, color_type,
"v_color");
fs_in_color->data.location = vs_out_color->data.location;
fs_in_color->data.interpolation = vs_out_color->data.interpolation;
nir_variable *fs_out_color =
nir_variable_create(fs_b.shader, nir_var_shader_out, color_type,
"f_color");
fs_out_color->data.location = FRAG_RESULT_DATA0;
nir_copy_var(&vs_b, vs_out_pos, vs_in_pos);
nir_copy_var(&vs_b, vs_out_color, vs_in_color);
nir_copy_var(&fs_b, fs_out_color, fs_in_color);
*out_vs = vs_b.shader;
*out_fs = fs_b.shader;
}
static VkResult
create_pipeline(struct anv_device *device,
struct nir_shader *vs_nir,
struct nir_shader *fs_nir,
const VkPipelineVertexInputStateCreateInfo *vi_state,
const VkPipelineDepthStencilStateCreateInfo *ds_state,
const VkPipelineColorBlendStateCreateInfo *cb_state,
const VkAllocationCallbacks *alloc,
struct anv_pipeline **pipeline)
{
VkDevice device_h = anv_device_to_handle(device);
VkResult result;
struct anv_shader_module vs_m = { .nir = vs_nir };
struct anv_shader_module fs_m = { .nir = fs_nir };
VkPipeline pipeline_h;
result = anv_graphics_pipeline_create(device_h,
VK_NULL_HANDLE,
&(VkGraphicsPipelineCreateInfo) {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.stageCount = 2,
.pStages = (VkPipelineShaderStageCreateInfo[]) {
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = anv_shader_module_to_handle(&vs_m),
.pName = "main",
},
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = anv_shader_module_to_handle(&fs_m),
.pName = "main",
},
},
.pVertexInputState = vi_state,
.pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
.primitiveRestartEnable = false,
},
.pViewportState = &(VkPipelineViewportStateCreateInfo) {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.viewportCount = 1,
.pViewports = NULL, /* dynamic */
.scissorCount = 1,
.pScissors = NULL, /* dynamic */
},
.pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.rasterizerDiscardEnable = false,
.polygonMode = VK_POLYGON_MODE_FILL,
.cullMode = VK_CULL_MODE_NONE,
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
.depthBiasEnable = false,
},
.pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) {
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.rasterizationSamples = 1, /* FINISHME: Multisampling */
.sampleShadingEnable = false,
.pSampleMask = (VkSampleMask[]) { UINT32_MAX },
.alphaToCoverageEnable = false,
.alphaToOneEnable = false,
},
.pDepthStencilState = ds_state,
.pColorBlendState = cb_state,
.pDynamicState = &(VkPipelineDynamicStateCreateInfo) {
/* The meta clear pipeline declares all state as dynamic.
* As a consequence, vkCmdBindPipeline writes no dynamic state
* to the cmd buffer. Therefore, at the end of the meta clear,
* we need only restore dynamic state was vkCmdSet.
*/
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = 9,
.pDynamicStates = (VkDynamicState[]) {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_LINE_WIDTH,
VK_DYNAMIC_STATE_DEPTH_BIAS,
VK_DYNAMIC_STATE_BLEND_CONSTANTS,
VK_DYNAMIC_STATE_DEPTH_BOUNDS,
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
},
},
.flags = 0,
.renderPass = anv_render_pass_to_handle(&anv_meta_dummy_renderpass),
.subpass = 0,
},
&(struct anv_graphics_pipeline_create_info) {
.use_repclear = true,
.disable_viewport = true,
.disable_vs = true,
.use_rectlist = true
},
alloc,
&pipeline_h);
ralloc_free(vs_nir);
ralloc_free(fs_nir);
*pipeline = anv_pipeline_from_handle(pipeline_h);
return result;
}
static VkResult
init_color_pipeline(struct anv_device *device)
{
struct nir_shader *vs_nir;
struct nir_shader *fs_nir;
build_color_shaders(&vs_nir, &fs_nir);
const VkPipelineVertexInputStateCreateInfo vi_state = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
{
.binding = 0,
.stride = sizeof(struct color_clear_vattrs),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
},
},
.vertexAttributeDescriptionCount = 3,
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
{
/* VUE Header */
.location = 0,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_UINT,
.offset = offsetof(struct color_clear_vattrs, vue_header),
},
{
/* Position */
.location = 1,
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(struct color_clear_vattrs, position),
},
{
/* Color */
.location = 2,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
.offset = offsetof(struct color_clear_vattrs, color),
},
},
};
const VkPipelineDepthStencilStateCreateInfo ds_state = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthTestEnable = false,
.depthWriteEnable = false,
.depthBoundsTestEnable = false,
.stencilTestEnable = false,
};
const VkPipelineColorBlendStateCreateInfo cb_state = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.logicOpEnable = false,
.attachmentCount = 1,
.pAttachments = (VkPipelineColorBlendAttachmentState []) {
{
.blendEnable = false,
.colorWriteMask = VK_COLOR_COMPONENT_A_BIT |
VK_COLOR_COMPONENT_R_BIT |
VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT,
},
},
};
return
create_pipeline(device, vs_nir, fs_nir, &vi_state, &ds_state,
&cb_state, NULL,
&device->meta_state.clear.color_pipeline);
}
static void
emit_load_color_clear(struct anv_cmd_buffer *cmd_buffer,
uint32_t attachment,
VkClearColorValue clear_value)
{
struct anv_device *device = cmd_buffer->device;
VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer);
const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
VkPipeline pipeline_h =
anv_pipeline_to_handle(device->meta_state.clear.color_pipeline);
const struct color_clear_vattrs vertex_data[3] = {
{
.vue_header = { 0 },
.position = { 0.0, 0.0 },
.color = clear_value,
},
{
.vue_header = { 0 },
.position = { fb->width, 0.0 },
.color = clear_value,
},
{
.vue_header = { 0 },
.position = { fb->width, fb->height },
.color = clear_value,
},
};
struct anv_state state =
anv_cmd_buffer_emit_dynamic(cmd_buffer, vertex_data, sizeof(vertex_data), 16);
struct anv_buffer vertex_buffer = {
.device = device,
.size = sizeof(vertex_data),
.bo = &device->dynamic_state_block_pool.bo,
.offset = state.offset,
};
anv_cmd_buffer_begin_subpass(cmd_buffer,
&(struct anv_subpass) {
.color_count = 1,
.color_attachments = (uint32_t[]) { attachment },
.depth_stencil_attachment = VK_ATTACHMENT_UNUSED,
});
ANV_CALL(CmdSetViewport)(cmd_buffer_h, 0, 1,
(VkViewport[]) {
{
.x = 0,
.y = 0,
.width = fb->width,
.height = fb->height,
.minDepth = 0.0,
.maxDepth = 1.0,
},
});
ANV_CALL(CmdSetScissor)(cmd_buffer_h, 0, 1,
(VkRect2D[]) {
{
.offset = { 0, 0 },
.extent = { fb->width, fb->height },
}
});
ANV_CALL(CmdBindVertexBuffers)(cmd_buffer_h, 0, 1,
(VkBuffer[]) { anv_buffer_to_handle(&vertex_buffer) },
(VkDeviceSize[]) { 0 });
if (cmd_buffer->state.pipeline != device->meta_state.clear.color_pipeline) {
ANV_CALL(CmdBindPipeline)(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline_h);
}
ANV_CALL(CmdDraw)(cmd_buffer_h, 3, 1, 0, 0);
}
static void
build_depthstencil_shaders(struct nir_shader **out_vs,
struct nir_shader **out_fs)
{
nir_builder vs_b;
nir_builder fs_b;
nir_builder_init_simple_shader(&vs_b, NULL, MESA_SHADER_VERTEX, NULL);
nir_builder_init_simple_shader(&fs_b, NULL, MESA_SHADER_FRAGMENT, NULL);
const struct glsl_type *position_type = glsl_vec4_type();
nir_variable *vs_in_pos =
nir_variable_create(vs_b.shader, nir_var_shader_in, position_type,
"a_position");
vs_in_pos->data.location = VERT_ATTRIB_GENERIC0;
nir_variable *vs_out_pos =
nir_variable_create(vs_b.shader, nir_var_shader_out, position_type,
"gl_Position");
vs_out_pos->data.location = VARYING_SLOT_POS;
nir_copy_var(&vs_b, vs_out_pos, vs_in_pos);
*out_vs = vs_b.shader;
*out_fs = fs_b.shader;
}
static VkResult
create_depthstencil_pipeline(struct anv_device *device,
VkImageAspectFlags aspects,
struct anv_pipeline **pipeline)
{
struct nir_shader *vs_nir;
struct nir_shader *fs_nir;
build_depthstencil_shaders(&vs_nir, &fs_nir);
const VkPipelineVertexInputStateCreateInfo vi_state = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.vertexBindingDescriptionCount = 1,
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[]) {
{
.binding = 0,
.stride = sizeof(struct depthstencil_clear_vattrs),
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
},
},
.vertexAttributeDescriptionCount = 2,
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]) {
{
/* VUE Header */
.location = 0,
.binding = 0,
.format = VK_FORMAT_R32G32B32A32_UINT,
.offset = offsetof(struct depthstencil_clear_vattrs, vue_header),
},
{
/* Position */
.location = 1,
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(struct depthstencil_clear_vattrs, position),
},
},
};
const VkPipelineDepthStencilStateCreateInfo ds_state = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.depthTestEnable = (aspects & VK_IMAGE_ASPECT_DEPTH_BIT),
.depthCompareOp = VK_COMPARE_OP_ALWAYS,
.depthWriteEnable = (aspects & VK_IMAGE_ASPECT_DEPTH_BIT),
.depthBoundsTestEnable = false,
.stencilTestEnable = (aspects & VK_IMAGE_ASPECT_STENCIL_BIT),
.front = {
.passOp = VK_STENCIL_OP_REPLACE,
.compareOp = VK_COMPARE_OP_ALWAYS,
.writeMask = UINT32_MAX,
.reference = 0, /* dynamic */
},
.back = { 0 /* dont care */ },
};
const VkPipelineColorBlendStateCreateInfo cb_state = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.logicOpEnable = false,
.attachmentCount = 0,
.pAttachments = NULL,
};
return create_pipeline(device, vs_nir, fs_nir, &vi_state, &ds_state,
&cb_state, NULL, pipeline);
}
static void
emit_load_depthstencil_clear(struct anv_cmd_buffer *cmd_buffer,
uint32_t attachment,
VkImageAspectFlags aspects,
VkClearDepthStencilValue clear_value)
{
struct anv_device *device = cmd_buffer->device;
VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer);
const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
const struct depthstencil_clear_vattrs vertex_data[3] = {
{
.vue_header = { 0 },
.position = { 0.0, 0.0 },
},
{
.vue_header = { 0 },
.position = { fb->width, 0.0 },
},
{
.vue_header = { 0 },
.position = { fb->width, fb->height },
},
};
struct anv_state state =
anv_cmd_buffer_emit_dynamic(cmd_buffer, vertex_data, sizeof(vertex_data), 16);
struct anv_buffer vertex_buffer = {
.device = device,
.size = sizeof(vertex_data),
.bo = &device->dynamic_state_block_pool.bo,
.offset = state.offset,
};
anv_cmd_buffer_begin_subpass(cmd_buffer,
&(struct anv_subpass) {
.color_count = 0,
.depth_stencil_attachment = attachment,
});
ANV_CALL(CmdSetViewport)(cmd_buffer_h, 0, 1,
(VkViewport[]) {
{
.x = 0,
.y = 0,
.width = fb->width,
.height = fb->height,
/* Ignored when clearing only stencil. */
.minDepth = clear_value.depth,
.maxDepth = clear_value.depth,
},
});
ANV_CALL(CmdSetScissor)(cmd_buffer_h, 0, 1,
(VkRect2D[]) {
{
.offset = { 0, 0 },
.extent = { fb->width, fb->height },
}
});
if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
ANV_CALL(CmdSetStencilReference)(cmd_buffer_h, VK_STENCIL_FACE_FRONT_BIT,
clear_value.stencil);
}
ANV_CALL(CmdBindVertexBuffers)(cmd_buffer_h, 0, 1,
(VkBuffer[]) { anv_buffer_to_handle(&vertex_buffer) },
(VkDeviceSize[]) { 0 });
struct anv_pipeline *pipeline;
switch (aspects) {
case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
pipeline = device->meta_state.clear.depthstencil_pipeline;
break;
case VK_IMAGE_ASPECT_DEPTH_BIT:
pipeline = device->meta_state.clear.depth_only_pipeline;
break;
case VK_IMAGE_ASPECT_STENCIL_BIT:
pipeline = device->meta_state.clear.stencil_only_pipeline;
break;
default:
unreachable("expected depth or stencil aspect");
}
if (cmd_buffer->state.pipeline != pipeline) {
ANV_CALL(CmdBindPipeline)(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
anv_pipeline_to_handle(pipeline));
}
ANV_CALL(CmdDraw)(cmd_buffer_h, 3, 1, 0, 0);
}
static VkResult
init_depthstencil_pipelines(struct anv_device *device)
{
VkResult result;
struct anv_meta_state *state = &device->meta_state;
result =
create_depthstencil_pipeline(device, VK_IMAGE_ASPECT_DEPTH_BIT,
&state->clear.depth_only_pipeline);
if (result != VK_SUCCESS)
goto fail;
result =
create_depthstencil_pipeline(device, VK_IMAGE_ASPECT_STENCIL_BIT,
&state->clear.stencil_only_pipeline);
if (result != VK_SUCCESS)
goto fail_depth_only;
result =
create_depthstencil_pipeline(device,
VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT,
&state->clear.depthstencil_pipeline);
if (result != VK_SUCCESS)
goto fail_stencil_only;
return result;
fail_stencil_only:
anv_DestroyPipeline(anv_device_to_handle(device),
anv_pipeline_to_handle(state->clear.stencil_only_pipeline),
NULL);
fail_depth_only:
anv_DestroyPipeline(anv_device_to_handle(device),
anv_pipeline_to_handle(state->clear.depth_only_pipeline),
NULL);
fail:
return result;
}
VkResult
anv_device_init_meta_clear_state(struct anv_device *device)
{
VkResult result;
result = init_color_pipeline(device);
if (result != VK_SUCCESS)
goto fail;
result = init_depthstencil_pipelines(device);
if (result != VK_SUCCESS)
goto fail_color_pipeline;
return VK_SUCCESS;
fail_color_pipeline:
anv_DestroyPipeline(anv_device_to_handle(device),
anv_pipeline_to_handle(device->meta_state.clear.color_pipeline),
NULL);
fail:
return result;
}
void
anv_device_finish_meta_clear_state(struct anv_device *device)
{
VkDevice device_h = anv_device_to_handle(device);
ANV_CALL(DestroyPipeline)(device_h,
anv_pipeline_to_handle(device->meta_state.clear.color_pipeline),
NULL);
ANV_CALL(DestroyPipeline)(device_h,
anv_pipeline_to_handle(device->meta_state.clear.depth_only_pipeline),
NULL);
ANV_CALL(DestroyPipeline)(device_h,
anv_pipeline_to_handle(device->meta_state.clear.stencil_only_pipeline),
NULL);
ANV_CALL(DestroyPipeline)(device_h,
anv_pipeline_to_handle(device->meta_state.clear.depthstencil_pipeline),
NULL);
}
void
anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer,
struct anv_render_pass *pass,
const VkClearValue *clear_values)
{
struct anv_meta_saved_state saved_state;
/* Figure out whether or not we actually need to clear anything to avoid
* trashing state when clearing is a no-op.
*/
bool needs_clear = false;
for (uint32_t a = 0; a < pass->attachment_count; ++a) {
struct anv_render_pass_attachment *att = &pass->attachments[a];
if (anv_format_is_color(att->format)) {
if (att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
needs_clear = true;
break;
}
} else {
if ((att->format->depth_format &&
att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) ||
(att->format->has_stencil &&
att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)) {
needs_clear = true;
break;
}
}
}
if (!needs_clear)
return;
meta_clear_begin(&saved_state, cmd_buffer);
for (uint32_t a = 0; a < pass->attachment_count; ++a) {
struct anv_render_pass_attachment *att = &pass->attachments[a];
if (anv_format_is_color(att->format)) {
if (att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
emit_load_color_clear(cmd_buffer, a, clear_values[a].color);
}
} else {
VkImageAspectFlags clear_aspects = 0;
if (att->format->depth_format &&
att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
clear_aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
if (att->format->has_stencil &&
att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
clear_aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
if (clear_aspects) {
emit_load_depthstencil_clear(cmd_buffer, a, clear_aspects,
clear_values[a].depthStencil);
}
}
}
meta_clear_end(&saved_state, cmd_buffer);
}
void anv_CmdClearColorImage(
VkCommandBuffer commandBuffer,
VkImage _image,
VkImageLayout imageLayout,
const VkClearColorValue* pColor,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_image, image, _image);
struct anv_meta_saved_state saved_state;
meta_clear_begin(&saved_state, cmd_buffer);
for (uint32_t r = 0; r < rangeCount; r++) {
for (uint32_t l = 0; l < pRanges[r].levelCount; l++) {
for (uint32_t s = 0; s < pRanges[r].layerCount; s++) {
struct anv_image_view iview;
anv_image_view_init(&iview, cmd_buffer->device,
&(VkImageViewCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = _image,
.viewType = anv_meta_get_view_type(image),
.format = image->vk_format,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = pRanges[r].baseMipLevel + l,
.levelCount = 1,
.baseArrayLayer = pRanges[r].baseArrayLayer + s,
.layerCount = 1
},
},
cmd_buffer);
VkFramebuffer fb;
anv_CreateFramebuffer(anv_device_to_handle(cmd_buffer->device),
&(VkFramebufferCreateInfo) {
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.attachmentCount = 1,
.pAttachments = (VkImageView[]) {
anv_image_view_to_handle(&iview),
},
.width = iview.extent.width,
.height = iview.extent.height,
.layers = 1
}, &cmd_buffer->pool->alloc, &fb);
VkRenderPass pass;
anv_CreateRenderPass(anv_device_to_handle(cmd_buffer->device),
&(VkRenderPassCreateInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
.attachmentCount = 1,
.pAttachments = &(VkAttachmentDescription) {
.format = iview.vk_format,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.initialLayout = VK_IMAGE_LAYOUT_GENERAL,
.finalLayout = VK_IMAGE_LAYOUT_GENERAL,
},
.subpassCount = 1,
.pSubpasses = &(VkSubpassDescription) {
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.inputAttachmentCount = 0,
.colorAttachmentCount = 1,
.pColorAttachments = &(VkAttachmentReference) {
.attachment = 0,
.layout = VK_IMAGE_LAYOUT_GENERAL,
},
.pResolveAttachments = NULL,
.pDepthStencilAttachment = &(VkAttachmentReference) {
.attachment = VK_ATTACHMENT_UNUSED,
.layout = VK_IMAGE_LAYOUT_GENERAL,
},
.preserveAttachmentCount = 1,
.pPreserveAttachments = (uint32_t[]) { 0 },
},
.dependencyCount = 0,
}, &cmd_buffer->pool->alloc, &pass);
ANV_CALL(CmdBeginRenderPass)(anv_cmd_buffer_to_handle(cmd_buffer),
&(VkRenderPassBeginInfo) {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
.renderArea = {
.offset = { 0, 0, },
.extent = {
.width = iview.extent.width,
.height = iview.extent.height,
},
},
.renderPass = pass,
.framebuffer = fb,
.clearValueCount = 1,
.pClearValues = (VkClearValue[]) {
{ .color = *pColor },
},
}, VK_SUBPASS_CONTENTS_INLINE);
ANV_CALL(CmdEndRenderPass)(anv_cmd_buffer_to_handle(cmd_buffer));
/* XXX: We're leaking the render pass and framebuffer */
}
}
}
meta_clear_end(&saved_state, cmd_buffer);
}
void anv_CmdClearDepthStencilImage(
VkCommandBuffer commandBuffer,
VkImage image,
VkImageLayout imageLayout,
const VkClearDepthStencilValue* pDepthStencil,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges)
{
stub();
}
void anv_CmdClearAttachments(
VkCommandBuffer commandBuffer,
uint32_t attachmentCount,
const VkClearAttachment* pAttachments,
uint32_t rectCount,
const VkClearRect* pRects)
{
stub();
}