xref: /third_party/mesa3d/src/mesa/main/barrier.c (revision bf215546)
1/*
2 * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24/**
25 * \file barrier.c
26 * Implementation of various pipeline barrier entry points.
27 *
28 * \author Marek Olšák <maraeo@gmail.com>
29 */
30
31#include "context.h"
32#include "api_exec_decl.h"
33
34#include "pipe/p_context.h"
35
36
37static void
38memory_barrier(struct gl_context *ctx, GLbitfield barriers)
39{
40   struct pipe_context *pipe = ctx->pipe;
41   unsigned flags = 0;
42
43   if (barriers & GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT)
44      flags |= PIPE_BARRIER_VERTEX_BUFFER;
45   if (barriers & GL_ELEMENT_ARRAY_BARRIER_BIT)
46      flags |= PIPE_BARRIER_INDEX_BUFFER;
47   if (barriers & GL_UNIFORM_BARRIER_BIT)
48      flags |= PIPE_BARRIER_CONSTANT_BUFFER;
49   if (barriers & GL_TEXTURE_FETCH_BARRIER_BIT)
50      flags |= PIPE_BARRIER_TEXTURE;
51   if (barriers & GL_SHADER_IMAGE_ACCESS_BARRIER_BIT)
52      flags |= PIPE_BARRIER_IMAGE;
53   if (barriers & GL_COMMAND_BARRIER_BIT)
54      flags |= PIPE_BARRIER_INDIRECT_BUFFER;
55   if (barriers & GL_PIXEL_BUFFER_BARRIER_BIT) {
56      /* The PBO may be
57       *  (1) bound as a texture for PBO uploads, or
58       *  (2) accessed by the CPU via transfer ops.
59       * For case (2), we assume automatic flushing by the driver.
60       */
61      flags |= PIPE_BARRIER_TEXTURE;
62   }
63   if (barriers & GL_TEXTURE_UPDATE_BARRIER_BIT) {
64      /* GL_TEXTURE_UPDATE_BARRIER_BIT:
65       * Texture updates translate to:
66       *  (1) texture transfers to/from the CPU,
67       *  (2) texture as blit destination, or
68       *  (3) texture as framebuffer.
69       * Some drivers may handle these automatically, and can ignore the bit.
70       */
71      flags |= PIPE_BARRIER_UPDATE_TEXTURE;
72   }
73   if (barriers & GL_BUFFER_UPDATE_BARRIER_BIT) {
74      /* GL_BUFFER_UPDATE_BARRIER_BIT:
75       * Buffer updates translate to
76       *  (1) buffer transfers to/from the CPU,
77       *  (2) resource copies and clears.
78       * Some drivers may handle these automatically, and can ignore the bit.
79       */
80      flags |= PIPE_BARRIER_UPDATE_BUFFER;
81   }
82   if (barriers & GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT)
83      flags |= PIPE_BARRIER_MAPPED_BUFFER;
84   if (barriers & GL_QUERY_BUFFER_BARRIER_BIT)
85      flags |= PIPE_BARRIER_QUERY_BUFFER;
86   if (barriers & GL_FRAMEBUFFER_BARRIER_BIT)
87      flags |= PIPE_BARRIER_FRAMEBUFFER;
88   if (barriers & GL_TRANSFORM_FEEDBACK_BARRIER_BIT)
89      flags |= PIPE_BARRIER_STREAMOUT_BUFFER;
90   if (barriers & GL_ATOMIC_COUNTER_BARRIER_BIT)
91      flags |= PIPE_BARRIER_SHADER_BUFFER;
92   if (barriers & GL_SHADER_STORAGE_BARRIER_BIT)
93      flags |= PIPE_BARRIER_SHADER_BUFFER;
94
95   if (flags && pipe->memory_barrier)
96      pipe->memory_barrier(pipe, flags);
97}
98
99void GLAPIENTRY
100_mesa_TextureBarrierNV(void)
101{
102   GET_CURRENT_CONTEXT(ctx);
103
104   if (!ctx->Extensions.NV_texture_barrier) {
105      _mesa_error(ctx, GL_INVALID_OPERATION,
106                  "glTextureBarrier(not supported)");
107      return;
108   }
109
110   ctx->pipe->texture_barrier(ctx->pipe, PIPE_TEXTURE_BARRIER_SAMPLER);
111}
112
113void GLAPIENTRY
114_mesa_MemoryBarrier(GLbitfield barriers)
115{
116   GET_CURRENT_CONTEXT(ctx);
117
118   memory_barrier(ctx, barriers);
119}
120
121static ALWAYS_INLINE void
122memory_barrier_by_region(struct gl_context *ctx, GLbitfield barriers,
123                         bool no_error)
124{
125   GLbitfield all_allowed_bits = GL_ATOMIC_COUNTER_BARRIER_BIT |
126                                 GL_FRAMEBUFFER_BARRIER_BIT |
127                                 GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
128                                 GL_SHADER_STORAGE_BARRIER_BIT |
129                                 GL_TEXTURE_FETCH_BARRIER_BIT |
130                                 GL_UNIFORM_BARRIER_BIT;
131
132   /* From section 7.11.2 of the OpenGL ES 3.1 specification:
133    *
134    *    "When barriers is ALL_BARRIER_BITS, shader memory accesses will be
135    *     synchronized relative to all these barrier bits, but not to other
136    *     barrier bits specific to MemoryBarrier."
137    *
138    * That is, if barriers is the special value GL_ALL_BARRIER_BITS, then all
139    * barriers allowed by glMemoryBarrierByRegion should be activated."
140    */
141   if (barriers == GL_ALL_BARRIER_BITS) {
142      memory_barrier(ctx, all_allowed_bits);
143      return;
144   }
145
146   /* From section 7.11.2 of the OpenGL ES 3.1 specification:
147    *
148    *    "An INVALID_VALUE error is generated if barriers is not the special
149    *     value ALL_BARRIER_BITS, and has any bits set other than those
150    *     described above."
151    */
152   if (!no_error && (barriers & ~all_allowed_bits) != 0) {
153      _mesa_error(ctx, GL_INVALID_VALUE,
154                  "glMemoryBarrierByRegion(unsupported barrier bit");
155   }
156
157   memory_barrier(ctx, barriers);
158}
159
160void GLAPIENTRY
161_mesa_MemoryBarrierByRegion_no_error(GLbitfield barriers)
162{
163   GET_CURRENT_CONTEXT(ctx);
164   memory_barrier_by_region(ctx, barriers, true);
165}
166
167void GLAPIENTRY
168_mesa_MemoryBarrierByRegion(GLbitfield barriers)
169{
170   GET_CURRENT_CONTEXT(ctx);
171   memory_barrier_by_region(ctx, barriers, false);
172}
173
174void GLAPIENTRY
175_mesa_BlendBarrier(void)
176{
177   GET_CURRENT_CONTEXT(ctx);
178
179   if (!ctx->Extensions.KHR_blend_equation_advanced) {
180      _mesa_error(ctx, GL_INVALID_OPERATION,
181                  "glBlendBarrier(not supported)");
182      return;
183   }
184
185   ctx->pipe->texture_barrier(ctx->pipe, PIPE_TEXTURE_BARRIER_FRAMEBUFFER);
186}
187
188void GLAPIENTRY
189_mesa_FramebufferFetchBarrierEXT(void)
190{
191   GET_CURRENT_CONTEXT(ctx);
192
193   if (!ctx->Extensions.EXT_shader_framebuffer_fetch_non_coherent) {
194      _mesa_error(ctx, GL_INVALID_OPERATION,
195                  "glFramebufferFetchBarrierEXT(not supported)");
196      return;
197   }
198
199   ctx->pipe->texture_barrier(ctx->pipe, PIPE_TEXTURE_BARRIER_FRAMEBUFFER);
200}
201