Commit e7478816 authored by pcy's avatar pcy
Browse files

prepare stuff for texture support

parent 0ff4087d
......@@ -6,19 +6,18 @@ the `Effect` API as much as possible. (Which isn't always working.)
## Does it work?
Kinda. Static shaders work. Passing vertex data is very hacky and brittle.
Uniforms, samples/textures, ... don't work at all yet. Using regular shaders
interleaved w/ GLSL shader draw calls seems to work ok.
Uniforms seem to work, but aren't well-tested. Samples/textures, ... don't
work at all yet. Using regular shaders interleaved w/ GLSL shader draw calls
seems to work ok.
## How does this work?
No. Don't.
No. Don't. Here be dragons.
## Are there things it can't do?
Yes:
* No uniform support (this is being worked on! FNA/mojoshader internals might
throw a wrench tho)
* No texture support (will have to be researched)
* Passing this to a `SpriteBatch` will probably fail in a bad way (unlikely
to be fixed).
......@@ -34,6 +33,8 @@ var glsl = new GLSLEffect(GraphicsDevice, new Dictionary<GLSLPurpose, string>()
// ...
glsl.Parameters["paramname"].SetValueT(xyz);
using (var bound = glsl.Bind())
{
GraphicsDevice.DrawPrimitives(/*...*/);
......
......@@ -20,7 +20,6 @@ using Microsoft.Xna.Framework.Graphics;
* --> circumvent? --> HOW??
* --> just go with it?? --> glProgramReady ok, glProgramViewportInfo might segfault!
*
* * uniforms
* * samplers, textures
* -> https://www.khronos.org/opengl/wiki/Program_Introspection
* -> https://stackoverflow.com/questions/440144/in-opengl-is-there-a-way-to-get-a-list-of-all-uniforms-attribs-used-by-a-shade#442819
......@@ -48,10 +47,11 @@ namespace PoroCYon.FNAGLSL {
public partial class GLSLEffect : Effect {
public struct ActiveEffect : IDisposable {
internal uint oldprgm;
internal List<uint> texs;
bool disposed;
internal ActiveEffect(uint old) {
oldprgm = old; disposed = false;
internal ActiveEffect(uint old, List<uint> ts) {
oldprgm = old; disposed = false; texs = ts;
}
public void Dispose() {
......@@ -60,6 +60,12 @@ namespace PoroCYon.FNAGLSL {
GL.UseProgram(oldprgm);
oldprgm = 0;
// TODO: release textures
/*for (int i = 0; i < texs.Length; ++i) {
}*/
texs.Clear();
disposed = true;
}
}
......@@ -153,10 +159,10 @@ namespace PoroCYon.FNAGLSL {
}
}
readonly static EffectParameterCollection emptyParamColl
/*readonly static EffectParameterCollection emptyParamColl
= ReflUtil.CreateParamColl(new List<EffectParameter >());
readonly static EffectAnnotationCollection emptyAnnotColl
= ReflUtil.CreateAnnotColl(new List<EffectAnnotation>());
= ReflUtil.CreateAnnotColl(new List<EffectAnnotation>());*/
void ParseAttribUnif() {
/*int attrs = GL.GetProgramiv(glprgm, GL.ACTIVE_ATTRIBUTES);
GL.Throw();
......@@ -194,6 +200,7 @@ namespace PoroCYon.FNAGLSL {
}
IntPtr bleh = Marshal.AllocHGlobal((IntPtr)totalsize);
ILUtil.Initblk(bleh, 0, (IntPtr)totalsize);
bool ok = false;
try {
......@@ -221,18 +228,31 @@ namespace PoroCYon.FNAGLSL {
}
}
List<uint> usedTextures = new List<uint>();
void ApplyUnifs() {
// TODO
usedTextures.Clear();
// TODO: get active texture to restore later -> glGetIntegerv(GL_ACTIVE_TEXTURE)
// TODO: make list to hold used texture slots
IntPtr data = unifDataBacking;
for (int i = 0; i < unifs.Length; ++i) {
var u = unifs[i];
//var p = Parameters[i];
SetUniform(ref u, data);
var p = Parameters[i];
// TODO:
/*if (it's a texture) {
find empty texture slot, put texture in it
-> GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
-> GL_TEXTURE_BINDING_[123]D / _BINDING_CUBE_MAP
bind uniform to texture slot
add texture slot to the used slot list
}
else*/ SetUniform(ref u, data);
data = (IntPtr)((long)data + u.bytesize);
}
// TODO: restore active texture
}
// TODO: find out a better (i.e. more API-conform) way to do this!
......@@ -254,7 +274,7 @@ namespace PoroCYon.FNAGLSL {
ApplyUnifs();
return new ActiveEffect(oldprgm);
return new ActiveEffect(oldprgm, usedTextures);
}
[Obsolete("Please use Bind() instead")]
public ActiveEffect Apply() { return Bind(); }
......
......@@ -47,6 +47,19 @@ namespace PoroCYon.FNAGLSL {
{ FLOAT_MAT3x4, sizeof(float)*4*4 },
{ FLOAT_MAT4x2, sizeof(float)*4*4 },
{ FLOAT_MAT4x3, sizeof(float)*4*4 },
// int-sized bc. not used, but data ptr needs to be nonzero anyway
{ SAMPLER_1D, sizeof(int) },
{ SAMPLER_2D, sizeof(int) },
{ SAMPLER_3D, sizeof(int) },
{ SAMPLER_CUBE, sizeof(int) },
{ INT_SAMPLER_1D, sizeof(int) },
{ INT_SAMPLER_2D, sizeof(int) },
{ INT_SAMPLER_3D, sizeof(int) },
{ INT_SAMPLER_CUBE, sizeof(int) },
{ UNSIGNED_INT_SAMPLER_1D, sizeof(int) },
{ UNSIGNED_INT_SAMPLER_2D, sizeof(int) },
{ UNSIGNED_INT_SAMPLER_3D, sizeof(int) },
{ UNSIGNED_INT_SAMPLER_CUBE, sizeof(int) },
};
typ2class = new Dictionary<GLSLType, EffectParameterClass>() {
{ FLOAT, Scalar },
......
......@@ -12,6 +12,10 @@ namespace PoroCYon.FNAGLSL {
"GLDevice", BindingFlags.GetField|BindingFlags.NonPublic|BindingFlags.Instance);
readonly static FieldInfo ef_glEffect_fi = typeof(Effect).GetField(
"glEffect", BindingFlags.GetField|BindingFlags.NonPublic|BindingFlags.Instance);
readonly static FieldInfo ep_texture_fi = typeof(EffectParameter).GetField(
"texture" , BindingFlags.GetField|BindingFlags.NonPublic|BindingFlags.Instance);
readonly static FieldInfo tx_texture_fi = typeof(Texture).GetField(
"texture" , BindingFlags.GetField|BindingFlags.NonPublic|BindingFlags.Instance);
readonly static PropertyInfo ef_Techniques_pi = typeof(Effect).GetProperty(
"Techniques", BindingFlags.SetProperty|BindingFlags.Public|BindingFlags.Instance),
......@@ -22,6 +26,12 @@ namespace PoroCYon.FNAGLSL {
ci_EffTechColl, ci_EffParamColl, ci_EffAnnotColl,
ci_EffTech, ci_EffParam, ci_EffAnnot;
readonly static int ci_EffParam_plen;
static MethodInfo gldev_DeleteEffect_mi;
static PropertyInfo ef_GLEffectData_pi, ef_EffectData_pi,
gltex_Handle_pi, gltex_Target_pi;
static ReflUtil() {
var pm1f = new ParameterModifier(1);
pm1f[0] = false;
......@@ -67,6 +77,9 @@ namespace PoroCYon.FNAGLSL {
// fuck it
typeof(EffectParameter).GetConstructors(BindingFlags.Instance
|BindingFlags.CreateInstance|BindingFlags.NonPublic)[0];
// ^ turns out, depending on the FNA version, the dataSize (uint)
// parameter mightn't be included
ci_EffParam_plen = ci_EffParam.GetParameters().Length;
ci_EffAnnot = typeof(EffectAnnotation).GetConstructor(
BindingFlags.CreateInstance|BindingFlags.NonPublic|BindingFlags.Instance,
......@@ -80,9 +93,6 @@ namespace PoroCYon.FNAGLSL {
throw new Exception("can't find ctors");
}
static MethodInfo gldev_DeleteEffect_mi;
static PropertyInfo ef_GLEffectData_pi, ef_EffectData_pi;
public static object GLDevice(this GraphicsDevice gd) =>
gd_GLDevice_fi.GetValue(gd);
public static object glEffect(this Effect eff) =>
......@@ -170,7 +180,7 @@ namespace PoroCYon.FNAGLSL {
EffectParameterClass paramClass, EffectParameterType paramType,
EffectParameterCollection structMembers, EffectAnnotationCollection annots,
IntPtr data, uint dataSize) {
int plen = ci_EffParam.GetParameters().Length;
int plen = ci_EffParam_plen;
if (plen == 11) {
return (EffectParameter)ci_EffParam.Invoke(new object[]{name, semantic,
rowCount, colCount, elemCount, paramClass, paramType,
......@@ -188,6 +198,32 @@ namespace PoroCYon.FNAGLSL {
EffectParameterType paramType, IntPtr data)
=> (EffectAnnotation)ci_EffAnnot.Invoke(new object[]{name, semantic,
rowCount, colCount, paramClass, paramType, data});
public static Texture GetValueTexture(this EffectParameter ep)
=> (Texture)ep_texture_fi.GetValue(ep);
public static uint GetGLTexID(this Texture tex) { // gl object id
var igltex = tx_texture_fi.GetValue(tex);
if (gltex_Handle_pi == null) {
// IGLTexture type not known at compile-time
gltex_Handle_pi = igltex.GetType().GetProperty("Handle",
BindingFlags.GetProperty|BindingFlags.Instance|BindingFlags.Public);
}
return (uint)gltex_Handle_pi.GetValue(igltex, null);
}
public static int GetGLTexTarget(this Texture tex) { // GL_TEXTURE_[123]D etc
var igltex = tx_texture_fi.GetValue(tex);
if (gltex_Target_pi == null) {
// IGLTexture type not known at compile-time
gltex_Target_pi = igltex.GetType().GetProperty("Target",
BindingFlags.GetProperty|BindingFlags.Instance|BindingFlags.Public);
}
return (int)gltex_Target_pi.GetValue(igltex, null);
}
}
}
......@@ -176,7 +176,7 @@ class TestGame : Game {
}*/
var vp = GraphicsDevice.Viewport;
glsl.Parameters["fGlobalTime"].SetValue((float)totalTime.TotalSeconds);
glsl.Parameters["fGlobalTime" ].SetValue((float)totalTime.TotalSeconds);
glsl.Parameters["v2Resolution"].SetValue(new Vector2(vp.Width, vp.Height));
using (var act = glsl.Bind()) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment