blob: 819b35125b4dbae4682ed03450e3e10cbb9ef256 [file] [log] [blame]
Chia-I Wu525c6602014-08-27 10:22:34 +08001/*
2 * XGL
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
Chia-I Wu44e42362014-09-02 08:32:09 +080023 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
Chia-I Wu525c6602014-08-27 10:22:34 +080026 */
27
28#include "genhw/genhw.h"
29#include "img.h"
Chia-I Wu714df452015-01-01 07:55:04 +080030#include "buf.h"
Chia-I Wu525c6602014-08-27 10:22:34 +080031#include "cmd_priv.h"
32
33enum {
Chia-I Wuc45db532015-02-19 11:20:38 -070034 READ_OP = 1 << 0,
35 WRITE_OP = 1 << 1,
36 HIZ_OP = 1 << 2,
37};
38
39enum {
Chia-I Wu525c6602014-08-27 10:22:34 +080040 MEM_CACHE = 1 << 0,
41 DATA_READ_CACHE = 1 << 1,
42 DATA_WRITE_CACHE = 1 << 2,
43 RENDER_CACHE = 1 << 3,
44 SAMPLER_CACHE = 1 << 4,
45};
46
Chia-I Wuc45db532015-02-19 11:20:38 -070047static uint32_t img_get_layout_ops(const struct intel_img *img,
48 XGL_IMAGE_LAYOUT layout)
49{
50 uint32_t ops;
51
52 switch (layout) {
53 case XGL_IMAGE_LAYOUT_GENERAL:
54 ops = READ_OP | WRITE_OP;
55 break;
56 case XGL_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
57 ops = READ_OP | WRITE_OP;
58 break;
59 case XGL_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
60 ops = READ_OP | WRITE_OP | HIZ_OP;
61 break;
62 case XGL_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
63 ops = READ_OP | HIZ_OP;
64 break;
65 case XGL_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
66 ops = READ_OP;
67 break;
68 case XGL_IMAGE_LAYOUT_CLEAR_OPTIMAL:
69 ops = WRITE_OP | HIZ_OP;
70 break;
71 case XGL_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL:
72 ops = READ_OP;
73 break;
74 case XGL_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL:
75 ops = WRITE_OP;
76 break;
77 default:
78 ops = 0;
79 break;
80 }
81
82 return ops;
83}
84
Mike Stroyan55658c22014-12-04 11:08:39 +000085static uint32_t img_get_layout_caches(const struct intel_img *img,
86 XGL_IMAGE_LAYOUT layout)
Chia-I Wu525c6602014-08-27 10:22:34 +080087{
88 uint32_t caches;
89
Mike Stroyan55658c22014-12-04 11:08:39 +000090 switch (layout) {
91 case XGL_IMAGE_LAYOUT_GENERAL:
92 // General layout when image can be used for any kind of access
93 caches = MEM_CACHE | DATA_READ_CACHE | DATA_WRITE_CACHE | RENDER_CACHE | SAMPLER_CACHE;
Chia-I Wub5c1cdf2014-11-22 03:17:45 +080094 break;
Mike Stroyan55658c22014-12-04 11:08:39 +000095 case XGL_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
96 // Optimal layout when image is only used for color attachment read/write
97 caches = DATA_WRITE_CACHE | RENDER_CACHE;
Chia-I Wu525c6602014-08-27 10:22:34 +080098 break;
Mike Stroyan55658c22014-12-04 11:08:39 +000099 case XGL_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
100 // Optimal layout when image is only used for depth/stencil attachment read/write
101 caches = DATA_WRITE_CACHE | RENDER_CACHE;
Chia-I Wu525c6602014-08-27 10:22:34 +0800102 break;
Mike Stroyan55658c22014-12-04 11:08:39 +0000103 case XGL_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
104 // Optimal layout when image is used for read only depth/stencil attachment and shader access
Chia-I Wu525c6602014-08-27 10:22:34 +0800105 caches = RENDER_CACHE;
106 break;
Mike Stroyan55658c22014-12-04 11:08:39 +0000107 case XGL_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
108 // Optimal layout when image is used for read only shader access
109 caches = DATA_READ_CACHE | SAMPLER_CACHE;
110 break;
111 case XGL_IMAGE_LAYOUT_CLEAR_OPTIMAL:
112 // Optimal layout when image is used only for clear operations
113 caches = RENDER_CACHE;
114 break;
115 case XGL_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL:
116 // Optimal layout when image is used only as source of transfer operations
117 caches = MEM_CACHE | DATA_READ_CACHE | RENDER_CACHE | SAMPLER_CACHE;
118 break;
119 case XGL_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL:
120 // Optimal layout when image is used only as destination of transfer operations
121 caches = MEM_CACHE | DATA_WRITE_CACHE | RENDER_CACHE;
Chia-I Wu525c6602014-08-27 10:22:34 +0800122 break;
123 default:
124 caches = 0;
125 break;
126 }
127
128 return caches;
129}
130
Chia-I Wuc45db532015-02-19 11:20:38 -0700131static void cmd_resolve_depth(struct intel_cmd *cmd,
132 struct intel_img *img,
133 XGL_IMAGE_LAYOUT old_layout,
134 XGL_IMAGE_LAYOUT new_layout,
135 const XGL_IMAGE_SUBRESOURCE_RANGE *range)
136{
137 const uint32_t old_ops = img_get_layout_ops(img, old_layout);
138 const uint32_t new_ops = img_get_layout_ops(img, new_layout);
139
140 if (old_ops & WRITE_OP) {
141 if ((old_ops & HIZ_OP) && !(new_ops & HIZ_OP))
142 cmd_meta_ds_op(cmd, INTEL_CMD_META_DS_RESOLVE, img, range);
143 else if (!(old_ops & HIZ_OP) && (new_ops & HIZ_OP))
144 cmd_meta_ds_op(cmd, INTEL_CMD_META_DS_HIZ_RESOLVE, img, range);
145 }
146}
147
Chia-I Wub5c1cdf2014-11-22 03:17:45 +0800148static uint32_t cmd_get_flush_flags(const struct intel_cmd *cmd,
149 uint32_t old_caches,
150 uint32_t new_caches,
151 bool is_ds)
Chia-I Wu525c6602014-08-27 10:22:34 +0800152{
153 uint32_t flags = 0;
154
155 /* not dirty */
156 if (!(old_caches & (MEM_CACHE | RENDER_CACHE | DATA_WRITE_CACHE)))
157 return 0;
158
159 if ((old_caches & RENDER_CACHE) && (new_caches & ~RENDER_CACHE)) {
Chia-I Wub5c1cdf2014-11-22 03:17:45 +0800160 if (is_ds)
Chia-I Wu525c6602014-08-27 10:22:34 +0800161 flags |= GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH;
162 else
163 flags |= GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH;
164 }
165
166 if ((old_caches & DATA_WRITE_CACHE) &&
167 (new_caches & ~(DATA_READ_CACHE | DATA_WRITE_CACHE))) {
168 if (cmd_gen(cmd) >= INTEL_GEN(7))
Chia-I Wu97aa4de2015-03-05 15:43:16 -0700169 flags |= GEN7_PIPE_CONTROL_DC_FLUSH;
Chia-I Wu525c6602014-08-27 10:22:34 +0800170 }
171
172 if (new_caches & SAMPLER_CACHE)
173 flags |= GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
174
175 if ((new_caches & DATA_READ_CACHE) && old_caches != DATA_WRITE_CACHE)
176 flags |= GEN6_PIPE_CONTROL_CONSTANT_CACHE_INVALIDATE;
177
178 if (!flags)
179 return 0;
180
181 flags |= GEN6_PIPE_CONTROL_CS_STALL;
182
183 return flags;
184}
185
Mike Stroyan55658c22014-12-04 11:08:39 +0000186static void cmd_memory_barriers(struct intel_cmd *cmd,
Mark Lobodzinskid3eabd72015-01-29 14:24:14 -0600187 uint32_t flush_flags,
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600188 uint32_t memory_barrier_count,
Mark Lobodzinskid3eabd72015-01-29 14:24:14 -0600189 const void** memory_barriers)
Chia-I Wu525c6602014-08-27 10:22:34 +0800190{
Mike Stroyan55658c22014-12-04 11:08:39 +0000191 uint32_t i;
Mike Stroyan55658c22014-12-04 11:08:39 +0000192 XGL_FLAGS input_mask = 0;
193 XGL_FLAGS output_mask = 0;
Chia-I Wu525c6602014-08-27 10:22:34 +0800194
Mike Stroyan55658c22014-12-04 11:08:39 +0000195 for (i = 0; i < memory_barrier_count; i++) {
Mark Lobodzinskid3eabd72015-01-29 14:24:14 -0600196
197 const union {
198 XGL_STRUCTURE_TYPE type;
199
200 XGL_MEMORY_BARRIER mem;
201 XGL_BUFFER_MEMORY_BARRIER buf;
202 XGL_IMAGE_MEMORY_BARRIER img;
203 } *u = memory_barriers[i];
204
205 switch(u->type)
Mike Stroyan55658c22014-12-04 11:08:39 +0000206 {
207 case XGL_STRUCTURE_TYPE_MEMORY_BARRIER:
Mark Lobodzinskid3eabd72015-01-29 14:24:14 -0600208 output_mask |= u->mem.outputMask;
209 input_mask |= u->mem.inputMask;
Mike Stroyan55658c22014-12-04 11:08:39 +0000210 break;
211 case XGL_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER:
Mark Lobodzinskid3eabd72015-01-29 14:24:14 -0600212 output_mask |= u->buf.outputMask;
213 input_mask |= u->buf.inputMask;
Mike Stroyan55658c22014-12-04 11:08:39 +0000214 break;
215 case XGL_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER:
Mark Lobodzinskid3eabd72015-01-29 14:24:14 -0600216 output_mask |= u->img.outputMask;
217 input_mask |= u->img.inputMask;
Mike Stroyan55658c22014-12-04 11:08:39 +0000218 {
Mark Lobodzinskid3eabd72015-01-29 14:24:14 -0600219 struct intel_img *img = intel_img(u->img.image);
Chia-I Wuc45db532015-02-19 11:20:38 -0700220
221 cmd_resolve_depth(cmd, img, u->img.oldLayout,
222 u->img.newLayout, &u->img.subresourceRange);
223
Mike Stroyan55658c22014-12-04 11:08:39 +0000224 flush_flags |= cmd_get_flush_flags(cmd,
Mark Lobodzinskid3eabd72015-01-29 14:24:14 -0600225 img_get_layout_caches(img, u->img.oldLayout),
226 img_get_layout_caches(img, u->img.newLayout),
Jeremy Hayes2b7e88a2015-01-23 08:51:43 -0700227 icd_format_is_ds(img->layout.format));
Mike Stroyan55658c22014-12-04 11:08:39 +0000228 }
229 break;
230 default:
231 break;
232 }
Chia-I Wu525c6602014-08-27 10:22:34 +0800233 }
234
Mike Stroyan55658c22014-12-04 11:08:39 +0000235 if (output_mask & XGL_MEMORY_OUTPUT_SHADER_WRITE_BIT) {
Chia-I Wu97aa4de2015-03-05 15:43:16 -0700236 flush_flags |= GEN7_PIPE_CONTROL_DC_FLUSH;
Mike Stroyan55658c22014-12-04 11:08:39 +0000237 }
238 if (output_mask & XGL_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT) {
239 flush_flags |= GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH;
240 }
241 if (output_mask & XGL_MEMORY_OUTPUT_DEPTH_STENCIL_ATTACHMENT_BIT) {
242 flush_flags |= GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH;
243 }
244
245 /* CPU write is cache coherent, so XGL_MEMORY_OUTPUT_CPU_WRITE_BIT needs no flush. */
246 /* Meta handles flushes, so XGL_MEMORY_OUTPUT_COPY_BIT needs no flush. */
247
248 if (input_mask & (XGL_MEMORY_INPUT_SHADER_READ_BIT | XGL_MEMORY_INPUT_UNIFORM_READ_BIT)) {
249 flush_flags |= GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
250 }
251
252 if (input_mask & XGL_MEMORY_INPUT_UNIFORM_READ_BIT) {
253 flush_flags |= GEN6_PIPE_CONTROL_CONSTANT_CACHE_INVALIDATE;
254 }
255
256 if (input_mask & XGL_MEMORY_INPUT_VERTEX_ATTRIBUTE_FETCH_BIT) {
257 flush_flags |= GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE;
258 }
259
260 /* These bits have no corresponding cache invalidate operation.
261 * XGL_MEMORY_INPUT_CPU_READ_BIT
262 * XGL_MEMORY_INPUT_INDIRECT_COMMAND_BIT
263 * XGL_MEMORY_INPUT_INDEX_FETCH_BIT
264 * XGL_MEMORY_INPUT_COLOR_ATTACHMENT_BIT
265 * XGL_MEMORY_INPUT_DEPTH_STENCIL_ATTACHMENT_BIT
266 * XGL_MEMORY_INPUT_COPY_BIT
267 */
268
Chia-I Wu525c6602014-08-27 10:22:34 +0800269 cmd_batch_flush(cmd, flush_flags);
270}
271
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600272ICD_EXPORT void XGLAPI xglCmdWaitEvents(
Chia-I Wu525c6602014-08-27 10:22:34 +0800273 XGL_CMD_BUFFER cmdBuffer,
Mike Stroyan55658c22014-12-04 11:08:39 +0000274 const XGL_EVENT_WAIT_INFO* pWaitInfo)
Chia-I Wu525c6602014-08-27 10:22:34 +0800275{
276 struct intel_cmd *cmd = intel_cmd(cmdBuffer);
Chia-I Wu525c6602014-08-27 10:22:34 +0800277
Mike Stroyan55658c22014-12-04 11:08:39 +0000278 /* This hardware will always wait at XGL_WAIT_EVENT_TOP_OF_PIPE.
279 * Passing a pWaitInfo->waitEvent of XGL_WAIT_EVENT_BEFORE_FRAGMENT_PROCESSING
280 * does not change that.
281 */
Chia-I Wu525c6602014-08-27 10:22:34 +0800282
Mike Stroyan55658c22014-12-04 11:08:39 +0000283 /* Because the command buffer is serialized, reaching
284 * a pipelined wait is always after completion of prior events.
285 * pWaitInfo->pEvents need not be examined.
286 * xglCmdWaitEvents is equivalent to memory barrier part of xglCmdPipelineBarrier.
287 * cmd_memory_barriers will wait for GEN6_PIPE_CONTROL_CS_STALL and perform
288 * appropriate cache control.
289 */
290 cmd_memory_barriers(cmd,
291 GEN6_PIPE_CONTROL_CS_STALL,
Mark Lobodzinski628a8a52015-02-02 11:55:52 -0600292 pWaitInfo->memBarrierCount, pWaitInfo->ppMemBarriers);
Mike Stroyan55658c22014-12-04 11:08:39 +0000293}
294
Mark Lobodzinskie2d07a52015-01-29 08:55:56 -0600295ICD_EXPORT void XGLAPI xglCmdPipelineBarrier(
Mike Stroyan55658c22014-12-04 11:08:39 +0000296 XGL_CMD_BUFFER cmdBuffer,
297 const XGL_PIPELINE_BARRIER* pBarrier)
298{
299 struct intel_cmd *cmd = intel_cmd(cmdBuffer);
300 uint32_t pipe_control_flags = 0;
301 uint32_t i;
302
303 /* This hardware will always wait at XGL_WAIT_EVENT_TOP_OF_PIPE.
304 * Passing a pBarrier->waitEvent of XGL_WAIT_EVENT_BEFORE_FRAGMENT_PROCESSING
305 * does not change that.
306 */
307
308 /* Cache control is done with PIPE_CONTROL flags.
309 * With no GEN6_PIPE_CONTROL_CS_STALL flag set, it behaves as XGL_SET_EVENT_TOP_OF_PIPE.
310 * All other pEvents values will behave as XGL_SET_EVENT_GPU_COMMANDS_COMPLETE.
311 */
312 for (i = 0; i < pBarrier->eventCount; i++) {
313 switch(pBarrier->pEvents[i])
314 {
315 case XGL_SET_EVENT_TOP_OF_PIPE:
316 break;
317 case XGL_SET_EVENT_VERTEX_PROCESSING_COMPLETE:
318 case XGL_SET_EVENT_FRAGMENT_PROCESSING_COMPLETE:
319 case XGL_SET_EVENT_GRAPHICS_PIPELINE_COMPLETE:
320 case XGL_SET_EVENT_COMPUTE_PIPELINE_COMPLETE:
321 case XGL_SET_EVENT_TRANSFER_COMPLETE:
322 case XGL_SET_EVENT_GPU_COMMANDS_COMPLETE:
323 pipe_control_flags |= GEN6_PIPE_CONTROL_CS_STALL;
324 break;
325 default:
Chia-I Wu4e5577a2015-02-10 11:04:44 -0700326 cmd_fail(cmd, XGL_ERROR_UNKNOWN);
Mike Stroyan55658c22014-12-04 11:08:39 +0000327 return;
328 break;
329 }
Chia-I Wu525c6602014-08-27 10:22:34 +0800330 }
331
Mike Stroyan55658c22014-12-04 11:08:39 +0000332 /* cmd_memory_barriers can wait for GEN6_PIPE_CONTROL_CS_STALL and perform
333 * appropriate cache control.
334 */
335 cmd_memory_barriers(cmd,
336 pipe_control_flags,
Mark Lobodzinski628a8a52015-02-02 11:55:52 -0600337 pBarrier->memBarrierCount, pBarrier->ppMemBarriers);
Chia-I Wu525c6602014-08-27 10:22:34 +0800338}