X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Firis%2Firis_pipe_control.c;h=3d12a5b03603f805f0063acec0299eacb58315a8;hb=4f1319a17dc795cb76cd97853b15bfd1dfb02a14;hp=66a559d5cc3291099f15de16764627cf254ad72e;hpb=21acc004901629fe376206afd979259a1f220248;p=mesa.git diff --git a/src/gallium/drivers/iris/iris_pipe_control.c b/src/gallium/drivers/iris/iris_pipe_control.c index 66a559d5cc3..3d12a5b0360 100644 --- a/src/gallium/drivers/iris/iris_pipe_control.c +++ b/src/gallium/drivers/iris/iris_pipe_control.c @@ -8,20 +8,45 @@ * 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 above copyright notice and this permission notice 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, + * 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. + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * @file iris_pipe_control.c + * + * PIPE_CONTROL is the main flushing and synchronization primitive on Intel + * GPUs. It can invalidate caches, stall until rendering reaches various + * stages of completion, write to memory, and other things. In a way, it's + * a swiss army knife command - it has all kinds of capabilities, but some + * significant limitations as well. + * + * Unfortunately, it's notoriously complicated and difficult to use. Many + * sub-commands can't be used together. Some are meant to be used at the + * top of the pipeline (invalidating caches before drawing), while some are + * meant to be used at the end (stalling or flushing after drawing). + * + * Also, there's a list of restrictions a mile long, which vary by generation. + * Do this before doing that, or suffer the consequences (usually a GPU hang). + * + * This file contains helpers for emitting them safely. You can simply call + * iris_emit_pipe_control_flush() with the desired operations (as logical + * PIPE_CONTROL_* bits), and it will take care of splitting it into multiple + * PIPE_CONTROL commands as necessary. The per-generation workarounds are + * applied in iris_emit_raw_pipe_control() in iris_state.c. */ #include "iris_context.h" +#include "util/hash_table.h" +#include "util/set.h" /** * Emit a PIPE_CONTROL with various flushing flags. @@ -30,9 +55,7 @@ * given generation. */ void -iris_emit_pipe_control_flush(struct iris_context *ice, - struct iris_batch *batch, - uint32_t flags) +iris_emit_pipe_control_flush(struct iris_batch *batch, uint32_t flags) { if ((flags & PIPE_CONTROL_CACHE_FLUSH_BITS) && (flags & PIPE_CONTROL_CACHE_INVALIDATE_BITS)) { @@ -47,12 +70,11 @@ iris_emit_pipe_control_flush(struct iris_context *ice, * with any write cache flush, so this shouldn't be a concern. In order * to ensure a full stall, we do an end-of-pipe sync. */ - iris_emit_end_of_pipe_sync(ice, batch, - flags & PIPE_CONTROL_CACHE_FLUSH_BITS); + iris_emit_end_of_pipe_sync(batch, flags & PIPE_CONTROL_CACHE_FLUSH_BITS); flags &= ~(PIPE_CONTROL_CACHE_FLUSH_BITS | PIPE_CONTROL_CS_STALL); } - ice->state.emit_raw_pipe_control(batch, flags, NULL, 0, 0); + batch->vtbl->emit_raw_pipe_control(batch, flags, NULL, 0, 0); } /** @@ -64,12 +86,11 @@ iris_emit_pipe_control_flush(struct iris_context *ice, * - PIPE_CONTROL_WRITE_DEPTH_COUNT */ void -iris_emit_pipe_control_write(struct iris_context *ice, - struct iris_batch *batch, uint32_t flags, +iris_emit_pipe_control_write(struct iris_batch *batch, uint32_t flags, struct iris_bo *bo, uint32_t offset, uint64_t imm) { - ice->state.emit_raw_pipe_control(batch, flags, bo, offset, imm); + batch->vtbl->emit_raw_pipe_control(batch, flags, bo, offset, imm); } /* @@ -95,9 +116,7 @@ iris_emit_pipe_control_write(struct iris_context *ice, * Data" in the PIPE_CONTROL command. */ void -iris_emit_end_of_pipe_sync(struct iris_context *ice, - struct iris_batch *batch, - uint32_t flags) +iris_emit_end_of_pipe_sync(struct iris_batch *batch, uint32_t flags) { /* From Sandybridge PRM, volume 2, "1.7.3.1 Writing a Value to Memory": * @@ -121,7 +140,69 @@ iris_emit_end_of_pipe_sync(struct iris_context *ice, * Data, Required Write Cache Flush bits set) * - Workload-2 (Can use the data produce or output by Workload-1) */ - iris_emit_pipe_control_write(ice, batch, flags | PIPE_CONTROL_CS_STALL | + iris_emit_pipe_control_write(batch, flags | PIPE_CONTROL_CS_STALL | PIPE_CONTROL_WRITE_IMMEDIATE, batch->screen->workaround_bo, 0, 0); } + +static void +iris_texture_barrier(struct pipe_context *ctx, unsigned flags) +{ + struct iris_context *ice = (void *) ctx; + struct iris_batch *render_batch = &ice->batches[IRIS_BATCH_RENDER]; + struct iris_batch *compute_batch = &ice->batches[IRIS_BATCH_COMPUTE]; + + if (render_batch->contains_draw || + render_batch->cache.render->entries || + render_batch->cache.depth->entries) { + iris_emit_pipe_control_flush(&ice->batches[IRIS_BATCH_RENDER], + PIPE_CONTROL_DEPTH_CACHE_FLUSH | + PIPE_CONTROL_RENDER_TARGET_FLUSH | + PIPE_CONTROL_CS_STALL); + iris_emit_pipe_control_flush(&ice->batches[IRIS_BATCH_RENDER], + PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); + } + + if (compute_batch->contains_draw) { + iris_emit_pipe_control_flush(&ice->batches[IRIS_BATCH_COMPUTE], + PIPE_CONTROL_CS_STALL); + iris_emit_pipe_control_flush(&ice->batches[IRIS_BATCH_COMPUTE], + PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); + } +} + +static void +iris_memory_barrier(struct pipe_context *ctx, unsigned flags) +{ + struct iris_context *ice = (void *) ctx; + unsigned bits = PIPE_CONTROL_DATA_CACHE_FLUSH | PIPE_CONTROL_CS_STALL; + + if (flags & (PIPE_BARRIER_VERTEX_BUFFER | + PIPE_BARRIER_INDEX_BUFFER | + PIPE_BARRIER_INDIRECT_BUFFER)) { + bits |= PIPE_CONTROL_VF_CACHE_INVALIDATE; + } + + if (flags & PIPE_BARRIER_CONSTANT_BUFFER) { + bits |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | + PIPE_CONTROL_CONST_CACHE_INVALIDATE; + } + + if (flags & (PIPE_BARRIER_TEXTURE | PIPE_BARRIER_FRAMEBUFFER)) { + bits |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | + PIPE_CONTROL_RENDER_TARGET_FLUSH; + } + + for (int i = 0; i < IRIS_BATCH_COUNT; i++) { + if (ice->batches[i].contains_draw || + ice->batches[i].cache.render->entries) + iris_emit_pipe_control_flush(&ice->batches[i], bits); + } +} + +void +iris_init_flush_functions(struct pipe_context *ctx) +{ + ctx->memory_barrier = iris_memory_barrier; + ctx->texture_barrier = iris_texture_barrier; +}