Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gl_nir_link_xfb.c 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Copyright © 2018 Intel Corporation
  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 DEALINGS
  21. * IN THE SOFTWARE.
  22. */
  23. #include "nir.h"
  24. #include "nir_xfb_info.h"
  25. #include "gl_nir_linker.h"
  26. #include "linker_util.h"
  27. #include "main/context.h"
  28. #include "util/u_math.h"
  29. /*
  30. * This file does the linking of GLSL transform feedback using NIR.
  31. *
  32. * Note: This linking pass is currently tailored for ARB_gl_spirv needs and
  33. * particularities.
  34. */
  35. void
  36. gl_nir_link_assign_xfb_resources(struct gl_context *ctx,
  37. struct gl_shader_program *prog)
  38. {
  39. /*
  40. * From ARB_gl_spirv spec:
  41. *
  42. * "- If the *Xfb* Execution Mode is set, any output variable that is at
  43. * least partially captured:
  44. * * must be decorated with an *XfbBuffer*, declaring the capturing buffer
  45. * * must have at least one captured output variable in the capturing
  46. * buffer decorated with an *XfbStride* (and all such *XfbStride* values
  47. * for the capturing buffer must be equal)
  48. * - If the *Xfb* Execution Mode is set, any captured output:
  49. * * must be a non-structure decorated with *Offset* or a member of a
  50. * structure whose type member is decorated with *Offset*"
  51. *
  52. * Note the "must be", meaning that explicit buffer, offset and stride are
  53. * mandatory. So as this is intended to work with SPIR-V shaders we don't
  54. * need to calculate the offset or the stride.
  55. */
  56. struct gl_program *xfb_prog = prog->last_vert_prog;
  57. if (xfb_prog == NULL)
  58. return;
  59. /* free existing varyings, if any */
  60. for (unsigned i = 0; i < prog->TransformFeedback.NumVarying; i++)
  61. free(prog->TransformFeedback.VaryingNames[i]);
  62. free(prog->TransformFeedback.VaryingNames);
  63. nir_xfb_info *xfb_info = NULL;
  64. /* Find last stage before fragment shader */
  65. for (int stage = MESA_SHADER_FRAGMENT - 1; stage >= 0; stage--) {
  66. struct gl_linked_shader *sh = prog->_LinkedShaders[stage];
  67. if (sh && stage != MESA_SHADER_TESS_CTRL) {
  68. xfb_info = nir_gather_xfb_info(sh->Program->nir, NULL);
  69. break;
  70. }
  71. }
  72. struct gl_transform_feedback_info *linked_xfb =
  73. rzalloc(xfb_prog, struct gl_transform_feedback_info);
  74. xfb_prog->sh.LinkedTransformFeedback = linked_xfb;
  75. if (!xfb_info) {
  76. prog->TransformFeedback.NumVarying = 0;
  77. linked_xfb->NumOutputs = 0;
  78. linked_xfb->NumVarying = 0;
  79. linked_xfb->ActiveBuffers = 0;
  80. return;
  81. }
  82. for (unsigned buf = 0; buf < MAX_FEEDBACK_BUFFERS; buf++)
  83. prog->TransformFeedback.BufferStride[buf] = xfb_info->buffers[buf].stride;
  84. prog->TransformFeedback.NumVarying = xfb_info->varying_count;
  85. prog->TransformFeedback.VaryingNames =
  86. malloc(sizeof(GLchar *) * xfb_info->varying_count);
  87. linked_xfb->Outputs =
  88. rzalloc_array(xfb_prog,
  89. struct gl_transform_feedback_output,
  90. xfb_info->output_count);
  91. linked_xfb->NumOutputs = xfb_info->output_count;
  92. linked_xfb->Varyings =
  93. rzalloc_array(xfb_prog,
  94. struct gl_transform_feedback_varying_info,
  95. xfb_info->varying_count);
  96. linked_xfb->NumVarying = xfb_info->varying_count;
  97. int buffer_index = 0; /* Corresponds to GL_TRANSFORM_FEEDBACK_BUFFER_INDEX */
  98. int xfb_buffer =
  99. (xfb_info->varying_count > 0) ?
  100. xfb_info->outputs[0].buffer : 0;
  101. for (unsigned i = 0; i < xfb_info->varying_count; i++) {
  102. nir_xfb_varying_info *xfb_varying = &xfb_info->varyings[i];
  103. /* From ARB_gl_spirv spec:
  104. *
  105. * "19. How should the program interface query operations behave for
  106. * program objects created from SPIR-V shaders?
  107. *
  108. * DISCUSSION: we previously said we didn't need reflection to work
  109. * for SPIR-V shaders (at least for the first version), however we
  110. * are left with specifying how it should "not work". The primary
  111. * issue is that SPIR-V binaries are not required to have names
  112. * associated with variables. They can be associated in debug
  113. * information, but there is no requirement for that to be present,
  114. * and it should not be relied upon."
  115. *
  116. * Options:"
  117. *
  118. * <skip>
  119. *
  120. * "RESOLVED. Pick (c), but also allow debug names to be returned
  121. * if an implementation wants to."
  122. *
  123. * So names are considered optional debug info, so the linker needs to
  124. * work without them, and returning them is optional. For simplicity at
  125. * this point we are ignoring names
  126. */
  127. prog->TransformFeedback.VaryingNames[i] = NULL;
  128. if (xfb_buffer != xfb_varying->buffer) {
  129. buffer_index++;
  130. xfb_buffer = xfb_varying->buffer;
  131. }
  132. struct gl_transform_feedback_varying_info *varying =
  133. linked_xfb->Varyings + i;
  134. /* ARB_gl_spirv: see above. */
  135. varying->Name = NULL;
  136. varying->Type = glsl_get_gl_type(xfb_varying->type);
  137. varying->BufferIndex = buffer_index;
  138. varying->Size = glsl_type_is_array(xfb_varying->type) ?
  139. glsl_get_length(xfb_varying->type) : 1;
  140. varying->Offset = xfb_varying->offset;
  141. }
  142. for (unsigned i = 0; i < xfb_info->output_count; i++) {
  143. nir_xfb_output_info *xfb_output = &xfb_info->outputs[i];
  144. struct gl_transform_feedback_output *output =
  145. linked_xfb->Outputs + i;
  146. output->OutputRegister = xfb_output->location;
  147. output->OutputBuffer = xfb_output->buffer;
  148. output->NumComponents = util_bitcount(xfb_output->component_mask);
  149. output->StreamId = xfb_info->buffer_to_stream[xfb_output->buffer];
  150. output->DstOffset = xfb_output->offset / 4;
  151. output->ComponentOffset = xfb_output->component_offset;
  152. }
  153. /* Make sure MaxTransformFeedbackBuffers is <= 32 so the bitmask for
  154. * tracking the number of buffers doesn't overflow.
  155. */
  156. unsigned buffers = 0;
  157. assert(ctx->Const.MaxTransformFeedbackBuffers <= sizeof(buffers) * 8);
  158. for (unsigned buf = 0; buf < MAX_FEEDBACK_BUFFERS; buf++) {
  159. if (xfb_info->buffers[buf].stride > 0) {
  160. linked_xfb->Buffers[buf].Stride = xfb_info->buffers[buf].stride / 4;
  161. linked_xfb->Buffers[buf].NumVaryings = xfb_info->buffers[buf].varying_count;
  162. buffers |= 1 << buf;
  163. }
  164. }
  165. linked_xfb->ActiveBuffers = buffers;
  166. ralloc_free(xfb_info);
  167. }