test_glsl_shader.py 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573
  1. from panda3d import core
  2. import os
  3. import struct
  4. import pytest
  5. from _pytest.outcomes import Failed
  6. SHADERS_DIR = core.Filename.from_os_specific(os.path.dirname(__file__))
  7. # This is the template for the compute shader that is used by run_glsl_test.
  8. # It defines an assert() macro that writes failures to a buffer, indexed by
  9. # line number.
  10. # The reset() function serves to prevent the _triggered variable from being
  11. # optimized out in the case that the assertions are being optimized out.
  12. GLSL_COMPUTE_TEMPLATE = """#version {version}
  13. {extensions}
  14. layout(local_size_x = 1, local_size_y = 1) in;
  15. {preamble}
  16. layout(r8ui) uniform writeonly uimageBuffer _triggered;
  17. void _reset() {{
  18. imageStore(_triggered, 0, uvec4(1));
  19. memoryBarrier();
  20. }}
  21. void _assert(bool cond, int line) {{
  22. if (!cond) {{
  23. imageStore(_triggered, line, uvec4(1));
  24. }}
  25. }}
  26. #define assert(cond) _assert(cond, __LINE__ - line_offset)
  27. void main() {{
  28. _reset();
  29. const int line_offset = __LINE__;
  30. {body}
  31. }}
  32. """
  33. # This is a version that uses a vertex and fragment shader instead. This is
  34. # slower to set up, but it works even when compute shaders are not supported.
  35. # The shader is rendered on a fullscreen triangle to a texture, where each
  36. # pixel represents one line of the code. The assert writes the result to the
  37. # output color if the current fragment matches the line number of that assert.
  38. # The first pixel is used as a control, to check that the shader has run.
  39. GLSL_VERTEX_TEMPLATE = """#version {version}
  40. in vec4 p3d_Vertex;
  41. void main() {{
  42. gl_Position = p3d_Vertex;
  43. }}
  44. """
  45. GLSL_FRAGMENT_TEMPLATE = """#version {version}
  46. {extensions}
  47. {preamble}
  48. layout(location = 0) out vec4 p3d_FragColor;
  49. void _reset() {{
  50. p3d_FragColor = vec4(0, 0, 0, 0);
  51. if (int(gl_FragCoord.x) == 0) {{
  52. p3d_FragColor = vec4(1, 1, 1, 1);
  53. }}
  54. }}
  55. void _assert(bool cond, int line) {{
  56. if (int(gl_FragCoord.x) == line) {{
  57. p3d_FragColor = vec4(!cond, !cond, !cond, !cond);
  58. }}
  59. }}
  60. #define assert(cond) _assert(cond, __LINE__ - line_offset)
  61. void main() {{
  62. _reset();
  63. const int line_offset = __LINE__;
  64. {body}
  65. }}
  66. """
  67. def run_glsl_test(gsg, body, preamble="", inputs={}, version=420, exts=set(),
  68. state=core.RenderState.make_empty()):
  69. """ Runs a GLSL test on the given GSG. The given body is executed in the
  70. main function and should call assert(). The preamble should contain all
  71. of the shader inputs. """
  72. if not gsg.supports_basic_shaders:
  73. pytest.skip("shaders not supported")
  74. use_compute = gsg.supports_compute_shaders and \
  75. gsg.supports_buffer_texture and \
  76. (gsg.supported_shader_capabilities & core.Shader.C_image_load_store) != 0
  77. missing_exts = sorted(ext for ext in exts if not gsg.has_extension(ext))
  78. if missing_exts:
  79. pytest.skip("missing extensions: " + ' '.join(missing_exts))
  80. if use_compute:
  81. exts = exts | {'GL_ARB_compute_shader', 'GL_ARB_shader_image_load_store'}
  82. extensions = ''
  83. for ext in exts:
  84. extensions += '#extension {ext} : require\n'.format(ext=ext)
  85. __tracebackhide__ = True
  86. preamble = preamble.strip()
  87. body = body.rstrip().lstrip('\n')
  88. if use_compute:
  89. code = GLSL_COMPUTE_TEMPLATE.format(version=version, extensions=extensions, preamble=preamble, body=body)
  90. shader = core.Shader.make_compute(core.Shader.SL_GLSL, code)
  91. else:
  92. vertex_code = GLSL_VERTEX_TEMPLATE.format(version=version, extensions=extensions, preamble=preamble, body=body)
  93. code = GLSL_FRAGMENT_TEMPLATE.format(version=version, extensions=extensions, preamble=preamble, body=body)
  94. shader = core.Shader.make(core.Shader.SL_GLSL, vertex_code, code)
  95. if not shader:
  96. pytest.fail("error compiling shader:\n" + code)
  97. unsupported_caps = shader.get_used_capabilities() & ~gsg.supported_shader_capabilities
  98. if unsupported_caps != 0:
  99. stream = core.StringStream()
  100. core.ShaderEnums.output_capabilities(stream, unsupported_caps)
  101. pytest.skip("unsupported capabilities: " + stream.data.decode('ascii'))
  102. num_lines = body.count('\n') + 1
  103. # Create a buffer to hold the results of the assertion. We use one texel
  104. # per line of shader code, so we can show which lines triggered.
  105. engine = gsg.get_engine()
  106. result = core.Texture("")
  107. if use_compute:
  108. result.set_clear_color((0, 0, 0, 0))
  109. result.setup_buffer_texture(num_lines + 1, core.Texture.T_unsigned_byte,
  110. core.Texture.F_r8i, core.GeomEnums.UH_static)
  111. else:
  112. fbprops = core.FrameBufferProperties()
  113. fbprops.force_hardware = True
  114. fbprops.set_rgba_bits(8, 8, 8, 8)
  115. fbprops.srgb_color = False
  116. buffer = engine.make_output(
  117. gsg.pipe,
  118. 'buffer',
  119. 0,
  120. fbprops,
  121. core.WindowProperties.size(core.Texture.up_to_power_2(num_lines + 1), 1),
  122. core.GraphicsPipe.BF_refuse_window,
  123. gsg
  124. )
  125. buffer.add_render_texture(result, core.GraphicsOutput.RTM_copy_ram, core.GraphicsOutput.RTP_color)
  126. buffer.set_clear_color_active(True)
  127. buffer.set_clear_color((0, 0, 0, 0))
  128. engine.open_windows()
  129. # Build up the shader inputs
  130. attrib = core.ShaderAttrib.make(shader)
  131. for name, value in inputs.items():
  132. attrib = attrib.set_shader_input(name, value)
  133. if use_compute:
  134. attrib = attrib.set_shader_input('_triggered', result)
  135. state = state.set_attrib(attrib)
  136. # Run the shader.
  137. if use_compute:
  138. try:
  139. engine.dispatch_compute((1, 1, 1), state, gsg)
  140. except AssertionError as exc:
  141. assert False, "Error executing compute shader:\n" + code
  142. else:
  143. scene = core.NodePath("root")
  144. scene.set_attrib(core.DepthTestAttrib.make(core.RenderAttrib.M_always))
  145. format = core.GeomVertexFormat.get_v3()
  146. vdata = core.GeomVertexData("tri", format, core.Geom.UH_static)
  147. vdata.unclean_set_num_rows(3)
  148. vertex = core.GeomVertexWriter(vdata, "vertex")
  149. vertex.set_data3(-1, -1, 0)
  150. vertex.set_data3(3, -1, 0)
  151. vertex.set_data3(-1, 3, 0)
  152. tris = core.GeomTriangles(core.Geom.UH_static)
  153. tris.add_next_vertices(3)
  154. geom = core.Geom(vdata)
  155. geom.add_primitive(tris)
  156. gnode = core.GeomNode("tri")
  157. gnode.add_geom(geom, state)
  158. scene.attach_new_node(gnode)
  159. scene.set_two_sided(True)
  160. camera = scene.attach_new_node(core.Camera("camera"))
  161. camera.node().get_lens(0).set_near_far(-10, 10)
  162. camera.node().set_cull_bounds(core.OmniBoundingVolume())
  163. region = buffer.make_display_region()
  164. region.active = True
  165. region.camera = camera
  166. try:
  167. engine.render_frame()
  168. except AssertionError as exc:
  169. assert False, "Error executing shader:\n" + code
  170. finally:
  171. engine.remove_window(buffer)
  172. # Download the texture to check whether the assertion triggered.
  173. if use_compute:
  174. success = engine.extract_texture_data(result, gsg)
  175. assert success
  176. triggered = result.get_ram_image()
  177. if use_compute:
  178. triggered = tuple(triggered)
  179. else:
  180. triggered = tuple(memoryview(triggered).cast('I'))
  181. if not triggered[0]:
  182. pytest.fail("control check failed")
  183. if any(triggered[1:]):
  184. count = len(triggered) - triggered.count(0) - 1
  185. lines = body.split('\n')
  186. formatted = ''
  187. for i, line in enumerate(lines):
  188. if triggered[i + 1]:
  189. formatted += '=> ' + line + '\n'
  190. else:
  191. formatted += ' ' + line + '\n'
  192. pytest.fail("{0} GLSL assertions triggered:\n{1}".format(count, formatted))
  193. def run_glsl_compile_check(gsg, vert_path, frag_path, expect_fail=False):
  194. """Compile supplied GLSL shader paths and check for errors"""
  195. shader = core.Shader.load(core.Shader.SL_GLSL, vert_path, frag_path)
  196. if expect_fail:
  197. assert shader is None
  198. return
  199. assert shader is not None
  200. if not gsg.supports_glsl:
  201. expect_fail = True
  202. shader.prepare_now(gsg.prepared_objects, gsg)
  203. assert shader.is_prepared(gsg.prepared_objects)
  204. if expect_fail:
  205. assert shader.get_error_flag()
  206. else:
  207. assert not shader.get_error_flag()
  208. def test_glsl_test(gsg):
  209. "Test to make sure that the GLSL tests work correctly."
  210. run_glsl_test(gsg, "assert(true);")
  211. def test_glsl_test_fail(gsg):
  212. "Same as above, but making sure that the failure case works correctly."
  213. with pytest.raises(Failed):
  214. run_glsl_test(gsg, "assert(false);")
  215. def test_glsl_sampler(gsg):
  216. tex1 = core.Texture("tex1-ubyte-rgba8")
  217. tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8)
  218. tex1.set_clear_color((0, 2 / 255.0, 1, 1))
  219. tex2 = core.Texture("tex2-float-rgba32")
  220. tex2.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_rgba32)
  221. tex2.set_clear_color((1.0, 2.0, -3.14, 0.0))
  222. tex3 = core.Texture("tex3-float-r32")
  223. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_float, core.Texture.F_r32)
  224. tex3.set_clear_color((0.5, 0.0, 0.0, 1.0))
  225. preamble = """
  226. uniform sampler1D tex1;
  227. uniform sampler2D tex2;
  228. uniform sampler3D tex3;
  229. """
  230. code = """
  231. assert(texture(tex1, 0) == vec4(0, 2 / 255.0, 1, 1));
  232. assert(texture(tex2, vec2(0, 0)) == vec4(1.0, 2.0, -3.14, 0.0));
  233. assert(texture(tex3, vec3(0, 0, 0)).r == 0.5);
  234. """
  235. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  236. def test_glsl_isampler(gsg):
  237. from struct import pack
  238. tex1 = core.Texture("")
  239. tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i)
  240. tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3))
  241. tex2 = core.Texture("")
  242. tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i)
  243. tex2.set_ram_image(pack('h', 4))
  244. tex3 = core.Texture("")
  245. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i)
  246. tex3.set_ram_image(pack('i', 5))
  247. preamble = """
  248. uniform isampler1D tex1;
  249. uniform isampler2D tex2;
  250. uniform isampler3D tex3;
  251. """
  252. code = """
  253. assert(texelFetch(tex1, 0, 0) == ivec4(0, 1, 2, 3));
  254. assert(texelFetch(tex2, ivec2(0, 0), 0) == ivec4(4, 0, 0, 1));
  255. assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == ivec4(5, 0, 0, 1));
  256. """
  257. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  258. def test_glsl_usampler(gsg):
  259. from struct import pack
  260. tex1 = core.Texture("")
  261. tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i)
  262. tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3))
  263. tex2 = core.Texture("")
  264. tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i)
  265. tex2.set_ram_image(pack('H', 4))
  266. tex3 = core.Texture("")
  267. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i)
  268. tex3.set_ram_image(pack('I', 5))
  269. preamble = """
  270. uniform usampler1D tex1;
  271. uniform usampler2D tex2;
  272. uniform usampler3D tex3;
  273. """
  274. code = """
  275. assert(texelFetch(tex1, 0, 0) == uvec4(0, 1, 2, 3));
  276. assert(texelFetch(tex2, ivec2(0, 0), 0) == uvec4(4, 0, 0, 1));
  277. assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == uvec4(5, 0, 0, 1));
  278. """
  279. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  280. def test_glsl_image(gsg):
  281. tex1 = core.Texture("")
  282. tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8)
  283. tex1.set_clear_color((0, 2 / 255.0, 1, 1))
  284. tex2 = core.Texture("")
  285. tex2.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_rgba32)
  286. tex2.set_clear_color((1.0, 2.0, -3.14, 0.0))
  287. preamble = """
  288. layout(rgba8) uniform image1D tex1;
  289. layout(rgba32f) uniform image2D tex2;
  290. """
  291. code = """
  292. assert(imageLoad(tex1, 0) == vec4(0, 2 / 255.0, 1, 1));
  293. assert(imageLoad(tex2, ivec2(0, 0)) == vec4(1.0, 2.0, -3.14, 0.0));
  294. """
  295. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
  296. def test_glsl_iimage(gsg):
  297. from struct import pack
  298. tex1 = core.Texture("")
  299. tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i)
  300. tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3))
  301. tex2 = core.Texture("")
  302. tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i)
  303. tex2.set_ram_image(pack('h', 4))
  304. tex3 = core.Texture("")
  305. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i)
  306. tex3.set_ram_image(pack('i', 5))
  307. preamble = """
  308. layout(rgba8i) uniform iimage1D tex1;
  309. layout(r16i) uniform iimage2D tex2;
  310. layout(r32i) uniform iimage3D tex3;
  311. """
  312. code = """
  313. assert(imageLoad(tex1, 0) == ivec4(0, 1, 2, 3));
  314. assert(imageLoad(tex2, ivec2(0, 0)) == ivec4(4, 0, 0, 1));
  315. assert(imageLoad(tex3, ivec3(0, 0, 0)) == ivec4(5, 0, 0, 1));
  316. """
  317. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  318. def test_glsl_uimage(gsg):
  319. from struct import pack
  320. tex1 = core.Texture("")
  321. tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i)
  322. tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3))
  323. tex2 = core.Texture("")
  324. tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i)
  325. tex2.set_ram_image(pack('H', 4))
  326. tex3 = core.Texture("")
  327. tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i)
  328. tex3.set_ram_image(pack('I', 5))
  329. preamble = """
  330. layout(rgba8ui) uniform uimage1D tex1;
  331. layout(r16ui) uniform uimage2D tex2;
  332. layout(r32ui) uniform uimage3D tex3;
  333. """
  334. code = """
  335. assert(imageLoad(tex1, 0) == uvec4(0, 1, 2, 3));
  336. assert(imageLoad(tex2, ivec2(0, 0)) == uvec4(4, 0, 0, 1));
  337. assert(imageLoad(tex3, ivec3(0, 0, 0)) == uvec4(5, 0, 0, 1));
  338. """
  339. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
  340. def test_glsl_ssbo(gsg):
  341. from struct import pack
  342. num1 = pack('<i', 1234567)
  343. num2 = pack('<i', -1234567)
  344. buffer1 = core.ShaderBuffer("buffer1", num1, core.GeomEnums.UH_static)
  345. buffer2 = core.ShaderBuffer("buffer2", num2, core.GeomEnums.UH_static)
  346. buffer3 = core.ShaderBuffer("buffer3", 4, core.GeomEnums.UH_static)
  347. preamble = """
  348. layout(std430, binding=0) readonly buffer buffer1 {
  349. int value1;
  350. };
  351. layout(std430, binding=1) buffer buffer2 {
  352. readonly int value2;
  353. };
  354. layout(std430, binding=3) buffer buffer3 {
  355. writeonly int value3;
  356. int value4;
  357. };
  358. """
  359. # Assigning value3 to 999 first proves buffers aren't accidentally aliased
  360. code = """
  361. value3 = 999;
  362. assert(value1 == 1234567);
  363. assert(value2 == -1234567);
  364. """
  365. run_glsl_test(gsg, code, preamble,
  366. {'buffer1': buffer1, 'buffer2': buffer2, 'buffer3': buffer3},
  367. version=430)
  368. def test_glsl_ssbo_array(gsg):
  369. from struct import pack
  370. dummy = pack('<i', 999999)
  371. num1 = pack('<i', 1234567)
  372. num2 = pack('<i', -1234567)
  373. unused = core.ShaderBuffer("unused", dummy, core.GeomEnums.UH_static)
  374. buffer1 = core.ShaderBuffer("buffer1", num1, core.GeomEnums.UH_static)
  375. buffer2 = core.ShaderBuffer("buffer2", num2, core.GeomEnums.UH_static)
  376. preamble = """
  377. struct InsideStruct {
  378. int value;
  379. };
  380. layout(std430, binding=0) buffer test {
  381. readonly InsideStruct inside[1];
  382. } test_ns[3];
  383. """
  384. code = """
  385. assert(test_ns[1].inside[0].value == 1234567);
  386. assert(test_ns[2].inside[0].value == -1234567);
  387. """
  388. run_glsl_test(gsg, code, preamble,
  389. {'test[0]': unused, 'test[1]': buffer1, 'test[2]': buffer2},
  390. version=430)
  391. def test_glsl_ssbo_runtime_length(gsg):
  392. from struct import pack
  393. nums = pack('<ii', 1234, 5678)
  394. ssbo = core.ShaderBuffer("ssbo", nums, core.GeomEnums.UH_static)
  395. preamble = """
  396. layout(std430, binding=0) buffer ssbo {
  397. int values[];
  398. };
  399. """
  400. code = """
  401. assert(values.length() == 2);
  402. assert(values[0] == 1234);
  403. assert(values[1] == 5678);
  404. """
  405. run_glsl_test(gsg, code, preamble, {'ssbo': ssbo}, version=430)
  406. def test_glsl_float(gsg):
  407. inputs = dict(
  408. zero=0,
  409. a=1.23,
  410. b=-829.123,
  411. )
  412. preamble = """
  413. uniform float zero;
  414. uniform float a;
  415. uniform float b;
  416. """
  417. code = """
  418. assert(zero == 0);
  419. assert(abs(a - 1.23) < 0.001);
  420. assert(abs(b - -829.123) < 0.001);
  421. """
  422. run_glsl_test(gsg, code, preamble, inputs)
  423. def test_glsl_int(gsg):
  424. inputs = dict(
  425. zero=0,
  426. intmax=0x7fffffff,
  427. intmin=-0x7fffffff,
  428. )
  429. preamble = """
  430. uniform int zero;
  431. uniform int intmax;
  432. uniform int intmin;
  433. """
  434. code = """
  435. assert(zero == 0);
  436. assert(intmax == 0x7fffffff);
  437. assert(intmin == -0x7fffffff);
  438. """
  439. run_glsl_test(gsg, code, preamble, inputs)
  440. def test_glsl_uint(gsg):
  441. #TODO: fix passing uints greater than intmax
  442. inputs = dict(
  443. zero=0,
  444. intmax=0x7fffffff,
  445. )
  446. preamble = """
  447. uniform uint zero;
  448. uniform uint intmax;
  449. """
  450. code = """
  451. assert(zero == 0u);
  452. assert(intmax == 0x7fffffffu);
  453. """
  454. run_glsl_test(gsg, code, preamble, inputs)
  455. #@pytest.mark.xfail(reason="https://github.com/KhronosGroup/SPIRV-Tools/issues/3387")
  456. def test_glsl_bool(gsg):
  457. flags = dict(
  458. flag1=False,
  459. flag2=0,
  460. flag3=0.0,
  461. flag4=True,
  462. flag5=1,
  463. flag6=3,
  464. )
  465. preamble = """
  466. uniform bool flag1;
  467. uniform bool flag2;
  468. uniform bool flag3;
  469. uniform bool flag4;
  470. uniform bool flag5;
  471. uniform bool flag6;
  472. """
  473. code = """
  474. assert(!flag1);
  475. assert(!flag2);
  476. assert(!flag3);
  477. assert(flag4);
  478. assert(flag5);
  479. assert(flag6);
  480. """
  481. run_glsl_test(gsg, code, preamble, flags)
  482. def test_glsl_mat3(gsg):
  483. param1 = core.LMatrix4f(core.LMatrix3f(1, 2, 3, 4, 5, 6, 7, 8, 9))
  484. param2 = core.LMatrix4d(core.LMatrix3d(10, 11, 12, 13, 14, 15, 16, 17, 18))
  485. param3 = core.NodePath("param3")
  486. param3.set_mat(core.LMatrix3(19, 20, 21, 22, 23, 24, 25, 26, 27))
  487. preamble = """
  488. uniform mat3 param1;
  489. uniform mat3 param2;
  490. uniform mat3 param3;
  491. """
  492. code = """
  493. assert(param1[0] == vec3(1, 2, 3));
  494. assert(param1[1] == vec3(4, 5, 6));
  495. assert(param1[2] == vec3(7, 8, 9));
  496. assert(param2[0] == vec3(10, 11, 12));
  497. assert(param2[1] == vec3(13, 14, 15));
  498. assert(param2[2] == vec3(16, 17, 18));
  499. assert(param3[0] == vec3(19, 20, 21));
  500. assert(param3[1] == vec3(22, 23, 24));
  501. assert(param3[2] == vec3(25, 26, 27));
  502. """
  503. run_glsl_test(gsg, code, preamble,
  504. {'param1': param1, 'param2': param2, 'param3': param3})
  505. def test_glsl_mat4(gsg):
  506. param1 = core.LMatrix4f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
  507. param2 = core.LMatrix4d(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)
  508. param3 = core.NodePath("param3")
  509. param3.set_mat(core.LMatrix4(
  510. 33, 34, 35, 36,
  511. 37, 38, 39, 40,
  512. 41, 42, 43, 44,
  513. 45, 46, 47, 48))
  514. preamble = """
  515. uniform mat4 param1;
  516. uniform mat4 param2;
  517. uniform mat4 param3;
  518. """
  519. code = """
  520. assert(param1[0] == vec4(1, 2, 3, 4));
  521. assert(param1[1] == vec4(5, 6, 7, 8));
  522. assert(param1[2] == vec4(9, 10, 11, 12));
  523. assert(param1[3] == vec4(13, 14, 15, 16));
  524. assert(param2[0] == vec4(17, 18, 19, 20));
  525. assert(param2[1] == vec4(21, 22, 23, 24));
  526. assert(param2[2] == vec4(25, 26, 27, 28));
  527. assert(param2[3] == vec4(29, 30, 31, 32));
  528. assert(param3[0] == vec4(33, 34, 35, 36));
  529. assert(param3[1] == vec4(37, 38, 39, 40));
  530. assert(param3[2] == vec4(41, 42, 43, 44));
  531. assert(param3[3] == vec4(45, 46, 47, 48));
  532. """
  533. run_glsl_test(gsg, code, preamble,
  534. {'param1': param1, 'param2': param2, 'param3': param3})
  535. def test_glsl_mat3x4(gsg):
  536. param1 = core.LMatrix4f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
  537. param2 = core.LMatrix4d(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)
  538. preamble = """
  539. uniform mat3x4 param1;
  540. uniform mat3x4 param2;
  541. """
  542. code = """
  543. assert(param1[0] == vec4(1, 2, 3, 4));
  544. assert(param1[1] == vec4(5, 6, 7, 8));
  545. assert(param1[2] == vec4(9, 10, 11, 12));
  546. assert(param2[0] == vec4(17, 18, 19, 20));
  547. assert(param2[1] == vec4(21, 22, 23, 24));
  548. assert(param2[2] == vec4(25, 26, 27, 28));
  549. """
  550. run_glsl_test(gsg, code, preamble,
  551. {'param1': param1, 'param2': param2})
  552. def test_glsl_mat4x3(gsg):
  553. param1 = core.LMatrix4f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
  554. param2 = core.LMatrix4d(17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32)
  555. preamble = """
  556. uniform mat4x3 param1;
  557. uniform mat4x3 param2;
  558. uniform mat4x3 param3;
  559. """
  560. code = """
  561. assert(param1[0] == vec3(1, 2, 3));
  562. assert(param1[1] == vec3(5, 6, 7));
  563. assert(param1[2] == vec3(9, 10, 11));
  564. assert(param1[3] == vec3(13, 14, 15));
  565. assert(param2[0] == vec3(17, 18, 19));
  566. assert(param2[1] == vec3(21, 22, 23));
  567. assert(param2[2] == vec3(25, 26, 27));
  568. assert(param2[3] == vec3(29, 30, 31));
  569. """
  570. run_glsl_test(gsg, code, preamble,
  571. {'param1': param1, 'param2': param2})
  572. def test_glsl_pta_int(gsg):
  573. pta = core.PTA_int((0, 1, 2, 3))
  574. preamble = """
  575. uniform int pta[4];
  576. """
  577. code = """
  578. assert(pta[0] == 0);
  579. assert(pta[1] == 1);
  580. assert(pta[2] == 2);
  581. assert(pta[3] == 3);
  582. """
  583. run_glsl_test(gsg, code, preamble, {'pta': pta})
  584. def test_glsl_pta_ivec4(gsg):
  585. pta = core.PTA_LVecBase4i(((0, 1, 2, 3), (4, 5, 6, 7)))
  586. preamble = """
  587. uniform ivec4 pta[2];
  588. """
  589. code = """
  590. assert(pta[0] == ivec4(0, 1, 2, 3));
  591. assert(pta[1] == ivec4(4, 5, 6, 7));
  592. """
  593. run_glsl_test(gsg, code, preamble, {'pta': pta})
  594. @pytest.mark.parametrize("type", (core.PTA_LVecBase3f, core.PTA_LVecBase3d, core.PTA_LVecBase3i))
  595. def test_glsl_pta_vec3(gsg, type):
  596. pta = type((
  597. (0, 1, 2),
  598. (3, 4, 5),
  599. (6, 7, 8),
  600. ))
  601. preamble = """
  602. uniform vec3 pta[3];
  603. """
  604. code = """
  605. assert(pta[0] == vec3(0, 1, 2));
  606. assert(pta[1] == vec3(3, 4, 5));
  607. assert(pta[2] == vec3(6, 7, 8));
  608. """
  609. run_glsl_test(gsg, code, preamble, {'pta': pta})
  610. @pytest.mark.parametrize("type", (core.PTA_LVecBase3f, core.PTA_LVecBase3d, core.PTA_LVecBase3i))
  611. def test_glsl_pta_dvec3(gsg, type):
  612. pta = type((
  613. (0, 1, 2),
  614. (3, 4, 5),
  615. (6, 7, 8),
  616. ))
  617. preamble = """
  618. uniform dvec3 pta[3];
  619. """
  620. code = """
  621. assert(pta[0] == vec3(0, 1, 2));
  622. assert(pta[1] == vec3(3, 4, 5));
  623. assert(pta[2] == vec3(6, 7, 8));
  624. """
  625. run_glsl_test(gsg, code, preamble, {'pta': pta})
  626. @pytest.mark.parametrize("type", (core.PTA_LVecBase4f, core.PTA_LVecBase4d, core.PTA_LVecBase4i))
  627. def test_glsl_pta_vec4(gsg, type):
  628. pta = type((
  629. (0, 1, 2, 3),
  630. (4, 5, 6, 7),
  631. (8, 9, 10, 11),
  632. ))
  633. preamble = """
  634. uniform vec4 pta[4];
  635. """
  636. code = """
  637. assert(pta[0] == vec4(0, 1, 2, 3));
  638. assert(pta[1] == vec4(4, 5, 6, 7));
  639. assert(pta[2] == vec4(8, 9, 10, 11));
  640. """
  641. run_glsl_test(gsg, code, preamble, {'pta': pta})
  642. @pytest.mark.parametrize("type", (core.PTA_LVecBase4f, core.PTA_LVecBase4d, core.PTA_LVecBase4i))
  643. def test_glsl_pta_dvec4(gsg, type):
  644. pta = type((
  645. (0, 1, 2, 3),
  646. (4, 5, 6, 7),
  647. (8, 9, 10, 11),
  648. ))
  649. preamble = """
  650. uniform dvec4 pta[4];
  651. """
  652. code = """
  653. assert(pta[0] == dvec4(0, 1, 2, 3));
  654. assert(pta[1] == dvec4(4, 5, 6, 7));
  655. assert(pta[2] == dvec4(8, 9, 10, 11));
  656. """
  657. run_glsl_test(gsg, code, preamble, {'pta': pta})
  658. @pytest.mark.parametrize("type", (core.PTA_LMatrix3f, core.PTA_LMatrix3d))
  659. def test_glsl_pta_mat3(gsg, type):
  660. pta = type((
  661. (0, 1, 2, 3, 4, 5, 6, 7, 8),
  662. (9, 10, 11, 12, 13, 14, 15, 16, 17),
  663. ))
  664. preamble = """
  665. uniform mat3 pta[2];
  666. """
  667. code = """
  668. assert(pta[0][0] == vec3(0, 1, 2));
  669. assert(pta[0][1] == vec3(3, 4, 5));
  670. assert(pta[0][2] == vec3(6, 7, 8));
  671. assert(pta[1][0] == vec3(9, 10, 11));
  672. assert(pta[1][1] == vec3(12, 13, 14));
  673. assert(pta[1][2] == vec3(15, 16, 17));
  674. """
  675. run_glsl_test(gsg, code, preamble, {'pta': pta})
  676. @pytest.mark.parametrize("type", (core.PTA_LMatrix4f, core.PTA_LMatrix4d))
  677. def test_glsl_pta_mat4(gsg, type):
  678. pta = type((
  679. (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
  680. (16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31),
  681. ))
  682. preamble = """
  683. uniform mat4 pta[2];
  684. """
  685. code = """
  686. assert(pta[0][0] == vec4(0, 1, 2, 3));
  687. assert(pta[0][1] == vec4(4, 5, 6, 7));
  688. assert(pta[0][2] == vec4(8, 9, 10, 11));
  689. assert(pta[0][3] == vec4(12, 13, 14, 15));
  690. assert(pta[1][0] == vec4(16, 17, 18, 19));
  691. assert(pta[1][1] == vec4(20, 21, 22, 23));
  692. assert(pta[1][2] == vec4(24, 25, 26, 27));
  693. assert(pta[1][3] == vec4(28, 29, 30, 31));
  694. """
  695. run_glsl_test(gsg, code, preamble, {'pta': pta})
  696. def test_glsl_param_vec4(gsg):
  697. param = core.ParamVecBase4((0, 1, 2, 3))
  698. preamble = """
  699. uniform vec4 param;
  700. """
  701. code = """
  702. assert(param.x == 0.0);
  703. assert(param.y == 1.0);
  704. assert(param.z == 2.0);
  705. assert(param.w == 3.0);
  706. """
  707. run_glsl_test(gsg, code, preamble, {'param': param})
  708. def test_glsl_param_ivec4(gsg):
  709. param = core.ParamVecBase4i((0, 1, 2, 3))
  710. preamble = """
  711. uniform ivec4 param;
  712. """
  713. code = """
  714. assert(param.x == 0);
  715. assert(param.y == 1);
  716. assert(param.z == 2);
  717. assert(param.w == 3);
  718. """
  719. run_glsl_test(gsg, code, preamble, {'param': param})
  720. def test_glsl_struct(gsg):
  721. preamble = """
  722. uniform struct TestStruct {
  723. vec3 a;
  724. float b;
  725. sampler2D c;
  726. float unused;
  727. vec3 d[2];
  728. vec2 e;
  729. sampler2D f;
  730. } test;
  731. """
  732. code = """
  733. assert(test.a == vec3(1, 2, 3));
  734. assert(test.b == 4);
  735. assert(texture(test.c, vec2(0, 0)).r == 5);
  736. assert(test.d[0] == vec3(6, 7, 8));
  737. assert(test.d[1] == vec3(9, 10, 11));
  738. assert(test.e == vec2(12, 13));
  739. assert(texture(test.f, vec2(0, 0)).r == 14);
  740. """
  741. tex_c = core.Texture('c')
  742. tex_c.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_r32)
  743. tex_c.set_clear_color((5, 0, 0, 0))
  744. tex_f = core.Texture('f')
  745. tex_f.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_r32)
  746. tex_f.set_clear_color((14, 0, 0, 0))
  747. run_glsl_test(gsg, code, preamble, {
  748. 'test.unused': 0,
  749. 'test.a': (1, 2, 3),
  750. 'test.b': 4,
  751. 'test.c': tex_c,
  752. 'test.d': [(6, 7, 8), (9, 10, 11)],
  753. 'test.e': [12, 13],
  754. 'test.f': tex_f,
  755. })
  756. def test_glsl_struct_nested(gsg):
  757. preamble = """
  758. struct TestSubStruct1 {
  759. float a;
  760. float b;
  761. };
  762. struct TestSubStruct2 {
  763. float unused;
  764. sampler2D a;
  765. vec2 b;
  766. };
  767. uniform struct TestStruct {
  768. vec3 a;
  769. TestSubStruct1 b;
  770. TestSubStruct2 c;
  771. float d;
  772. } test;
  773. """
  774. code = """
  775. assert(test.a == vec3(1, 2, 3));
  776. assert(test.b.a == 4);
  777. assert(test.b.b == 5);
  778. assert(texture(test.c.a, vec2(0, 0)).r == 6);
  779. assert(test.c.b == vec2(7, 8));
  780. assert(test.d == 9);
  781. """
  782. tex_c_a = core.Texture()
  783. tex_c_a.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_r32)
  784. tex_c_a.set_clear_color((6, 0, 0, 0))
  785. run_glsl_test(gsg, code, preamble, {
  786. 'test.unused': 0,
  787. 'test.a': (1, 2, 3),
  788. 'test.b.a': 4,
  789. 'test.b.b': 5,
  790. 'test.c.unused': 0,
  791. 'test.c.a': tex_c_a,
  792. 'test.c.b': (7, 8),
  793. 'test.d': 9,
  794. })
  795. def test_glsl_struct_array(gsg):
  796. preamble = """
  797. uniform struct TestStruct {
  798. vec3 a;
  799. sampler2D b;
  800. float unused;
  801. float c;
  802. } test[2];
  803. """
  804. code = """
  805. assert(test[0].a == vec3(1, 2, 3));
  806. assert(texture(test[0].b, vec2(0, 0)).r == 4);
  807. assert(test[0].c == 5);
  808. assert(test[1].a == vec3(6, 7, 8));
  809. assert(texture(test[1].b, vec2(0, 0)).r == 9);
  810. assert(test[1].c == 10);
  811. """
  812. tex_0_b = core.Texture()
  813. tex_0_b.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_r32)
  814. tex_0_b.set_clear_color((4, 0, 0, 0))
  815. tex_1_b = core.Texture()
  816. tex_1_b.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_r32)
  817. tex_1_b.set_clear_color((9, 0, 0, 0))
  818. run_glsl_test(gsg, code, preamble, {
  819. 'test[0].unused': 0,
  820. 'test[0].a': (1, 2, 3),
  821. 'test[0].b': tex_0_b,
  822. 'test[0].c': 5,
  823. 'test[1].unused': 0,
  824. 'test[1].a': (6, 7, 8),
  825. 'test[1].b': tex_1_b,
  826. 'test[1].c': 10,
  827. })
  828. def test_glsl_struct_pseudo_light(gsg):
  829. # Something that looks like a named light source, but isn't one at all
  830. preamble = """
  831. struct FakeLightParameters {
  832. vec4 specular;
  833. vec4 position;
  834. vec3 attenuation;
  835. float constantAttenuation;
  836. float radius;
  837. };
  838. uniform FakeLightParameters test;
  839. """
  840. code = """
  841. assert(test.specular == vec4(1, 2, 3, 4));
  842. assert(test.position == vec4(5, 6, 7, 8));
  843. assert(test.attenuation == vec3(9, 10, 11));
  844. assert(test.constantAttenuation == 12);
  845. assert(test.radius == 13);
  846. """
  847. run_glsl_test(gsg, code, preamble, {
  848. 'test.specular': (1, 2, 3, 4),
  849. 'test.position': (5, 6, 7, 8),
  850. 'test.attenuation': (9, 10, 11),
  851. 'test.constantAttenuation': 12,
  852. 'test.radius': 13,
  853. })
  854. def test_glsl_light(gsg):
  855. preamble = """
  856. uniform struct p3d_LightSourceParameters {
  857. vec4 color;
  858. vec3 ambient;
  859. vec4 diffuse;
  860. vec4 specular;
  861. vec3 position;
  862. vec4 halfVector;
  863. vec4 spotDirection;
  864. float spotCutoff;
  865. float spotCosCutoff;
  866. float spotExponent;
  867. vec3 attenuation;
  868. float constantAttenuation;
  869. float linearAttenuation;
  870. float quadraticAttenuation;
  871. } plight;
  872. """
  873. code = """
  874. assert(plight.color == vec4(1, 2, 3, 4));
  875. assert(plight.ambient == vec3(0, 0, 0));
  876. assert(plight.diffuse == vec4(1, 2, 3, 4));
  877. assert(plight.specular == vec4(5, 6, 7, 8));
  878. assert(plight.position == vec3(9, 10, 11));
  879. assert(plight.spotCutoff == 180);
  880. assert(plight.spotCosCutoff == -1);
  881. assert(plight.spotExponent == 0);
  882. assert(plight.attenuation == vec3(12, 13, 14));
  883. assert(plight.constantAttenuation == 12);
  884. assert(plight.linearAttenuation == 13);
  885. assert(plight.quadraticAttenuation == 14);
  886. """
  887. plight = core.PointLight("plight")
  888. plight.color = (1, 2, 3, 4)
  889. plight.specular_color = (5, 6, 7, 8)
  890. plight.transform = core.TransformState.make_pos((9, 10, 11))
  891. plight.attenuation = (12, 13, 14)
  892. run_glsl_test(gsg, code, preamble, {
  893. 'plight': core.NodePath(plight),
  894. })
  895. def test_glsl_named_light_source(gsg):
  896. spot = core.Spotlight("spot")
  897. spot.get_lens().set_fov(90, 90)
  898. spot.set_color((1, 2, 3, 4))
  899. spot.set_specular_color((5, 6, 7, 8))
  900. preamble = """
  901. struct p3d_LightSourceParameters {
  902. vec4 color;
  903. vec4 specular;
  904. };
  905. uniform p3d_LightSourceParameters spot;
  906. """
  907. code = """
  908. assert(spot.color == vec4(1, 2, 3, 4));
  909. assert(spot.specular == vec4(5, 6, 7, 8));
  910. """
  911. run_glsl_test(gsg, code, preamble, {'spot': core.NodePath(spot)})
  912. def test_glsl_state_light(gsg):
  913. preamble = """
  914. uniform struct p3d_LightSourceParameters {
  915. vec4 color;
  916. vec3 ambient;
  917. vec4 diffuse;
  918. vec4 specular;
  919. vec4 position;
  920. vec4 halfVector;
  921. vec4 spotDirection;
  922. float spotCutoff;
  923. float spotCosCutoff;
  924. float spotExponent;
  925. vec3 attenuation;
  926. float constantAttenuation;
  927. float linearAttenuation;
  928. float quadraticAttenuation;
  929. } p3d_LightSource[2];
  930. """
  931. code = """
  932. assert(p3d_LightSource[0].color == vec4(1, 2, 3, 4));
  933. assert(p3d_LightSource[0].ambient == vec3(0, 0, 0));
  934. assert(p3d_LightSource[0].diffuse == vec4(1, 2, 3, 4));
  935. assert(p3d_LightSource[0].specular == vec4(5, 6, 7, 8));
  936. assert(p3d_LightSource[0].position == vec4(9, 10, 11, 1));
  937. assert(p3d_LightSource[0].spotCutoff == 180);
  938. assert(p3d_LightSource[0].spotCosCutoff == -1);
  939. assert(p3d_LightSource[0].spotExponent == 0);
  940. assert(p3d_LightSource[0].attenuation == vec3(12, 13, 14));
  941. assert(p3d_LightSource[0].constantAttenuation == 12);
  942. assert(p3d_LightSource[0].linearAttenuation == 13);
  943. assert(p3d_LightSource[0].quadraticAttenuation == 14);
  944. assert(p3d_LightSource[1].color == vec4(15, 16, 17, 18));
  945. assert(p3d_LightSource[1].ambient == vec3(0, 0, 0));
  946. assert(p3d_LightSource[1].diffuse == vec4(15, 16, 17, 18));
  947. assert(p3d_LightSource[1].specular == vec4(19, 20, 21, 22));
  948. assert(p3d_LightSource[1].position == vec4(0, 1, 0, 0));
  949. assert(p3d_LightSource[1].spotCutoff == 180);
  950. assert(p3d_LightSource[1].spotCosCutoff == -1);
  951. assert(p3d_LightSource[1].spotExponent == 0);
  952. assert(p3d_LightSource[1].attenuation == vec3(1, 0, 0));
  953. assert(p3d_LightSource[1].constantAttenuation == 1);
  954. assert(p3d_LightSource[1].linearAttenuation == 0);
  955. assert(p3d_LightSource[1].quadraticAttenuation == 0);
  956. """
  957. plight = core.PointLight("plight")
  958. plight.priority = 0
  959. plight.color = (1, 2, 3, 4)
  960. plight.specular_color = (5, 6, 7, 8)
  961. plight.transform = core.TransformState.make_pos((9, 10, 11))
  962. plight.attenuation = (12, 13, 14)
  963. plight_path = core.NodePath(plight)
  964. dlight = core.DirectionalLight("dlight")
  965. dlight.priority = -1
  966. dlight.direction = (0, -1, 0)
  967. dlight.color = (15, 16, 17, 18)
  968. dlight.specular_color = (19, 20, 21, 22)
  969. dlight.transform = core.TransformState.make_pos((23, 24, 25))
  970. dlight_path = core.NodePath(dlight)
  971. lattr = core.LightAttrib.make()
  972. lattr = lattr.add_on_light(plight_path)
  973. lattr = lattr.add_on_light(dlight_path)
  974. state = core.RenderState.make(lattr)
  975. run_glsl_test(gsg, code, preamble, state=state)
  976. def test_glsl_state_light_source(gsg):
  977. spot = core.Spotlight("spot")
  978. spot.priority = 3
  979. spot.get_lens().set_fov(120, 120)
  980. spot.set_color((1, 2, 3, 4))
  981. spot.set_specular_color((5, 6, 7, 8))
  982. spot.attenuation = (23, 24, 25)
  983. spot.exponent = 26
  984. dire = core.DirectionalLight("dire")
  985. dire.priority = 2
  986. dire.set_color((9, 10, 11, 12))
  987. dire.set_specular_color((13, 14, 15, 16))
  988. dire.direction = (17, 18, 19)
  989. preamble = """
  990. struct p3d_LightSourceParameters {
  991. vec4 color;
  992. vec4 specular;
  993. vec4 ambient;
  994. vec4 diffuse;
  995. vec4 position;
  996. vec3 attenuation;
  997. float constantAttenuation;
  998. float linearAttenuation;
  999. float quadraticAttenuation;
  1000. float spotExponent;
  1001. float spotCosCutoff;
  1002. float spotCutoff;
  1003. mat4 shadowViewMatrix;
  1004. };
  1005. uniform p3d_LightSourceParameters p3d_LightSource[3];
  1006. """
  1007. code = """
  1008. assert(p3d_LightSource[0].color == vec4(1, 2, 3, 4));
  1009. assert(p3d_LightSource[0].specular == vec4(5, 6, 7, 8));
  1010. assert(p3d_LightSource[0].ambient == vec4(0, 0, 0, 1));
  1011. assert(p3d_LightSource[0].diffuse == vec4(1, 2, 3, 4));
  1012. assert(p3d_LightSource[0].position == vec4(20, 21, 22, 1));
  1013. assert(p3d_LightSource[0].attenuation == vec3(23, 24, 25));
  1014. assert(p3d_LightSource[0].constantAttenuation == 23);
  1015. assert(p3d_LightSource[0].linearAttenuation == 24);
  1016. assert(p3d_LightSource[0].quadraticAttenuation == 25);
  1017. assert(p3d_LightSource[0].spotExponent == 26);
  1018. assert(p3d_LightSource[0].spotCosCutoff > 0.499);
  1019. assert(p3d_LightSource[0].spotCosCutoff < 0.501);
  1020. assert(p3d_LightSource[0].spotCutoff == 60);
  1021. assert(p3d_LightSource[0].shadowViewMatrix[0][0] > 0.2886);
  1022. assert(p3d_LightSource[0].shadowViewMatrix[0][0] < 0.2887);
  1023. assert(p3d_LightSource[0].shadowViewMatrix[0][1] == 0);
  1024. assert(p3d_LightSource[0].shadowViewMatrix[0][2] == 0);
  1025. assert(p3d_LightSource[0].shadowViewMatrix[0][3] == 0);
  1026. assert(p3d_LightSource[0].shadowViewMatrix[1][0] == 0);
  1027. assert(p3d_LightSource[0].shadowViewMatrix[1][1] > 0.2886);
  1028. assert(p3d_LightSource[0].shadowViewMatrix[1][1] < 0.2887);
  1029. assert(p3d_LightSource[0].shadowViewMatrix[1][2] == 0);
  1030. assert(p3d_LightSource[0].shadowViewMatrix[1][3] == 0);
  1031. //assert(p3d_LightSource[0].shadowViewMatrix[2][0] == -0.5);
  1032. //assert(p3d_LightSource[0].shadowViewMatrix[2][1] == -0.5);
  1033. assert(p3d_LightSource[0].shadowViewMatrix[2][2] > -1.00002);
  1034. //assert(p3d_LightSource[0].shadowViewMatrix[2][2] < -1.0);
  1035. //assert(p3d_LightSource[0].shadowViewMatrix[2][3] == -1);
  1036. assert(p3d_LightSource[0].shadowViewMatrix[3][0] > -16.2736);
  1037. assert(p3d_LightSource[0].shadowViewMatrix[3][0] < -16.2734);
  1038. assert(p3d_LightSource[0].shadowViewMatrix[3][1] > -16.8510);
  1039. assert(p3d_LightSource[0].shadowViewMatrix[3][1] < -16.8508);
  1040. assert(p3d_LightSource[0].shadowViewMatrix[3][2] > -22.0003);
  1041. assert(p3d_LightSource[0].shadowViewMatrix[3][2] < -22.0001);
  1042. assert(p3d_LightSource[0].shadowViewMatrix[3][3] > -21.0001);
  1043. assert(p3d_LightSource[0].shadowViewMatrix[3][3] < -20.9999);
  1044. assert(p3d_LightSource[1].color == vec4(9, 10, 11, 12));
  1045. assert(p3d_LightSource[1].specular == vec4(13, 14, 15, 16));
  1046. assert(p3d_LightSource[1].diffuse == vec4(9, 10, 11, 12));
  1047. assert(p3d_LightSource[1].ambient == vec4(0, 0, 0, 1));
  1048. assert(p3d_LightSource[1].position == vec4(-17, -18, -19, 0));
  1049. assert(p3d_LightSource[1].attenuation == vec3(1, 0, 0));
  1050. assert(p3d_LightSource[1].constantAttenuation == 1);
  1051. assert(p3d_LightSource[1].linearAttenuation == 0);
  1052. assert(p3d_LightSource[1].quadraticAttenuation == 0);
  1053. assert(p3d_LightSource[1].spotExponent == 0);
  1054. assert(p3d_LightSource[1].spotCosCutoff == -1);
  1055. assert(p3d_LightSource[2].color == vec4(0, 0, 0, 1));
  1056. assert(p3d_LightSource[2].specular == vec4(0, 0, 0, 1));
  1057. assert(p3d_LightSource[2].diffuse == vec4(0, 0, 0, 1));
  1058. assert(p3d_LightSource[2].ambient == vec4(0, 0, 0, 1));
  1059. assert(p3d_LightSource[2].position == vec4(0, 0, 1, 0));
  1060. assert(p3d_LightSource[2].attenuation == vec3(1, 0, 0));
  1061. assert(p3d_LightSource[2].constantAttenuation == 1);
  1062. assert(p3d_LightSource[2].linearAttenuation == 0);
  1063. assert(p3d_LightSource[2].quadraticAttenuation == 0);
  1064. assert(p3d_LightSource[2].spotExponent == 0);
  1065. assert(p3d_LightSource[2].spotCosCutoff == -1);
  1066. """
  1067. node = core.NodePath("state")
  1068. spot_path = node.attach_new_node(spot)
  1069. spot_path.set_pos(20, 21, 22)
  1070. node.set_light(spot_path)
  1071. dire_path = node.attach_new_node(dire)
  1072. node.set_light(dire_path)
  1073. run_glsl_test(gsg, code, preamble, state=node.get_state())
  1074. def test_glsl_state_material(gsg):
  1075. mat = core.Material("mat")
  1076. mat.ambient = (1, 2, 3, 4)
  1077. mat.diffuse = (5, 6, 7, 8)
  1078. mat.emission = (9, 10, 11, 12)
  1079. mat.specular = (13, 14, 15, 0)
  1080. mat.shininess = 16
  1081. mat.metallic = 0.5
  1082. mat.refractive_index = 21
  1083. preamble = """
  1084. struct p3d_MaterialParameters {
  1085. vec4 ambient;
  1086. vec4 diffuse;
  1087. vec4 emission;
  1088. vec3 specular;
  1089. float shininess;
  1090. float metallic;
  1091. float refractiveIndex;
  1092. };
  1093. uniform p3d_MaterialParameters p3d_Material;
  1094. """
  1095. code = """
  1096. assert(p3d_Material.ambient == vec4(1, 2, 3, 4));
  1097. assert(p3d_Material.diffuse == vec4(5, 6, 7, 8));
  1098. assert(p3d_Material.emission == vec4(9, 10, 11, 12));
  1099. assert(p3d_Material.specular == vec3(13, 14, 15));
  1100. assert(p3d_Material.shininess == 16);
  1101. assert(p3d_Material.metallic == 0.5);
  1102. assert(p3d_Material.refractiveIndex == 21);
  1103. """
  1104. node = core.NodePath("state")
  1105. node.set_material(mat)
  1106. run_glsl_test(gsg, code, preamble, state=node.get_state())
  1107. def test_glsl_state_material_pbr(gsg):
  1108. mat = core.Material("mat")
  1109. mat.base_color = (1, 2, 3, 4)
  1110. mat.emission = (9, 10, 11, 12)
  1111. mat.roughness = 16
  1112. mat.metallic = 0.5
  1113. mat.refractive_index = 21
  1114. preamble = """
  1115. struct p3d_MaterialParameters {
  1116. vec4 baseColor;
  1117. vec4 emission;
  1118. float metallic;
  1119. float refractiveIndex;
  1120. float roughness;
  1121. };
  1122. uniform p3d_MaterialParameters p3d_Material;
  1123. """
  1124. code = """
  1125. assert(p3d_Material.baseColor == vec4(1, 2, 3, 4));
  1126. assert(p3d_Material.emission == vec4(9, 10, 11, 12));
  1127. assert(p3d_Material.roughness == 16);
  1128. assert(p3d_Material.metallic == 0.5);
  1129. assert(p3d_Material.refractiveIndex == 21);
  1130. """
  1131. node = core.NodePath("state")
  1132. node.set_material(mat)
  1133. run_glsl_test(gsg, code, preamble, state=node.get_state())
  1134. def test_glsl_state_fog(gsg):
  1135. fog = core.Fog("fog")
  1136. fog.color = (1, 2, 3, 4)
  1137. fog.exp_density = 0.5
  1138. fog.set_linear_range(6, 10)
  1139. preamble = """
  1140. struct p3d_FogParameters {
  1141. vec4 color;
  1142. float density;
  1143. float start;
  1144. float end;
  1145. float scale;
  1146. };
  1147. uniform p3d_FogParameters p3d_Fog;
  1148. """
  1149. code = """
  1150. assert(p3d_Fog.color == vec4(1, 2, 3, 4));
  1151. assert(p3d_Fog.density == 0.5);
  1152. assert(p3d_Fog.start == 6);
  1153. assert(p3d_Fog.end == 10);
  1154. assert(p3d_Fog.scale == 0.25);
  1155. """
  1156. node = core.NodePath("state")
  1157. node.set_fog(fog)
  1158. run_glsl_test(gsg, code, preamble, state=node.get_state())
  1159. def test_glsl_state_texture(gsg):
  1160. def gen_texture(v):
  1161. tex = core.Texture(f"tex{v}")
  1162. tex.setup_2d_texture(1, 1, core.Texture.T_unsigned_byte, core.Texture.F_red)
  1163. tex.set_clear_color((v / 255.0, 0, 0, 0))
  1164. return tex
  1165. np = core.NodePath("test")
  1166. ts1 = core.TextureStage("ts1")
  1167. ts1.sort = 10
  1168. ts1.mode = core.TextureStage.M_modulate
  1169. np.set_texture(ts1, gen_texture(1))
  1170. ts2 = core.TextureStage("ts2")
  1171. ts2.sort = 20
  1172. ts2.mode = core.TextureStage.M_add
  1173. np.set_texture(ts2, gen_texture(2))
  1174. ts3 = core.TextureStage("ts3")
  1175. ts3.sort = 30
  1176. ts3.mode = core.TextureStage.M_modulate
  1177. np.set_texture(ts3, gen_texture(3))
  1178. ts4 = core.TextureStage("ts4")
  1179. ts4.sort = 40
  1180. ts4.mode = core.TextureStage.M_normal_height
  1181. np.set_texture(ts4, gen_texture(4))
  1182. ts5 = core.TextureStage("ts5")
  1183. ts5.sort = 50
  1184. ts5.mode = core.TextureStage.M_add
  1185. np.set_texture(ts5, gen_texture(5))
  1186. ts6 = core.TextureStage("ts6")
  1187. ts6.sort = 60
  1188. ts6.mode = core.TextureStage.M_normal
  1189. np.set_texture(ts6, gen_texture(6))
  1190. # Do this in multiple passes to stay under sampler limit of 16
  1191. preamble = """
  1192. uniform sampler2D p3d_Texture2;
  1193. uniform sampler2D p3d_Texture0;
  1194. uniform sampler2D p3d_Texture1;
  1195. uniform sampler2D p3d_Texture3;
  1196. uniform sampler2D p3d_Texture4;
  1197. uniform sampler2D p3d_Texture5;
  1198. uniform sampler2D p3d_Texture6;
  1199. uniform sampler2D p3d_Texture[7];
  1200. """
  1201. code = """
  1202. vec2 coord = vec2(0, 0);
  1203. assert(abs(texture(p3d_Texture2, coord).r - 3.0 / 255.0) < 0.001);
  1204. assert(abs(texture(p3d_Texture0, coord).r - 1.0 / 255.0) < 0.001);
  1205. assert(abs(texture(p3d_Texture1, coord).r - 2.0 / 255.0) < 0.001);
  1206. assert(abs(texture(p3d_Texture3, coord).r - 4.0 / 255.0) < 0.001);
  1207. assert(abs(texture(p3d_Texture4, coord).r - 5.0 / 255.0) < 0.001);
  1208. assert(abs(texture(p3d_Texture5, coord).r - 6.0 / 255.0) < 0.001);
  1209. assert(texture(p3d_Texture6, coord).r == 1.0);
  1210. assert(abs(texture(p3d_Texture[0], coord).r - 1.0 / 255.0) < 0.001);
  1211. assert(abs(texture(p3d_Texture[2], coord).r - 3.0 / 255.0) < 0.001);
  1212. assert(abs(texture(p3d_Texture[3], coord).r - 4.0 / 255.0) < 0.001);
  1213. assert(abs(texture(p3d_Texture[1], coord).r - 2.0 / 255.0) < 0.001);
  1214. assert(abs(texture(p3d_Texture[4], coord).r - 5.0 / 255.0) < 0.001);
  1215. assert(abs(texture(p3d_Texture[5], coord).r - 6.0 / 255.0) < 0.001);
  1216. assert(texture(p3d_Texture[6], coord).r == 1.0);
  1217. """
  1218. run_glsl_test(gsg, code, preamble, state=np.get_state())
  1219. preamble = """
  1220. uniform sampler2D p3d_TextureFF[5];
  1221. uniform sampler2D p3d_TextureModulate[3];
  1222. uniform sampler2D p3d_TextureAdd[3];
  1223. uniform sampler2D p3d_TextureNormal[3];
  1224. uniform sampler2D p3d_TextureHeight[2];
  1225. """
  1226. code = """
  1227. vec2 coord = vec2(0, 0);
  1228. assert(abs(texture(p3d_TextureFF[0], coord).r - 1.0 / 255.0) < 0.001);
  1229. assert(abs(texture(p3d_TextureFF[1], coord).r - 2.0 / 255.0) < 0.001);
  1230. assert(abs(texture(p3d_TextureFF[2], coord).r - 3.0 / 255.0) < 0.001);
  1231. assert(abs(texture(p3d_TextureFF[3], coord).r - 5.0 / 255.0) < 0.001);
  1232. assert(texture(p3d_TextureFF[4], coord).r == 1.0);
  1233. assert(abs(texture(p3d_TextureModulate[0], coord).r - 1.0 / 255.0) < 0.001);
  1234. assert(abs(texture(p3d_TextureModulate[1], coord).r - 3.0 / 255.0) < 0.001);
  1235. assert(texture(p3d_TextureModulate[2], coord).r == 1.0);
  1236. assert(abs(texture(p3d_TextureAdd[0], coord).r - 2.0 / 255.0) < 0.001);
  1237. assert(abs(texture(p3d_TextureAdd[1], coord).r - 5.0 / 255.0) < 0.001);
  1238. assert(texture(p3d_TextureAdd[2], coord) == vec4(0.0, 0.0, 0.0, 1.0));
  1239. assert(abs(texture(p3d_TextureNormal[0], coord).r - 4.0 / 255.0) < 0.001);
  1240. assert(abs(texture(p3d_TextureNormal[1], coord).r - 6.0 / 255.0) < 0.001);
  1241. assert(all(lessThan(abs(texture(p3d_TextureNormal[2], coord) - vec4(127 / 255.0, 127 / 255.0, 1.0, 0.0)), vec4(0.004))));
  1242. assert(texture(p3d_TextureHeight[0], coord).r == 4.0 / 255.0);
  1243. assert(all(lessThan(abs(texture(p3d_TextureHeight[1], coord) - vec4(127 / 255.0, 127 / 255.0, 1.0, 0.0)), vec4(0.004))));
  1244. """
  1245. run_glsl_test(gsg, code, preamble, state=np.get_state())
  1246. def test_glsl_frame_number(gsg):
  1247. clock = core.ClockObject.get_global_clock()
  1248. old_frame_count = clock.get_frame_count()
  1249. try:
  1250. clock.set_frame_count(123)
  1251. preamble = """
  1252. uniform int osg_FrameNumber;
  1253. """
  1254. code = """
  1255. assert(osg_FrameNumber == 123);
  1256. """
  1257. run_glsl_test(gsg, code, preamble)
  1258. finally:
  1259. clock.set_frame_count(old_frame_count)
  1260. def test_glsl_write_extract_image_buffer(gsg):
  1261. # Tests that we can write to a buffer texture on the GPU, and then extract
  1262. # the data on the CPU. We test two textures since there was in the past a
  1263. # where it would only work correctly for one texture.
  1264. tex1 = core.Texture("tex1")
  1265. tex1.set_clear_color(0)
  1266. tex1.setup_buffer_texture(1, core.Texture.T_unsigned_int, core.Texture.F_r32i,
  1267. core.GeomEnums.UH_static)
  1268. tex2 = core.Texture("tex2")
  1269. tex2.set_clear_color(0)
  1270. tex2.setup_buffer_texture(1, core.Texture.T_int, core.Texture.F_r32i,
  1271. core.GeomEnums.UH_static)
  1272. preamble = """
  1273. layout(r32ui) uniform uimageBuffer tex1;
  1274. layout(r32i) uniform iimageBuffer tex2;
  1275. """
  1276. code = """
  1277. assert(imageLoad(tex1, 0).r == 0u);
  1278. assert(imageLoad(tex2, 0).r == 0);
  1279. imageStore(tex1, 0, uvec4(123));
  1280. imageStore(tex2, 0, ivec4(-456));
  1281. memoryBarrier();
  1282. assert(imageLoad(tex1, 0).r == 123u);
  1283. assert(imageLoad(tex2, 0).r == -456);
  1284. """
  1285. run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
  1286. engine = core.GraphicsEngine.get_global_ptr()
  1287. assert engine.extract_texture_data(tex1, gsg)
  1288. assert engine.extract_texture_data(tex2, gsg)
  1289. assert struct.unpack('I', tex1.get_ram_image()) == (123,)
  1290. assert struct.unpack('i', tex2.get_ram_image()) == (-456,)
  1291. def test_glsl_compile_error(gsg):
  1292. """Test getting compile errors from bad shaders"""
  1293. suffix = ''
  1294. if gsg.pipe.interface_name == "OpenGL" and \
  1295. (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  1296. suffix = '_legacy'
  1297. vert_path = core.Filename(SHADERS_DIR, 'glsl_bad' + suffix + '.vert')
  1298. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  1299. run_glsl_compile_check(gsg, vert_path, frag_path, expect_fail=True)
  1300. def test_glsl_from_file(gsg):
  1301. """Test compiling GLSL shaders from files"""
  1302. suffix = ''
  1303. if gsg.pipe.interface_name == "OpenGL" and \
  1304. (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  1305. suffix = '_legacy'
  1306. vert_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.vert')
  1307. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  1308. run_glsl_compile_check(gsg, vert_path, frag_path)
  1309. def test_glsl_includes(gsg):
  1310. """Test preprocessing includes in GLSL shaders"""
  1311. suffix = ''
  1312. if gsg.pipe.interface_name == "OpenGL" and \
  1313. (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  1314. suffix = '_legacy'
  1315. vert_path = core.Filename(SHADERS_DIR, 'glsl_include' + suffix + '.vert')
  1316. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  1317. run_glsl_compile_check(gsg, vert_path, frag_path)
  1318. def test_glsl_includes_angle_nodir(gsg):
  1319. """Test preprocessing includes with angle includes without model-path"""
  1320. suffix = ''
  1321. if gsg.pipe.interface_name == "OpenGL" and \
  1322. (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  1323. suffix = '_legacy'
  1324. vert_path = core.Filename(SHADERS_DIR, 'glsl_include_angle' + suffix + '.vert')
  1325. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  1326. assert core.Shader.load(core.Shader.SL_GLSL, vert_path, frag_path) is None
  1327. @pytest.fixture
  1328. def with_current_dir_on_model_path():
  1329. model_path = core.get_model_path()
  1330. model_path.prepend_directory(core.Filename.from_os_specific(os.path.dirname(__file__)))
  1331. yield
  1332. model_path.clear_local_value()
  1333. def test_glsl_includes_angle_withdir(gsg, with_current_dir_on_model_path):
  1334. """Test preprocessing includes with angle includes with model-path"""
  1335. suffix = ''
  1336. if gsg.pipe.interface_name == "OpenGL" and \
  1337. (gsg.driver_shader_version_major, gsg.driver_shader_version_minor) < (1, 50):
  1338. suffix = '_legacy'
  1339. vert_path = core.Filename(SHADERS_DIR, 'glsl_include_angle' + suffix + '.vert')
  1340. frag_path = core.Filename(SHADERS_DIR, 'glsl_simple' + suffix + '.frag')
  1341. run_glsl_compile_check(gsg, vert_path, frag_path)