1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2014 Ilia Mirkin. All Rights Reserved.
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
7bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
8bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
9bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
10bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
11bf215546Sopenharmony_ci * the following conditions:
12bf215546Sopenharmony_ci *
13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
14bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
15bf215546Sopenharmony_ci * of the Software.
16bf215546Sopenharmony_ci *
17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24bf215546Sopenharmony_ci *
25bf215546Sopenharmony_ci **************************************************************************/
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "program/prog_parameter.h"
29bf215546Sopenharmony_ci#include "program/prog_print.h"
30bf215546Sopenharmony_ci#include "compiler/glsl/ir_uniform.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "pipe/p_context.h"
33bf215546Sopenharmony_ci#include "pipe/p_defines.h"
34bf215546Sopenharmony_ci#include "util/u_inlines.h"
35bf215546Sopenharmony_ci#include "util/u_surface.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "st_debug.h"
38bf215546Sopenharmony_ci#include "st_context.h"
39bf215546Sopenharmony_ci#include "st_atom.h"
40bf215546Sopenharmony_ci#include "st_program.h"
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistatic void
43bf215546Sopenharmony_cist_binding_to_sb(struct gl_buffer_binding *binding,
44bf215546Sopenharmony_ci                 struct pipe_shader_buffer *sb,
45bf215546Sopenharmony_ci                 unsigned alignment)
46bf215546Sopenharmony_ci{
47bf215546Sopenharmony_ci   struct gl_buffer_object *st_obj = binding->BufferObject;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   if (st_obj && st_obj->buffer) {
50bf215546Sopenharmony_ci     unsigned offset = 0;
51bf215546Sopenharmony_ci     sb->buffer = st_obj->buffer;
52bf215546Sopenharmony_ci     offset = binding->Offset % alignment;
53bf215546Sopenharmony_ci     sb->buffer_offset = binding->Offset - offset;
54bf215546Sopenharmony_ci     sb->buffer_size = st_obj->buffer->width0 - sb->buffer_offset;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci     /* AutomaticSize is FALSE if the buffer was set with BindBufferRange.
57bf215546Sopenharmony_ci      * Take the minimum just to be sure.
58bf215546Sopenharmony_ci      */
59bf215546Sopenharmony_ci     if (!binding->AutomaticSize)
60bf215546Sopenharmony_ci       sb->buffer_size = MIN2(sb->buffer_size, (unsigned) binding->Size + offset);
61bf215546Sopenharmony_ci   } else {
62bf215546Sopenharmony_ci     sb->buffer = NULL;
63bf215546Sopenharmony_ci     sb->buffer_offset = 0;
64bf215546Sopenharmony_ci     sb->buffer_size = 0;
65bf215546Sopenharmony_ci   }
66bf215546Sopenharmony_ci}
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_cistatic void
69bf215546Sopenharmony_cist_bind_atomics(struct st_context *st, struct gl_program *prog,
70bf215546Sopenharmony_ci                gl_shader_stage stage)
71bf215546Sopenharmony_ci{
72bf215546Sopenharmony_ci   unsigned i;
73bf215546Sopenharmony_ci   enum pipe_shader_type shader_type = pipe_shader_type_from_mesa(stage);
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   if (!prog || !st->pipe->set_shader_buffers || st->has_hw_atomics)
76bf215546Sopenharmony_ci      return;
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   /* For !has_hw_atomics, the atomic counters have been rewritten to be above
79bf215546Sopenharmony_ci    * the SSBOs used by the program.
80bf215546Sopenharmony_ci    */
81bf215546Sopenharmony_ci   unsigned buffer_base = prog->info.num_ssbos;
82bf215546Sopenharmony_ci   unsigned used_bindings = 0;
83bf215546Sopenharmony_ci   for (i = 0; i < prog->sh.data->NumAtomicBuffers; i++) {
84bf215546Sopenharmony_ci      struct gl_active_atomic_buffer *atomic =
85bf215546Sopenharmony_ci         &prog->sh.data->AtomicBuffers[i];
86bf215546Sopenharmony_ci      struct pipe_shader_buffer sb;
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci      st_binding_to_sb(&st->ctx->AtomicBufferBindings[atomic->Binding], &sb,
89bf215546Sopenharmony_ci                       st->ctx->Const.ShaderStorageBufferOffsetAlignment);
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci      st->pipe->set_shader_buffers(st->pipe, shader_type,
92bf215546Sopenharmony_ci                                   buffer_base + atomic->Binding, 1, &sb, 0x1);
93bf215546Sopenharmony_ci      used_bindings = MAX2(atomic->Binding + 1, used_bindings);
94bf215546Sopenharmony_ci   }
95bf215546Sopenharmony_ci   st->last_used_atomic_bindings[shader_type] = used_bindings;
96bf215546Sopenharmony_ci}
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_civoid
99bf215546Sopenharmony_cist_bind_vs_atomics(struct st_context *st)
100bf215546Sopenharmony_ci{
101bf215546Sopenharmony_ci   struct gl_program *prog =
102bf215546Sopenharmony_ci      st->ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   st_bind_atomics(st, prog, MESA_SHADER_VERTEX);
105bf215546Sopenharmony_ci}
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_civoid
108bf215546Sopenharmony_cist_bind_fs_atomics(struct st_context *st)
109bf215546Sopenharmony_ci{
110bf215546Sopenharmony_ci   struct gl_program *prog =
111bf215546Sopenharmony_ci      st->ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   st_bind_atomics(st, prog, MESA_SHADER_FRAGMENT);
114bf215546Sopenharmony_ci}
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_civoid
117bf215546Sopenharmony_cist_bind_gs_atomics(struct st_context *st)
118bf215546Sopenharmony_ci{
119bf215546Sopenharmony_ci   struct gl_program *prog =
120bf215546Sopenharmony_ci      st->ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   st_bind_atomics(st, prog, MESA_SHADER_GEOMETRY);
123bf215546Sopenharmony_ci}
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_civoid
126bf215546Sopenharmony_cist_bind_tcs_atomics(struct st_context *st)
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci   struct gl_program *prog =
129bf215546Sopenharmony_ci      st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL];
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   st_bind_atomics(st, prog, MESA_SHADER_TESS_CTRL);
132bf215546Sopenharmony_ci}
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_civoid
135bf215546Sopenharmony_cist_bind_tes_atomics(struct st_context *st)
136bf215546Sopenharmony_ci{
137bf215546Sopenharmony_ci   struct gl_program *prog =
138bf215546Sopenharmony_ci      st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   st_bind_atomics(st, prog, MESA_SHADER_TESS_EVAL);
141bf215546Sopenharmony_ci}
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_civoid
144bf215546Sopenharmony_cist_bind_cs_atomics(struct st_context *st)
145bf215546Sopenharmony_ci{
146bf215546Sopenharmony_ci   if (st->has_hw_atomics) {
147bf215546Sopenharmony_ci      st_bind_hw_atomic_buffers(st);
148bf215546Sopenharmony_ci      return;
149bf215546Sopenharmony_ci   }
150bf215546Sopenharmony_ci   struct gl_program *prog =
151bf215546Sopenharmony_ci      st->ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   st_bind_atomics(st, prog, MESA_SHADER_COMPUTE);
154bf215546Sopenharmony_ci}
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_civoid
157bf215546Sopenharmony_cist_bind_hw_atomic_buffers(struct st_context *st)
158bf215546Sopenharmony_ci{
159bf215546Sopenharmony_ci   struct pipe_shader_buffer buffers[PIPE_MAX_HW_ATOMIC_BUFFERS];
160bf215546Sopenharmony_ci   int i;
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   if (!st->has_hw_atomics)
163bf215546Sopenharmony_ci      return;
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   for (i = 0; i < st->ctx->Const.MaxAtomicBufferBindings; i++)
166bf215546Sopenharmony_ci      st_binding_to_sb(&st->ctx->AtomicBufferBindings[i], &buffers[i], 1);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   st->pipe->set_hw_atomic_buffers(st->pipe, 0, st->ctx->Const.MaxAtomicBufferBindings, buffers);
169bf215546Sopenharmony_ci}
170