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.) ...@@ -6,19 +6,18 @@ the `Effect` API as much as possible. (Which isn't always working.)
## Does it work? ## Does it work?
Kinda. Static shaders work. Passing vertex data is very hacky and brittle. Kinda. Static shaders work. Passing vertex data is very hacky and brittle.
Uniforms, samples/textures, ... don't work at all yet. Using regular shaders Uniforms seem to work, but aren't well-tested. Samples/textures, ... don't
interleaved w/ GLSL shader draw calls seems to work ok. work at all yet. Using regular shaders interleaved w/ GLSL shader draw calls
seems to work ok.
## How does this work? ## How does this work?
No. Don't. No. Don't. Here be dragons.
## Are there things it can't do? ## Are there things it can't do?
Yes: 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) * No texture support (will have to be researched)
* Passing this to a `SpriteBatch` will probably fail in a bad way (unlikely * Passing this to a `SpriteBatch` will probably fail in a bad way (unlikely
to be fixed). to be fixed).
...@@ -34,6 +33,8 @@ var glsl = new GLSLEffect(GraphicsDevice, new Dictionary<GLSLPurpose, string>() ...@@ -34,6 +33,8 @@ var glsl = new GLSLEffect(GraphicsDevice, new Dictionary<GLSLPurpose, string>()
// ... // ...
glsl.Parameters["paramname"].SetValueT(xyz);
using (var bound = glsl.Bind()) using (var bound = glsl.Bind())
{ {
GraphicsDevice.DrawPrimitives(/*...*/); GraphicsDevice.DrawPrimitives(/*...*/);
......
...@@ -20,7 +20,6 @@ using Microsoft.Xna.Framework.Graphics; ...@@ -20,7 +20,6 @@ using Microsoft.Xna.Framework.Graphics;
* --> circumvent? --> HOW?? * --> circumvent? --> HOW??
* --> just go with it?? --> glProgramReady ok, glProgramViewportInfo might segfault! * --> just go with it?? --> glProgramReady ok, glProgramViewportInfo might segfault!
* *
* * uniforms
* * samplers, textures * * samplers, textures
* -> https://www.khronos.org/opengl/wiki/Program_Introspection * -> 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 * -> 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 { ...@@ -48,10 +47,11 @@ namespace PoroCYon.FNAGLSL {
public partial class GLSLEffect : Effect { public partial class GLSLEffect : Effect {
public struct ActiveEffect : IDisposable { public struct ActiveEffect : IDisposable {
internal uint oldprgm; internal uint oldprgm;
internal List<uint> texs;
bool disposed; bool disposed;
internal ActiveEffect(uint old) { internal ActiveEffect(uint old, List<uint> ts) {
oldprgm = old; disposed = false; oldprgm = old; disposed = false; texs = ts;
} }
public void Dispose() { public void Dispose() {
...@@ -60,6 +60,12 @@ namespace PoroCYon.FNAGLSL { ...@@ -60,6 +60,12 @@ namespace PoroCYon.FNAGLSL {
GL.UseProgram(oldprgm); GL.UseProgram(oldprgm);
oldprgm = 0; oldprgm = 0;
// TODO: release textures
/*for (int i = 0; i < texs.Length; ++i) {
}*/
texs.Clear();
disposed = true; disposed = true;
} }
} }
...@@ -153,10 +159,10 @@ namespace PoroCYon.FNAGLSL { ...@@ -153,10 +159,10 @@ namespace PoroCYon.FNAGLSL {
} }
} }
readonly static EffectParameterCollection emptyParamColl /*readonly static EffectParameterCollection emptyParamColl
= ReflUtil.CreateParamColl(new List<EffectParameter >()); = ReflUtil.CreateParamColl(new List<EffectParameter >());
readonly static EffectAnnotationCollection emptyAnnotColl readonly static EffectAnnotationCollection emptyAnnotColl
= ReflUtil.CreateAnnotColl(new List<EffectAnnotation>()); = ReflUtil.CreateAnnotColl(new List<EffectAnnotation>());*/
void ParseAttribUnif() { void ParseAttribUnif() {
/*int attrs = GL.GetProgramiv(glprgm, GL.ACTIVE_ATTRIBUTES); /*int attrs = GL.GetProgramiv(glprgm, GL.ACTIVE_ATTRIBUTES);
GL.Throw(); GL.Throw();
...@@ -194,6 +200,7 @@ namespace PoroCYon.FNAGLSL { ...@@ -194,6 +200,7 @@ namespace PoroCYon.FNAGLSL {
} }
IntPtr bleh = Marshal.AllocHGlobal((IntPtr)totalsize); IntPtr bleh = Marshal.AllocHGlobal((IntPtr)totalsize);
ILUtil.Initblk(bleh, 0, (IntPtr)totalsize);
bool ok = false; bool ok = false;
try { try {
...@@ -221,18 +228,31 @@ namespace PoroCYon.FNAGLSL { ...@@ -221,18 +228,31 @@ namespace PoroCYon.FNAGLSL {
} }
} }
List<uint> usedTextures = new List<uint>();
void ApplyUnifs() { 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; IntPtr data = unifDataBacking;
for (int i = 0; i < unifs.Length; ++i) { for (int i = 0; i < unifs.Length; ++i) {
var u = unifs[i]; var u = unifs[i];
//var p = Parameters[i]; var p = Parameters[i];
SetUniform(ref u, data); // 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); data = (IntPtr)((long)data + u.bytesize);
} }
// TODO: restore active texture
} }
// TODO: find out a better (i.e. more API-conform) way to do this! // TODO: find out a better (i.e. more API-conform) way to do this!
...@@ -254,7 +274,7 @@ namespace PoroCYon.FNAGLSL { ...@@ -254,7 +274,7 @@ namespace PoroCYon.FNAGLSL {
ApplyUnifs(); ApplyUnifs();
return new ActiveEffect(oldprgm); return new ActiveEffect(oldprgm, usedTextures);
} }
[Obsolete("Please use Bind() instead")] [Obsolete("Please use Bind() instead")]
public ActiveEffect Apply() { return Bind(); } public ActiveEffect Apply() { return Bind(); }
......
...@@ -47,6 +47,19 @@ namespace PoroCYon.FNAGLSL { ...@@ -47,6 +47,19 @@ namespace PoroCYon.FNAGLSL {
{ FLOAT_MAT3x4, sizeof(float)*4*4 }, { FLOAT_MAT3x4, sizeof(float)*4*4 },
{ FLOAT_MAT4x2, sizeof(float)*4*4 }, { FLOAT_MAT4x2, sizeof(float)*4*4 },
{ FLOAT_MAT4x3, 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>() { typ2class = new Dictionary<GLSLType, EffectParameterClass>() {
{ FLOAT, Scalar }, { FLOAT, Scalar },
......
...@@ -12,6 +12,10 @@ namespace PoroCYon.FNAGLSL { ...@@ -12,6 +12,10 @@ namespace PoroCYon.FNAGLSL {
"GLDevice", BindingFlags.GetField|BindingFlags.NonPublic|BindingFlags.Instance); "GLDevice", BindingFlags.GetField|BindingFlags.NonPublic|BindingFlags.Instance);
readonly static FieldInfo ef_glEffect_fi = typeof(Effect).GetField( readonly static FieldInfo ef_glEffect_fi = typeof(Effect).GetField(
"glEffect", BindingFlags.GetField|BindingFlags.NonPublic|BindingFlags.Instance); "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( readonly static PropertyInfo ef_Techniques_pi = typeof(Effect).GetProperty(
"Techniques", BindingFlags.SetProperty|BindingFlags.Public|BindingFlags.Instance), "Techniques", BindingFlags.SetProperty|BindingFlags.Public|BindingFlags.Instance),
...@@ -22,6 +26,12 @@ namespace PoroCYon.FNAGLSL { ...@@ -22,6 +26,12 @@ namespace PoroCYon.FNAGLSL {
ci_EffTechColl, ci_EffParamColl, ci_EffAnnotColl, ci_EffTechColl, ci_EffParamColl, ci_EffAnnotColl,
ci_EffTech, ci_EffParam, ci_EffAnnot; 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() { static ReflUtil() {
var pm1f = new ParameterModifier(1); var pm1f = new ParameterModifier(1);
pm1f[0] = false; pm1f[0] = false;
...@@ -67,6 +77,9 @@ namespace PoroCYon.FNAGLSL { ...@@ -67,6 +77,9 @@ namespace PoroCYon.FNAGLSL {
// fuck it // fuck it
typeof(EffectParameter).GetConstructors(BindingFlags.Instance typeof(EffectParameter).GetConstructors(BindingFlags.Instance
|BindingFlags.CreateInstance|BindingFlags.NonPublic)[0]; |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( ci_EffAnnot = typeof(EffectAnnotation).GetConstructor(
BindingFlags.CreateInstance|BindingFlags.NonPublic|BindingFlags.Instance, BindingFlags.CreateInstance|BindingFlags.NonPublic|BindingFlags.Instance,
...@@ -80,9 +93,6 @@ namespace PoroCYon.FNAGLSL { ...@@ -80,9 +93,6 @@ namespace PoroCYon.FNAGLSL {
throw new Exception("can't find ctors"); 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) => public static object GLDevice(this GraphicsDevice gd) =>
gd_GLDevice_fi.GetValue(gd); gd_GLDevice_fi.GetValue(gd);
public static object glEffect(this Effect eff) => public static object glEffect(this Effect eff) =>
...@@ -170,7 +180,7 @@ namespace PoroCYon.FNAGLSL { ...@@ -170,7 +180,7 @@ namespace PoroCYon.FNAGLSL {
EffectParameterClass paramClass, EffectParameterType paramType, EffectParameterClass paramClass, EffectParameterType paramType,
EffectParameterCollection structMembers, EffectAnnotationCollection annots, EffectParameterCollection structMembers, EffectAnnotationCollection annots,
IntPtr data, uint dataSize) { IntPtr data, uint dataSize) {
int plen = ci_EffParam.GetParameters().Length; int plen = ci_EffParam_plen;
if (plen == 11) { if (plen == 11) {
return (EffectParameter)ci_EffParam.Invoke(new object[]{name, semantic, return (EffectParameter)ci_EffParam.Invoke(new object[]{name, semantic,
rowCount, colCount, elemCount, paramClass, paramType, rowCount, colCount, elemCount, paramClass, paramType,
...@@ -188,6 +198,32 @@ namespace PoroCYon.FNAGLSL { ...@@ -188,6 +198,32 @@ namespace PoroCYon.FNAGLSL {
EffectParameterType paramType, IntPtr data) EffectParameterType paramType, IntPtr data)
=> (EffectAnnotation)ci_EffAnnot.Invoke(new object[]{name, semantic, => (EffectAnnotation)ci_EffAnnot.Invoke(new object[]{name, semantic,
rowCount, colCount, paramClass, paramType, data}); 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 { ...@@ -176,7 +176,7 @@ class TestGame : Game {
}*/ }*/
var vp = GraphicsDevice.Viewport; 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)); glsl.Parameters["v2Resolution"].SetValue(new Vector2(vp.Width, vp.Height));
using (var act = glsl.Bind()) { 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