• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2019 Collabora LTD
4  *
5  * Author: Gert Wollny <gert.wollny@collabora.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * on the rights to use, copy, modify, merge, publish, distribute, sub
11  * license, and/or sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26 
27 #include "r600_sfn.h"
28 
29 #include "compiler/nir/nir.h"
30 #include "compiler/shader_enums.h"
31 #include "sfn/sfn_assembler.h"
32 #include "sfn/sfn_debug.h"
33 #include "sfn/sfn_memorypool.h"
34 #include "sfn/sfn_nir.h"
35 #include "sfn/sfn_shader.h"
36 #include "r600_asm.h"
37 #include "r600_pipe.h"
38 #include "util/macros.h"
39 #include "util/ralloc.h"
40 
41 #include <cassert>
42 #include <cstdio>
43 #include <cstring>
44 #include <iostream>
45 
46 char *
r600_finalize_nir(pipe_screen * screen,void * shader)47 r600_finalize_nir(pipe_screen *screen, void *shader)
48 {
49    auto rs = container_of(screen, r600_screen, b.b);
50    auto nir = static_cast<nir_shader *>(shader);
51    r600_finalize_nir_common(nir, rs->b.gfx_level);
52    return nullptr;
53 }
54 
55 class MallocPoolRelease {
56 public:
MallocPoolRelease()57    MallocPoolRelease() { r600::init_pool(); }
~MallocPoolRelease()58    ~MallocPoolRelease() { r600::release_pool(); }
59 };
60 
61 int
r600_shader_from_nir(struct r600_context * rctx,struct r600_pipe_shader * pipeshader,r600_shader_key * key)62 r600_shader_from_nir(struct r600_context *rctx,
63                      struct r600_pipe_shader *pipeshader,
64                      r600_shader_key *key)
65 {
66 
67    MallocPoolRelease pool_release;
68 
69    struct r600_pipe_shader_selector *sel = pipeshader->selector;
70 
71    if (rctx->screen->b.debug_flags & DBG_PREOPT_IR) {
72       fprintf(stderr, "PRE-OPT-NIR-----------.------------------------------\n");
73       nir_print_shader(sel->nir, stderr);
74       fprintf(stderr, "END PRE-OPT-NIR--------------------------------------\n\n");
75    }
76 
77    auto sh = nir_shader_clone(sel->nir, sel->nir);
78 
79    r600_lower_and_optimize_nir(sh, key, rctx->b.gfx_level, &sel->so);
80 
81    if (rctx->screen->b.debug_flags & DBG_ALL_SHADERS) {
82       fprintf(stderr,
83               "-- NIR --------------------------------------------------------\n");
84       struct nir_function *func =
85          (struct nir_function *)exec_list_get_head(&sh->functions);
86       nir_index_ssa_defs(func->impl);
87       nir_print_shader(sh, stderr);
88       fprintf(stderr,
89               "-- END --------------------------------------------------------\n");
90    }
91 
92    memset(&pipeshader->shader, 0, sizeof(r600_shader));
93    pipeshader->scratch_space_needed = sh->scratch_size;
94 
95    if (sh->info.stage == MESA_SHADER_TESS_EVAL || sh->info.stage == MESA_SHADER_VERTEX ||
96        sh->info.stage == MESA_SHADER_GEOMETRY) {
97       pipeshader->shader.clip_dist_write |=
98          ((1 << sh->info.clip_distance_array_size) - 1);
99       pipeshader->shader.cull_dist_write = ((1 << sh->info.cull_distance_array_size) - 1)
100                                            << sh->info.clip_distance_array_size;
101       pipeshader->shader.cc_dist_mask =
102          (1 << (sh->info.cull_distance_array_size + sh->info.clip_distance_array_size)) -
103          1;
104    }
105    struct r600_shader *gs_shader = nullptr;
106    if (rctx->gs_shader)
107       gs_shader = &rctx->gs_shader->current->shader;
108    r600_screen *rscreen = rctx->screen;
109 
110    r600::Shader *shader =
111       r600::Shader::translate_from_nir(sh, &sel->so, gs_shader, *key,
112                                        rctx->isa->hw_class, rscreen->b.family);
113 
114    assert(shader);
115    if (!shader)
116       return -2;
117 
118    pipeshader->enabled_stream_buffers_mask = shader->enabled_stream_buffers_mask();
119    pipeshader->selector->info.file_count[TGSI_FILE_HW_ATOMIC] +=
120       shader->atomic_file_count();
121    pipeshader->selector->info.writes_memory =
122       shader->has_flag(r600::Shader::sh_writes_memory);
123 
124    r600_finalize_and_optimize_shader(shader);
125 
126    auto scheduled_shader = r600_schedule_shader(shader);
127    if (!scheduled_shader) {
128       return -1;
129    }
130 
131    scheduled_shader->get_shader_info(&pipeshader->shader);
132    pipeshader->shader.uses_doubles = sh->info.bit_sizes_float & 64 ? 1 : 0;
133 
134    r600_bytecode_init(&pipeshader->shader.bc,
135                       rscreen->b.gfx_level,
136                       rscreen->b.family,
137                       rscreen->has_compressed_msaa_texturing);
138 
139    /* We already schedule the code with this in mind, no need to handle this
140     * in the backend assembler */
141    pipeshader->shader.bc.ar_handling = AR_HANDLE_NORMAL;
142    pipeshader->shader.bc.r6xx_nop_after_rel_dst = 0;
143 
144    r600::sfn_log << r600::SfnLog::shader_info << "pipeshader->shader.processor_type = "
145                  << pipeshader->shader.processor_type << "\n";
146 
147    pipeshader->shader.bc.type = pipeshader->shader.processor_type;
148    pipeshader->shader.bc.isa = rctx->isa;
149    pipeshader->shader.bc.ngpr = scheduled_shader->required_registers();
150 
151    r600::Assembler afs(&pipeshader->shader, *key);
152    if (!afs.lower(scheduled_shader)) {
153       R600_ERR("%s: Lowering to assembly failed\n", __func__);
154 
155       scheduled_shader->print(std::cerr);
156       /* For now crash if the shader could not be generated */
157       assert(0);
158       return -1;
159    }
160 
161    if (sh->info.stage == MESA_SHADER_VERTEX) {
162       pipeshader->shader.vs_position_window_space =
163             sh->info.vs.window_space_position;
164    }
165 
166    if (sh->info.stage == MESA_SHADER_FRAGMENT)
167       pipeshader->shader.ps_conservative_z =
168             sh->info.fs.depth_layout;
169 
170    if (sh->info.stage == MESA_SHADER_GEOMETRY) {
171       r600::sfn_log << r600::SfnLog::shader_info
172                     << "Geometry shader, create copy shader\n";
173       generate_gs_copy_shader(rctx, pipeshader, &sel->so);
174       assert(pipeshader->gs_copy_shader);
175    } else {
176       r600::sfn_log << r600::SfnLog::shader_info << "This is not a Geometry shader\n";
177    }
178    ralloc_free(sh);
179 
180    return 0;
181 }
182