codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
module renderer.api.opengl.CgKernel; template MCgKernel() { private import renderer.cg.cgGL; private import utils.StructClass : simpleStructCtor; private import std.file : read, exists; private template MCgProgram() { /+void setParam(ShaderParam param, mat4 val) { cgGLSetMatrixParameterfr(cast(CGparameter)param, &val.data[0]); } void setStateMatrixParam(ShaderParam param, StateMatrix sm, MatrixTransform mt) { cgGLSetStateMatrixParameter(cast(CGparameter)param, cast(CGGLenum)sm, cast(CGGLenum)mt); }+/ final CGparameter getParam(char[] name) { { CGparameter* p = name in namedParams; if (p) return *p; } CGparameter p = cgGetNamedParameter(cgProgram, toStringz(name)); if (p is null) throw new Exception(`Unknown shader param: '` ~ name ~ `'`); namedParams[name.dup] = p; namedParams.rehash; return p; } override void opIndexAssign(float val, char[] name) { cgGLSetParameter1f(getParam(name), val); } override void opIndexAssign(vec2 val, char[] name) { cgGLSetParameter2fv(getParam(name), &val.x); } override void opIndexAssign(vec3 val, char[] name) { cgGLSetParameter3fv(getParam(name), &val.x); } override void opIndexAssign(vec4 val, char[] name) { cgGLSetParameter4fv(getParam(name), &val.x); } override void opIndexAssign(StateMatrix val, char[] name) { static CGGLenum[] typeMap = [ CGGLenum.CG_GL_MODELVIEW_MATRIX, CGGLenum.CG_GL_PROJECTION_MATRIX, CGGLenum.CG_GL_TEXTURE_MATRIX, CGGLenum.CG_GL_MODELVIEW_PROJECTION_MATRIX ]; static CGGLenum[] xformMap = [ CGGLenum.CG_GL_MATRIX_IDENTITY, CGGLenum.CG_GL_MATRIX_TRANSPOSE, CGGLenum.CG_GL_MATRIX_INVERSE, CGGLenum.CG_GL_MATRIX_INVERSE_TRANSPOSE ]; cgGLSetStateMatrixParameter(getParam(name), typeMap[cast(int)val.type], xformMap[cast(int)val.transform]); } protected { CGprofile cgProfile; CGprogram cgProgram; CGparameter[char[]] namedParams; } } class CgVertexShader : HwVertexShader { mixin MCgProgram; private void extractVaryingParams() { CGparameter leaf = cgGetFirstLeafParameter(cgProgram, CGenum.CG_PROGRAM); while (leaf) { CGenum var = cgGetParameterVariability(leaf); CGenum dir = cgGetParameterDirection(leaf); if (var == CGenum.CG_VARYING && dir != CGenum.CG_OUT && dir != CGenum.CG_ERROR) { CGresource res = cgGetParameterResource(leaf); if (res >= VertexDataType.min && res <= VertexDataType.max) { VertexDataType vdt = cast(VertexDataType)res; varyingParams ~= VaryingParam(leaf, vdt); writefln("CgVertexShader: extracted a param: ", cast(uint)vdt); } } leaf = cgGetNextLeafParameter(leaf); } } void bind() { foreach (inout VaryingParam vpar; varyingParams) { CgKernel.vdtCgParams[vpar.vdt - CgKernel.vdtArrayOffset] = vpar.param; } //writefln(`enabling vertex profile: `, cast(int)this.cgProfile); cgGLEnableProfile(this.cgProfile); cgGLBindProgram(this.cgProgram); } void unbind() { foreach (inout VaryingParam vpar; varyingParams) { CgKernel.vdtCgParams[vpar.vdt - CgKernel.vdtArrayOffset] = null; } cgGLUnbindProgram(this.cgProfile); cgGLDisableProfile(this.cgProfile); } this (CGprogram prog, CGprofile prof) { this.cgProgram = prog; this.cgProfile = prof; extractVaryingParams(); } override bool isVertexDataNeeded(VertexDataType vdt) { foreach (inout VaryingParam vp; varyingParams) { if (vp.vdt is vdt) { return true; } } return false; } /+void setTexture(ShaderParam param, Texture tex) { assert(false); // not implemented }+/ package { struct VaryingParam { CGparameter param; VertexDataType vdt; mixin simpleStructCtor; } VaryingParam[] varyingParams; } } class CgFragmentShader : HwFragmentShader { mixin MCgProgram; private void extractTexBindings() { CGparameter leaf = cgGetFirstLeafParameter(cgProgram, CGenum.CG_PROGRAM); while (leaf) { CGenum var = cgGetParameterVariability(leaf); CGenum dir = cgGetParameterDirection(leaf); if (var != CGenum.CG_VARYING && dir != CGenum.CG_OUT && dir != CGenum.CG_ERROR) { CGresource res = cgGetParameterResource(leaf); if (res >= CGresource.CG_TEXUNIT0 && res <= CGresource.CG_TEXUNIT15) { texBindings ~= TexBinding(leaf, res - CGresource.CG_TEXUNIT0); } } leaf = cgGetNextLeafParameter(leaf); } } this (CGprogram prog, CGprofile prof) { this.cgProgram = prog; this.cgProfile = prof; extractTexBindings(); } /+void setTexture(ShaderParam param, Texture tex) { TODO if (tex !is null && tex.id != -1) { foreach (inout TexBinding tb; texBindings) { if (tb.pred == cast(CGparameter)param) { CgTextureKernel.texUnitTextures[tb.succ] = tex; return; } } } }+/ void bind() { //writefln(`enabling fragment profile: `, cast(int)this.cgProfile); cgGLEnableProfile(this.cgProfile); cgGLBindProgram(this.cgProgram); } void unbind() { cgGLUnbindProgram(this.cgProfile); cgGLDisableProfile(this.cgProfile); } package { struct TexBinding { CGparameter param; uint unit; mixin simpleStructCtor; } TexBinding[] texBindings; } } static class CgException : Exception { this (char[] str) { super(str); } } class CgKernel : HwShaderKernel { private static void cgErrorCallback() { CGerror error = cgGetError(); char* errStr; if (error == CGerror.CG_COMPILER_ERROR) { errStr = cgGetLastListing(cgContext); } else { errStr = cgGetErrorString(error); } throw new CgException("cgError: " ~ .toString(errStr)); } override bool canLoadVertexShader(char[] filename, char[] profile) { return cgContext !is null && cgVertexProfile !is CGprofile.CG_PROFILE_UNKNOWN && filename.length > 3 && tolower(filename[$-3..$]) == `.cg` && std.file.exists(filename); } override bool canLoadFragmentShader(char[] filename, char[] profile) { return cgContext !is null && cgFragmentProfile !is CGprofile.CG_PROFILE_UNKNOWN && filename.length > 3 && tolower(filename[$-3..$]) == `.cg` && std.file.exists(filename); } private bool loadCgProgramFile(char[] programString, CGprofile profile, out CGprogram cgProg) { CGprogram prog; bool res = loadCgProgram(cast(char[])std.file.read(programString), profile, prog); if (res) cgProg = prog; return res; } private bool loadCgProgram(char[] programString, CGprofile profile, out CGprogram cgProg) { if (!cgGLIsProfileSupported(profile)) { return false; } char[] progStr = programString;//programString.replace("/+", "/*").replace("+/", "*/") ~ '\0'; CGprogram prog; try { cgGLSetOptimalOptions(profile); prog = cgCreateProgram(cgContext, CGenum.CG_SOURCE, .toStringz(progStr), profile, "main", null); cgGLEnableProfile(profile); cgGLLoadProgram(prog); cgGLDisableProfile(profile); } catch (CgException err) { writefln(err); return false; } cgProg = prog; return true; } override HwVertexShader loadVertexShader(char[] filename, char[] profileName) { writefln(`CgKernel.loadVertexShader (%s)`, filename); CGprofile profile = this.cgVertexProfile; if (profileName !is null) profile = cgGetProfile(.toStringz(profileName)); assert (profile != CGprofile.CG_PROFILE_UNKNOWN); CGprogram prog; if (canLoadVertexShader(filename, profileName) && loadCgProgramFile(filename, profile, prog)) { return new CgVertexShader(prog, profile); } else { return null; } } override HwFragmentShader loadFragmentShader(char[] filename, char[] profileName) { writefln(`CgKernel.loadFragmentShader (%s)`, filename); CGprofile profile = this.cgFragmentProfile; if (profileName !is null) profile = cgGetProfile(.toStringz(profileName)); assert (profile != CGprofile.CG_PROFILE_UNKNOWN); CGprogram prog; if (canLoadFragmentShader(filename, profileName) && loadCgProgramFile(filename, profile, prog)) { return new CgFragmentShader(prog, profile); } else { return null; } } protected void enableVertexArrayCallback(VertexDataType vdt, uint components, uint glType, uint stride, void* ptr) { CGparameter cgParam = vdtCgParams[vdt - vdtArrayOffset]; if (cgParam) { //writefln(`enabling cg array: `, cast(int)vdt); cgGLEnableClientState(cgParam); cgGLSetParameterPointer(cgParam, components, glType, stride, ptr); } } protected void disableVertexArrayCallback(VertexDataType vdt) { CGparameter cgParam = vdtCgParams[vdt - vdtArrayOffset]; if (cgParam) { //writefln(`disabling cg array: `, cast(int)vdt); cgGLDisableClientState(cgParam); } } this() { renderer.cg.cgGL.initCg(); renderer.cg.cgGL.initCgGl(); writefln(`Loaded the CgGL shared library`); if (cgCreateContext !is null) { cgContext = cgCreateContext(); assert (cgGLGetLatestProfile !is null); cgVertexProfile = cgGLGetLatestProfile(CGGLenum.CG_GL_VERTEX); if (cgVertexProfile !is CGprofile.CG_PROFILE_UNKNOWN) { assert (cgGLSetOptimalOptions !is null); cgGLSetOptimalOptions(cgVertexProfile); //checkForCgError("selecting vertex profile"); assert (cgGetProfileString !is null); writefln("Cg fragment profile: ", .toString(cgGetProfileString(cgVertexProfile))); } else writefln("No Cg fragment shader support"); cgFragmentProfile = cgGLGetLatestProfile(CGGLenum.CG_GL_FRAGMENT); if (cgFragmentProfile !is CGprofile.CG_PROFILE_UNKNOWN) { assert (cgGLSetOptimalOptions !is null); cgGLSetOptimalOptions(cgFragmentProfile); //checkForCgError("selecting vertex profile"); assert (cgGetProfileString !is null); writefln("Cg vertex profile: ", .toString(cgGetProfileString(cgFragmentProfile))); } else writefln("No Cg vertex shader support"); if (cgSetErrorCallback !is null) cgSetErrorCallback(&cgErrorCallback); addEnableArrayCallback(&enableVertexArrayCallback); addDisableArrayCallback(&disableVertexArrayCallback); } } static { CGcontext cgContext; CGprofile cgVertexProfile; CGprofile cgFragmentProfile; static const uint vdtArraySize = cast(uint)(VertexDataType.max - VertexDataType.min + 1); static const uint vdtArrayOffset = cast(uint)VertexDataType.min; static CGparameter[vdtArraySize] vdtCgParams; } } protected final void initCgKernel() { writefln(`Initializing the Cg kernel`); addHwShaderKernel(new CgKernel); } }
Private
[
?
]
Run code