effects_rd.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /**************************************************************************/
  2. /* effects_rd.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "effects_rd.h"
  31. #include "core/config/project_settings.h"
  32. #include "core/math/math_defs.h"
  33. #include "core/os/os.h"
  34. #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
  35. #include "thirdparty/misc/cubemap_coeffs.h"
  36. bool EffectsRD::get_prefer_raster_effects() {
  37. return prefer_raster_effects;
  38. }
  39. RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
  40. if (image_to_uniform_set_cache.has(p_image)) {
  41. RID uniform_set = image_to_uniform_set_cache[p_image];
  42. if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
  43. return uniform_set;
  44. }
  45. }
  46. Vector<RD::Uniform> uniforms;
  47. RD::Uniform u;
  48. u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
  49. u.binding = 0;
  50. u.append_id(p_image);
  51. uniforms.push_back(u);
  52. //any thing with the same configuration (one texture in binding 0 for set 0), is good
  53. RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0), 1);
  54. image_to_uniform_set_cache[p_image] = uniform_set;
  55. return uniform_set;
  56. }
  57. RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
  58. if (texture_to_compute_uniform_set_cache.has(p_texture)) {
  59. RID uniform_set = texture_to_compute_uniform_set_cache[p_texture];
  60. if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
  61. return uniform_set;
  62. }
  63. }
  64. Vector<RD::Uniform> uniforms;
  65. RD::Uniform u;
  66. u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
  67. u.binding = 0;
  68. u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
  69. u.append_id(p_texture);
  70. uniforms.push_back(u);
  71. //any thing with the same configuration (one texture in binding 0 for set 0), is good
  72. RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0), 0);
  73. texture_to_compute_uniform_set_cache[p_texture] = uniform_set;
  74. return uniform_set;
  75. }
  76. void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) {
  77. roughness_limiter.push_constant.screen_size[0] = p_size.x;
  78. roughness_limiter.push_constant.screen_size[1] = p_size.y;
  79. roughness_limiter.push_constant.curve = p_curve;
  80. RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
  81. RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness_limiter.pipeline);
  82. RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_normal), 0);
  83. RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_roughness), 1);
  84. RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness_limiter.push_constant, sizeof(RoughnessLimiterPushConstant)); //not used but set anyway
  85. RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_size.x, p_size.y, 1);
  86. RD::get_singleton()->compute_list_end();
  87. }
  88. void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
  89. Sort::PushConstant push_constant;
  90. push_constant.total_elements = p_size;
  91. bool done = true;
  92. int numThreadGroups = ((p_size - 1) >> 9) + 1;
  93. if (numThreadGroups > 1) {
  94. done = false;
  95. }
  96. RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
  97. RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sort.pipelines[SORT_MODE_BLOCK]);
  98. RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_uniform_set, 1);
  99. RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(Sort::PushConstant));
  100. RD::get_singleton()->compute_list_dispatch(compute_list, numThreadGroups, 1, 1);
  101. int presorted = 512;
  102. while (!done) {
  103. RD::get_singleton()->compute_list_add_barrier(compute_list);
  104. done = true;
  105. RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sort.pipelines[SORT_MODE_STEP]);
  106. numThreadGroups = 0;
  107. if (p_size > presorted) {
  108. if (p_size > presorted * 2) {
  109. done = false;
  110. }
  111. int pow2 = presorted;
  112. while (pow2 < p_size) {
  113. pow2 *= 2;
  114. }
  115. numThreadGroups = pow2 >> 9;
  116. }
  117. unsigned int nMergeSize = presorted * 2;
  118. for (unsigned int nMergeSubSize = nMergeSize >> 1; nMergeSubSize > 256; nMergeSubSize = nMergeSubSize >> 1) {
  119. push_constant.job_params[0] = nMergeSubSize;
  120. if (nMergeSubSize == nMergeSize >> 1) {
  121. push_constant.job_params[1] = (2 * nMergeSubSize - 1);
  122. push_constant.job_params[2] = -1;
  123. } else {
  124. push_constant.job_params[1] = nMergeSubSize;
  125. push_constant.job_params[2] = 1;
  126. }
  127. push_constant.job_params[3] = 0;
  128. RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(Sort::PushConstant));
  129. RD::get_singleton()->compute_list_dispatch(compute_list, numThreadGroups, 1, 1);
  130. RD::get_singleton()->compute_list_add_barrier(compute_list);
  131. }
  132. RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sort.pipelines[SORT_MODE_INNER]);
  133. RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(Sort::PushConstant));
  134. RD::get_singleton()->compute_list_dispatch(compute_list, numThreadGroups, 1, 1);
  135. presorted *= 2;
  136. }
  137. RD::get_singleton()->compute_list_end();
  138. }
  139. EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
  140. prefer_raster_effects = p_prefer_raster_effects;
  141. if (!prefer_raster_effects) {
  142. // Initialize roughness limiter
  143. Vector<String> shader_modes;
  144. shader_modes.push_back("");
  145. roughness_limiter.shader.initialize(shader_modes);
  146. roughness_limiter.shader_version = roughness_limiter.shader.version_create();
  147. roughness_limiter.pipeline = RD::get_singleton()->compute_pipeline_create(roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0));
  148. }
  149. {
  150. Vector<String> sort_modes;
  151. sort_modes.push_back("\n#define MODE_SORT_BLOCK\n");
  152. sort_modes.push_back("\n#define MODE_SORT_STEP\n");
  153. sort_modes.push_back("\n#define MODE_SORT_INNER\n");
  154. sort.shader.initialize(sort_modes);
  155. sort.shader_version = sort.shader.version_create();
  156. for (int i = 0; i < SORT_MODE_MAX; i++) {
  157. sort.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sort.shader.version_get_shader(sort.shader_version, i));
  158. }
  159. }
  160. RD::SamplerState sampler;
  161. sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
  162. sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
  163. sampler.max_lod = 0;
  164. default_sampler = RD::get_singleton()->sampler_create(sampler);
  165. RD::get_singleton()->set_resource_name(default_sampler, "Default Linear Sampler");
  166. sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
  167. sampler.mip_filter = RD::SAMPLER_FILTER_LINEAR;
  168. sampler.max_lod = 1e20;
  169. default_mipmap_sampler = RD::get_singleton()->sampler_create(sampler);
  170. RD::get_singleton()->set_resource_name(default_mipmap_sampler, "Default MipMap Sampler");
  171. { //create index array for copy shaders
  172. Vector<uint8_t> pv;
  173. pv.resize(6 * 4);
  174. {
  175. uint8_t *w = pv.ptrw();
  176. int *p32 = (int *)w;
  177. p32[0] = 0;
  178. p32[1] = 1;
  179. p32[2] = 2;
  180. p32[3] = 0;
  181. p32[4] = 2;
  182. p32[5] = 3;
  183. }
  184. index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
  185. index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6);
  186. }
  187. }
  188. EffectsRD::~EffectsRD() {
  189. RD::get_singleton()->free(default_sampler);
  190. RD::get_singleton()->free(default_mipmap_sampler);
  191. RD::get_singleton()->free(index_buffer); //array gets freed as dependency
  192. if (!prefer_raster_effects) {
  193. roughness_limiter.shader.version_free(roughness_limiter.shader_version);
  194. }
  195. sort.shader.version_free(sort.shader_version);
  196. }