If you are still using GameMaker: Studio instead of moving to a more current version
(perhaps you should - it's been almost five years since GMS1 support has ended)
and you are doing extension work or anything else that demands conversions
between raw pixel data and surfaces on Windows, you might have noticed that
buffer_set_surface doesn't work on some computers - no matter what you pass in,
no pixels appear on the surface.
Though the better way to put it would be "
buffer_set_surface doesn't work anymore".
This is a post about the matter.
Once upon a time, I filed
a bug report
buffer_set_surface not working on Intel GPUs (while working fine on an NVIDIA GPU).
The report was later closed due to likely being a driver bug.
Imagine my surprise when I ran the same code on the same GameMaker: Studio version half a decade later and found that it now doesn't work on NVIDIA GPUs either... but it still works on AMD! And in WINE. And on any GPU in GMS2 (which uses D3D11 instead of D3D9).
Is this a bug in two drivers?
Without getting into D3D9 trickery, the most obvious alternative is to simply plot the pixels into the surface.
You can do this in GML itself, but that can get a little slow due to dynamic nature of the language, so a better alternative is to utilize a trick from a few years back to call a built-in function from C++ code.
- For reasons perhaps related to CPU caching, the function starts working a bunch faster after the first few times you call it.
- The fallback function calls
draw_set_blend_mode_extand then sets it back to
draw_set_blend_mode(bm_normal), which is a thing to keep in mind if you use the function amid blend mode manipulations for some reason.
And that's all. You can find the compiled extension on itch and source code on GitHub.