From: Alyssa Rosenzweig Date: Tue, 7 Jul 2020 21:23:09 +0000 (-0400) Subject: panfrost: Move scoreboarding routines to common X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1fdeef5e4a11f0590f443b805b53be842f745018;p=mesa.git panfrost: Move scoreboarding routines to common Signed-off-by: Alyssa Rosenzweig Part-of: --- diff --git a/src/gallium/drivers/panfrost/Makefile.sources b/src/gallium/drivers/panfrost/Makefile.sources index 4688754672c..3ce48b2c50b 100644 --- a/src/gallium/drivers/panfrost/Makefile.sources +++ b/src/gallium/drivers/panfrost/Makefile.sources @@ -22,7 +22,6 @@ C_SOURCES := \ pan_public.h \ pan_resource.c \ pan_resource.h \ - pan_scoreboard.c \ pan_screen.c \ pan_screen.h \ pan_sfbd.c \ diff --git a/src/gallium/drivers/panfrost/meson.build b/src/gallium/drivers/panfrost/meson.build index 154d05a7344..f71a4cc2db5 100644 --- a/src/gallium/drivers/panfrost/meson.build +++ b/src/gallium/drivers/panfrost/meson.build @@ -38,7 +38,6 @@ files_panfrost = files( 'pan_cmdstream.c', 'pan_compute.c', 'pan_fragment.c', - 'pan_scoreboard.c', 'pan_sfbd.c', 'pan_mfbd.c', ) diff --git a/src/gallium/drivers/panfrost/pan_scoreboard.c b/src/gallium/drivers/panfrost/pan_scoreboard.c deleted file mode 100644 index d2cc0568789..00000000000 --- a/src/gallium/drivers/panfrost/pan_scoreboard.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2019 Collabora, Ltd. - * - * 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 "pan_context.h" -#include "pan_job.h" -#include "pan_pool.h" -#include "panfrost-quirks.h" -#include "util/bitset.h" - -/* - * There are various types of Mali jobs: - * - * - WRITE_VALUE: generic write primitive, used to zero tiler field - * - VERTEX: runs a vertex shader - * - TILER: runs tiling and sets up a fragment shader - * - FRAGMENT: runs fragment shaders and writes out - * - COMPUTE: runs a compute shader - * - FUSED: vertex+tiler fused together, implicit intradependency (Bifrost) - * - GEOMETRY: runs a geometry shader (unimplemented) - * - CACHE_FLUSH: unseen in the wild, theoretically cache flush - * - * In between a full batch and a single Mali job is the "job chain", a series - * of Mali jobs together forming a linked list. Within the job chain, each Mali - * job can set (up to) two dependencies on other earlier jobs in the chain. - * This dependency graph forms a scoreboard. The general idea of a scoreboard - * applies: when there is a data dependency of job B on job A, job B sets one - * of its dependency indices to job A, ensuring that job B won't start until - * job A finishes. - * - * More specifically, here are a set of rules: - * - * - A write value job must appear if and only if there is at least one tiler - * job, and tiler jobs must depend on it. - * - * - Vertex jobs and tiler jobs are independent. - * - * - A tiler job must have a dependency on its data source. If it's getting - * data from a vertex job, it depends on the vertex job. If it's getting data - * from software, this is null. - * - * - Tiler jobs must depend on the write value job (chained or otherwise). - * - * - Tiler jobs must be strictly ordered. So each tiler job must depend on the - * previous job in the chain. - * - * - Jobs linking via next_job has no bearing on order of execution, rather it - * just establishes the linked list of jobs, EXCEPT: - * - * - A job's dependencies must appear earlier in the linked list (job chain). - * - * Justification for each rule: - * - * - Write value jobs are used to write a zero into a magic tiling field, which - * enables tiling to work. If tiling occurs, they are needed; if it does not, - * we cannot emit them since then tiling partially occurs and it's bad. - * - * - The hardware has no notion of a "vertex/tiler job" (at least not our - * hardware -- other revs have fused jobs, but --- crap, this just got even - * more complicated). They are independent units that take in data, process - * it, and spit out data. - * - * - Any job must depend on its data source, in fact, or risk a - * read-before-write hazard. Tiler jobs get their data from vertex jobs, ergo - * tiler jobs depend on the corresponding vertex job (if it's there). - * - * - The tiler is not thread-safe; this dependency prevents race conditions - * between two different jobs trying to write to the tiler outputs at the - * same time. - * - * - Internally, jobs are scoreboarded; the next job fields just form a linked - * list to allow the jobs to be read in; the execution order is from - * resolving the dependency fields instead. - * - * - The hardware cannot set a dependency on a job it doesn't know about yet, - * and dependencies are processed in-order of the next job fields. - * - */ - -/* Generates, uploads, and queues a a new job. All fields are written in order - * except for next_job accounting (TODO: Should we be clever and defer the - * upload of the header here until next job to keep the access pattern totally - * linear? Or is that just a micro op at this point?). Returns the generated - * index for dep management. - * - * Inject is used to inject a job at the front, for wallpapering. If you are - * not wallpapering and set this, dragons will eat you. */ - -unsigned -panfrost_new_job( - struct pan_pool *pool, - struct pan_scoreboard *scoreboard, - enum mali_job_type type, - bool barrier, - unsigned local_dep, - void *payload, size_t payload_size, - bool inject) -{ - unsigned global_dep = 0; - - if (type == JOB_TYPE_TILER) { - /* Tiler jobs must be chained, and on Midgard, the first tiler - * job must depend on the write value job, whose index we - * reserve now */ - - if (scoreboard->tiler_dep) - global_dep = scoreboard->tiler_dep; - else if (!(pool->dev->quirks & IS_BIFROST)) { - scoreboard->write_value_index = ++scoreboard->job_index; - global_dep = scoreboard->write_value_index; - } - } - - /* Assign the index */ - unsigned index = ++scoreboard->job_index; - - struct mali_job_descriptor_header job = { - .job_descriptor_size = 1, - .job_type = type, - .job_barrier = barrier, - .job_index = index, - .job_dependency_index_1 = local_dep, - .job_dependency_index_2 = global_dep, - }; - - if (inject) - job.next_job = scoreboard->first_job; - - struct panfrost_transfer transfer = panfrost_pool_alloc(pool, sizeof(job) + payload_size); - memcpy(transfer.cpu, &job, sizeof(job)); - memcpy(transfer.cpu + sizeof(job), payload, payload_size); - - if (inject) { - scoreboard->first_job = transfer.gpu; - return index; - } - - /* Form a chain */ - if (type == JOB_TYPE_TILER) - scoreboard->tiler_dep = index; - - if (scoreboard->prev_job) - scoreboard->prev_job->next_job = transfer.gpu; - else - scoreboard->first_job = transfer.gpu; - - scoreboard->prev_job = (struct mali_job_descriptor_header *) transfer.cpu; - return index; -} - -/* Generates a write value job, used to initialize the tiler structures. Note - * this is called right before frame submission. */ - -void -panfrost_scoreboard_initialize_tiler(struct pan_pool *pool, - struct pan_scoreboard *scoreboard, - mali_ptr polygon_list) -{ - /* Check if we even need tiling */ - if (pool->dev->quirks & IS_BIFROST || !scoreboard->tiler_dep) - return; - - /* Okay, we do. Let's generate it. We'll need the job's polygon list - * regardless of size. */ - - struct mali_job_descriptor_header job = { - .job_type = JOB_TYPE_WRITE_VALUE, - .job_index = scoreboard->write_value_index, - .job_descriptor_size = 1, - .next_job = scoreboard->first_job - }; - - struct mali_payload_write_value payload = { - .address = polygon_list, - .value_descriptor = MALI_WRITE_VALUE_ZERO, - }; - - struct panfrost_transfer transfer = panfrost_pool_alloc(pool, sizeof(job) + sizeof(payload)); - memcpy(transfer.cpu, &job, sizeof(job)); - memcpy(transfer.cpu + sizeof(job), &payload, sizeof(payload)); - - scoreboard->first_job = transfer.gpu; -} diff --git a/src/gallium/drivers/panfrost/pan_scoreboard.h b/src/gallium/drivers/panfrost/pan_scoreboard.h deleted file mode 100644 index 329635f095a..00000000000 --- a/src/gallium/drivers/panfrost/pan_scoreboard.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2019-2020 Collabora Ltd. - * Copyright (C) 2019 Alyssa Rosenzweig - * Copyright (C) 2014-2017 Broadcom - * - * 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. - * - */ - -#ifndef __PAN_SCOREBOARD_H__ -#define __PAN_SCOREBOARD_H__ - -struct pan_scoreboard { - /* The first job in the batch */ - mali_ptr first_job; - - /* The number of jobs in the primary batch, essentially */ - unsigned job_index; - - /* A CPU-side pointer to the previous job for next_job linking */ - struct mali_job_descriptor_header *prev_job; - - /* The dependency for tiler jobs (i.e. the index of the last emitted - * tiler job, or zero if none have been emitted) */ - unsigned tiler_dep; - - /* The job index of the WRITE_VALUE job (before it has been created) */ - unsigned write_value_index; -}; - -unsigned -panfrost_new_job( - struct pan_pool *pool, - struct pan_scoreboard *scoreboard, - enum mali_job_type type, - bool barrier, - unsigned local_dep, - void *payload, size_t payload_size, - bool inject); - -void panfrost_scoreboard_initialize_tiler( - struct pan_pool *pool, - struct pan_scoreboard *scoreboard, - mali_ptr polygon_list); - -#endif diff --git a/src/panfrost/Makefile.sources b/src/panfrost/Makefile.sources index d085b763e3e..4efd694b3a7 100644 --- a/src/panfrost/Makefile.sources +++ b/src/panfrost/Makefile.sources @@ -33,6 +33,8 @@ encoder_FILES := \ encoder/pan_pool.h \ encoder/pan_props.c \ encoder/pan_sampler.c \ + encoder/pan_scoreboard.c \ + encoder/pan_scoreboard.h \ encoder/pan_tiler.c \ encoder/pan_texture.c \ encoder/pan_scratch.c \ diff --git a/src/panfrost/encoder/meson.build b/src/panfrost/encoder/meson.build index 2e5baea4fc5..e7b28e16338 100644 --- a/src/panfrost/encoder/meson.build +++ b/src/panfrost/encoder/meson.build @@ -30,6 +30,7 @@ libpanfrost_encoder_files = files( 'pan_sampler.c', 'pan_tiler.c', 'pan_texture.c', + 'pan_scoreboard.c', 'pan_scratch.c', 'pan_pool.c', 'pan_props.c', diff --git a/src/panfrost/encoder/pan_scoreboard.c b/src/panfrost/encoder/pan_scoreboard.c new file mode 100644 index 00000000000..c72c9a37c3a --- /dev/null +++ b/src/panfrost/encoder/pan_scoreboard.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2019 Collabora, Ltd. + * + * 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 +#include "pan_scoreboard.h" +#include "pan_device.h" +#include "panfrost-quirks.h" + +/* + * There are various types of Mali jobs: + * + * - WRITE_VALUE: generic write primitive, used to zero tiler field + * - VERTEX: runs a vertex shader + * - TILER: runs tiling and sets up a fragment shader + * - FRAGMENT: runs fragment shaders and writes out + * - COMPUTE: runs a compute shader + * - FUSED: vertex+tiler fused together, implicit intradependency (Bifrost) + * - GEOMETRY: runs a geometry shader (unimplemented) + * - CACHE_FLUSH: unseen in the wild, theoretically cache flush + * + * In between a full batch and a single Mali job is the "job chain", a series + * of Mali jobs together forming a linked list. Within the job chain, each Mali + * job can set (up to) two dependencies on other earlier jobs in the chain. + * This dependency graph forms a scoreboard. The general idea of a scoreboard + * applies: when there is a data dependency of job B on job A, job B sets one + * of its dependency indices to job A, ensuring that job B won't start until + * job A finishes. + * + * More specifically, here are a set of rules: + * + * - A write value job must appear if and only if there is at least one tiler + * job, and tiler jobs must depend on it. + * + * - Vertex jobs and tiler jobs are independent. + * + * - A tiler job must have a dependency on its data source. If it's getting + * data from a vertex job, it depends on the vertex job. If it's getting data + * from software, this is null. + * + * - Tiler jobs must depend on the write value job (chained or otherwise). + * + * - Tiler jobs must be strictly ordered. So each tiler job must depend on the + * previous job in the chain. + * + * - Jobs linking via next_job has no bearing on order of execution, rather it + * just establishes the linked list of jobs, EXCEPT: + * + * - A job's dependencies must appear earlier in the linked list (job chain). + * + * Justification for each rule: + * + * - Write value jobs are used to write a zero into a magic tiling field, which + * enables tiling to work. If tiling occurs, they are needed; if it does not, + * we cannot emit them since then tiling partially occurs and it's bad. + * + * - The hardware has no notion of a "vertex/tiler job" (at least not our + * hardware -- other revs have fused jobs, but --- crap, this just got even + * more complicated). They are independent units that take in data, process + * it, and spit out data. + * + * - Any job must depend on its data source, in fact, or risk a + * read-before-write hazard. Tiler jobs get their data from vertex jobs, ergo + * tiler jobs depend on the corresponding vertex job (if it's there). + * + * - The tiler is not thread-safe; this dependency prevents race conditions + * between two different jobs trying to write to the tiler outputs at the + * same time. + * + * - Internally, jobs are scoreboarded; the next job fields just form a linked + * list to allow the jobs to be read in; the execution order is from + * resolving the dependency fields instead. + * + * - The hardware cannot set a dependency on a job it doesn't know about yet, + * and dependencies are processed in-order of the next job fields. + * + */ + +/* Generates, uploads, and queues a a new job. All fields are written in order + * except for next_job accounting (TODO: Should we be clever and defer the + * upload of the header here until next job to keep the access pattern totally + * linear? Or is that just a micro op at this point?). Returns the generated + * index for dep management. + * + * Inject is used to inject a job at the front, for wallpapering. If you are + * not wallpapering and set this, dragons will eat you. */ + +unsigned +panfrost_new_job( + struct pan_pool *pool, + struct pan_scoreboard *scoreboard, + enum mali_job_type type, + bool barrier, + unsigned local_dep, + void *payload, size_t payload_size, + bool inject) +{ + unsigned global_dep = 0; + + if (type == JOB_TYPE_TILER) { + /* Tiler jobs must be chained, and on Midgard, the first tiler + * job must depend on the write value job, whose index we + * reserve now */ + + if (scoreboard->tiler_dep) + global_dep = scoreboard->tiler_dep; + else if (!(pool->dev->quirks & IS_BIFROST)) { + scoreboard->write_value_index = ++scoreboard->job_index; + global_dep = scoreboard->write_value_index; + } + } + + /* Assign the index */ + unsigned index = ++scoreboard->job_index; + + struct mali_job_descriptor_header job = { + .job_descriptor_size = 1, + .job_type = type, + .job_barrier = barrier, + .job_index = index, + .job_dependency_index_1 = local_dep, + .job_dependency_index_2 = global_dep, + }; + + if (inject) + job.next_job = scoreboard->first_job; + + struct panfrost_transfer transfer = panfrost_pool_alloc(pool, sizeof(job) + payload_size); + memcpy(transfer.cpu, &job, sizeof(job)); + memcpy(transfer.cpu + sizeof(job), payload, payload_size); + + if (inject) { + scoreboard->first_job = transfer.gpu; + return index; + } + + /* Form a chain */ + if (type == JOB_TYPE_TILER) + scoreboard->tiler_dep = index; + + if (scoreboard->prev_job) + scoreboard->prev_job->next_job = transfer.gpu; + else + scoreboard->first_job = transfer.gpu; + + scoreboard->prev_job = (struct mali_job_descriptor_header *) transfer.cpu; + return index; +} + +/* Generates a write value job, used to initialize the tiler structures. Note + * this is called right before frame submission. */ + +void +panfrost_scoreboard_initialize_tiler(struct pan_pool *pool, + struct pan_scoreboard *scoreboard, + mali_ptr polygon_list) +{ + /* Check if we even need tiling */ + if (pool->dev->quirks & IS_BIFROST || !scoreboard->tiler_dep) + return; + + /* Okay, we do. Let's generate it. We'll need the job's polygon list + * regardless of size. */ + + struct mali_job_descriptor_header job = { + .job_type = JOB_TYPE_WRITE_VALUE, + .job_index = scoreboard->write_value_index, + .job_descriptor_size = 1, + .next_job = scoreboard->first_job + }; + + struct mali_payload_write_value payload = { + .address = polygon_list, + .value_descriptor = MALI_WRITE_VALUE_ZERO, + }; + + struct panfrost_transfer transfer = panfrost_pool_alloc(pool, sizeof(job) + sizeof(payload)); + memcpy(transfer.cpu, &job, sizeof(job)); + memcpy(transfer.cpu + sizeof(job), &payload, sizeof(payload)); + + scoreboard->first_job = transfer.gpu; +} diff --git a/src/panfrost/encoder/pan_scoreboard.h b/src/panfrost/encoder/pan_scoreboard.h new file mode 100644 index 00000000000..71667d4b5de --- /dev/null +++ b/src/panfrost/encoder/pan_scoreboard.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019-2020 Collabora Ltd. + * Copyright (C) 2019 Alyssa Rosenzweig + * Copyright (C) 2014-2017 Broadcom + * + * 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. + * + */ + +#ifndef __PAN_SCOREBOARD_H__ +#define __PAN_SCOREBOARD_H__ + +#include "panfrost-job.h" +#include "pan_pool.h" + +struct pan_scoreboard { + /* The first job in the batch */ + mali_ptr first_job; + + /* The number of jobs in the primary batch, essentially */ + unsigned job_index; + + /* A CPU-side pointer to the previous job for next_job linking */ + struct mali_job_descriptor_header *prev_job; + + /* The dependency for tiler jobs (i.e. the index of the last emitted + * tiler job, or zero if none have been emitted) */ + unsigned tiler_dep; + + /* The job index of the WRITE_VALUE job (before it has been created) */ + unsigned write_value_index; +}; + +unsigned +panfrost_new_job( + struct pan_pool *pool, + struct pan_scoreboard *scoreboard, + enum mali_job_type type, + bool barrier, + unsigned local_dep, + void *payload, size_t payload_size, + bool inject); + +void panfrost_scoreboard_initialize_tiler( + struct pan_pool *pool, + struct pan_scoreboard *scoreboard, + mali_ptr polygon_list); + +#endif