static void
build_color_shaders(struct nir_shader **out_vs,
- struct nir_shader **out_fs)
+ struct nir_shader **out_fs,
+ uint32_t frag_output)
{
nir_builder vs_b;
nir_builder fs_b;
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;
+ fs_out_color->data.location = FRAG_RESULT_DATA0 + frag_output;
nir_copy_var(&vs_b, vs_out_pos, vs_in_pos);
nir_copy_var(&vs_b, vs_out_color, vs_in_color);
const VkPipelineDepthStencilStateCreateInfo *ds_state,
const VkPipelineColorBlendStateCreateInfo *cb_state,
const VkAllocationCallbacks *alloc,
+ bool use_repclear,
struct anv_pipeline **pipeline)
{
VkDevice device_h = anv_device_to_handle(device);
},
&(struct anv_graphics_pipeline_create_info) {
.color_attachment_count = MAX_RTS,
- .use_repclear = true,
+ .use_repclear = use_repclear,
.disable_viewport = true,
.disable_vs = true,
.use_rectlist = true
}
static VkResult
-init_color_pipeline(struct anv_device *device)
+create_color_pipeline(struct anv_device *device, uint32_t frag_output,
+ struct anv_pipeline **pipeline)
{
struct nir_shader *vs_nir;
struct nir_shader *fs_nir;
- build_color_shaders(&vs_nir, &fs_nir);
+ build_color_shaders(&vs_nir, &fs_nir, frag_output);
const VkPipelineVertexInputStateCreateInfo vi_state = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
},
};
+ /* Disable repclear because we do not want the compiler to replace the
+ * shader. We need the shader to write to the specified color attachment,
+ * but the repclear shader writes to all color attachments.
+ */
return
create_pipeline(device, vs_nir, fs_nir, &vi_state, &ds_state,
- &cb_state, NULL,
- &device->meta_state.clear.color_pipeline);
+ &cb_state, NULL, /*use_repclear*/ false,
+ pipeline);
+}
+
+static VkResult
+init_color_pipelines(struct anv_device *device)
+{
+ VkResult result;
+ struct anv_pipeline **pipelines = device->meta_state.clear.color_pipelines;
+ uint32_t n = ARRAY_SIZE(device->meta_state.clear.color_pipelines);
+
+ zero(device->meta_state.clear.color_pipelines);
+
+ for (uint32_t i = 0; i < n; ++i) {
+ result = create_color_pipeline(device, i, &pipelines[i]);
+ if (result < 0)
+ goto fail;
+ }
+
+ return VK_SUCCESS;
+
+fail:
+ for (uint32_t i = 0; i < n; ++i) {
+ if (pipelines[i] == NULL)
+ break;
+
+ anv_DestroyPipeline(anv_device_to_handle(device),
+ anv_pipeline_to_handle(pipelines[i]),
+ NULL);
+ }
+
+ return result;
}
static void
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);
+ struct anv_pipeline *pipeline = device->meta_state.clear.color_pipelines[0];
+ VkPipeline pipeline_h = anv_pipeline_to_handle(pipeline);
const struct color_clear_vattrs vertex_data[3] = {
{
(VkBuffer[]) { anv_buffer_to_handle(&vertex_buffer) },
(VkDeviceSize[]) { 0 });
- if (cmd_buffer->state.pipeline != device->meta_state.clear.color_pipeline) {
+ if (cmd_buffer->state.pipeline != pipeline) {
ANV_CALL(CmdBindPipeline)(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline_h);
}
};
return create_pipeline(device, vs_nir, fs_nir, &vi_state, &ds_state,
- &cb_state, NULL, pipeline);
+ &cb_state, NULL, /*use_repclear*/ true, pipeline);
}
static void
{
VkResult result;
- result = init_color_pipeline(device);
+ result = init_color_pipelines(device);
if (result != VK_SUCCESS)
- goto fail;
+ return result;
result = init_depthstencil_pipelines(device);
if (result != VK_SUCCESS)
- goto fail_color_pipeline;
+ return result;
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
{
VkDevice device_h = anv_device_to_handle(device);
- ANV_CALL(DestroyPipeline)(device_h,
- anv_pipeline_to_handle(device->meta_state.clear.color_pipeline),
- NULL);
+ for (uint32_t i = 0;
+ i < ARRAY_SIZE(device->meta_state.clear.color_pipelines); ++i) {
+ ANV_CALL(DestroyPipeline)(device_h,
+ anv_pipeline_to_handle(device->meta_state.clear.color_pipelines[i]),
+ NULL);
+ }
+
ANV_CALL(DestroyPipeline)(device_h,
anv_pipeline_to_handle(device->meta_state.clear.depth_only_pipeline),
NULL);