merge shader_overhaul from jyelon
This commit is contained in:
parent
2d8678de58
commit
1fdb425b88
|
|
@ -783,7 +783,7 @@ clear(DrawableRegion *clearable) {
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const LMatrix4f *GraphicsStateGuardian::
|
||||
fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
|
||||
fetch_specified_value(ShaderExpansion::ShaderMatSpec &spec, bool altered) {
|
||||
static LMatrix4f acc;
|
||||
const LMatrix4f *val1;
|
||||
const LMatrix4f *val2;
|
||||
|
|
@ -791,26 +791,26 @@ fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
|
|||
static LMatrix4f t2;
|
||||
|
||||
switch(spec._func) {
|
||||
case ShaderContext::SMF_compose:
|
||||
case ShaderExpansion::SMF_compose:
|
||||
val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1);
|
||||
val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2);
|
||||
acc.multiply(*val1, *val2);
|
||||
return &acc;
|
||||
case ShaderContext::SMF_compose_cache_first:
|
||||
case ShaderExpansion::SMF_compose_cache_first:
|
||||
if (altered) {
|
||||
spec._cache = *fetch_specified_part(spec._part[0], spec._arg[0], t1);
|
||||
}
|
||||
val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2);
|
||||
acc.multiply(spec._cache, *val2);
|
||||
return &acc;
|
||||
case ShaderContext::SMF_compose_cache_second:
|
||||
case ShaderExpansion::SMF_compose_cache_second:
|
||||
if (altered) {
|
||||
spec._cache = *fetch_specified_part(spec._part[1], spec._arg[1], t2);
|
||||
}
|
||||
val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1);
|
||||
acc.multiply(*val1, spec._cache);
|
||||
return &acc;
|
||||
case ShaderContext::SMF_first:
|
||||
case ShaderExpansion::SMF_first:
|
||||
return fetch_specified_part(spec._part[0], spec._arg[0], t1);
|
||||
default:
|
||||
// should never get here
|
||||
|
|
@ -824,24 +824,24 @@ fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
|
|||
// Description: See fetch_specified_value
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const LMatrix4f *GraphicsStateGuardian::
|
||||
fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMatrix4f &t) {
|
||||
fetch_specified_part(ShaderExpansion::ShaderMatInput part, InternalName *name, LMatrix4f &t) {
|
||||
switch(part) {
|
||||
case ShaderContext::SMO_identity: {
|
||||
case ShaderExpansion::SMO_identity: {
|
||||
return &LMatrix4f::ident_mat();
|
||||
}
|
||||
case ShaderContext::SMO_window_size: {
|
||||
case ShaderExpansion::SMO_window_size: {
|
||||
t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
|
||||
_current_display_region->get_pixel_height(),
|
||||
0.0);
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_pixel_size: {
|
||||
case ShaderExpansion::SMO_pixel_size: {
|
||||
t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
|
||||
_current_display_region->get_pixel_height(),
|
||||
0.0);
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_card_center: {
|
||||
case ShaderExpansion::SMO_card_center: {
|
||||
int px = _current_display_region->get_pixel_width();
|
||||
int py = _current_display_region->get_pixel_height();
|
||||
t = LMatrix4f::translate_mat((px*0.5) / Texture::up_to_power_2(px),
|
||||
|
|
@ -849,14 +849,14 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
0.0);
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_mat_constant_x: {
|
||||
case ShaderExpansion::SMO_mat_constant_x: {
|
||||
const ShaderInput *input = _target._shader->get_shader_input(name);
|
||||
if (input->get_nodepath().is_empty()) {
|
||||
return &LMatrix4f::ident_mat();
|
||||
}
|
||||
return &(input->get_nodepath().node()->get_transform()->get_mat());
|
||||
}
|
||||
case ShaderContext::SMO_vec_constant_x: {
|
||||
case ShaderExpansion::SMO_vec_constant_x: {
|
||||
const ShaderInput *input = _target._shader->get_shader_input(name);
|
||||
const float *data = input->get_vector().get_data();
|
||||
t = LMatrix4f(data[0],data[1],data[2],data[3],
|
||||
|
|
@ -865,28 +865,28 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
data[0],data[1],data[2],data[3]);
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_world_to_view: {
|
||||
case ShaderExpansion::SMO_world_to_view: {
|
||||
return &(get_scene()->get_world_transform()->get_mat());
|
||||
break;
|
||||
}
|
||||
case ShaderContext::SMO_view_to_world: {
|
||||
case ShaderExpansion::SMO_view_to_world: {
|
||||
return &(get_scene()->get_camera_transform()->get_mat());
|
||||
}
|
||||
case ShaderContext::SMO_model_to_view: {
|
||||
case ShaderExpansion::SMO_model_to_view: {
|
||||
return &(get_external_transform()->get_mat());
|
||||
}
|
||||
case ShaderContext::SMO_view_to_model: {
|
||||
case ShaderExpansion::SMO_view_to_model: {
|
||||
// DANGER: SLOW AND NOT CACHEABLE!
|
||||
t.invert_from(get_external_transform()->get_mat());
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_apiview_to_view: {
|
||||
case ShaderExpansion::SMO_apiview_to_view: {
|
||||
return &(_inv_cs_transform->get_mat());
|
||||
}
|
||||
case ShaderContext::SMO_view_to_apiview: {
|
||||
case ShaderExpansion::SMO_view_to_apiview: {
|
||||
return &(_cs_transform->get_mat());
|
||||
}
|
||||
case ShaderContext::SMO_clip_to_view: {
|
||||
case ShaderExpansion::SMO_clip_to_view: {
|
||||
if (_current_lens->get_coordinate_system() == _coordinate_system) {
|
||||
return &(_current_lens->get_projection_mat_inv(_current_stereo_channel));
|
||||
} else {
|
||||
|
|
@ -895,7 +895,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
return &t;
|
||||
}
|
||||
}
|
||||
case ShaderContext::SMO_view_to_clip: {
|
||||
case ShaderExpansion::SMO_view_to_clip: {
|
||||
if (_current_lens->get_coordinate_system() == _coordinate_system) {
|
||||
return &(_current_lens->get_projection_mat(_current_stereo_channel));
|
||||
} else {
|
||||
|
|
@ -904,15 +904,15 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
return &t;
|
||||
}
|
||||
}
|
||||
case ShaderContext::SMO_apiclip_to_view: {
|
||||
case ShaderExpansion::SMO_apiclip_to_view: {
|
||||
t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat();
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_view_to_apiclip: {
|
||||
case ShaderExpansion::SMO_view_to_apiclip: {
|
||||
t = _cs_transform->get_mat() * _projection_mat->get_mat();
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_view_x_to_view: {
|
||||
case ShaderExpansion::SMO_view_x_to_view: {
|
||||
const ShaderInput *input = _target._shader->get_shader_input(name);
|
||||
|
||||
if (input->get_nodepath().is_empty()) {
|
||||
|
|
@ -927,7 +927,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
get_scene()->get_world_transform()->get_mat();
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_view_to_view_x: {
|
||||
case ShaderExpansion::SMO_view_to_view_x: {
|
||||
const ShaderInput *input = _target._shader->get_shader_input(name);
|
||||
|
||||
if (input->get_nodepath().is_empty()) {
|
||||
|
|
@ -942,7 +942,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
invert(input->get_nodepath().get_net_transform()->get_mat());
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_apiview_x_to_view: {
|
||||
case ShaderExpansion::SMO_apiview_x_to_view: {
|
||||
const ShaderInput *input = _target._shader->get_shader_input(name);
|
||||
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
|
||||
t = LMatrix4f::convert_mat(_internal_coordinate_system, _coordinate_system) *
|
||||
|
|
@ -950,7 +950,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
get_scene()->get_world_transform()->get_mat();
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_view_to_apiview_x: {
|
||||
case ShaderExpansion::SMO_view_to_apiview_x: {
|
||||
const ShaderInput *input = _target._shader->get_shader_input(name);
|
||||
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
|
||||
t = (get_scene()->get_camera_transform()->get_mat() *
|
||||
|
|
@ -958,7 +958,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
LMatrix4f::convert_mat(_coordinate_system, _internal_coordinate_system));
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_clip_x_to_view: {
|
||||
case ShaderExpansion::SMO_clip_x_to_view: {
|
||||
const ShaderInput *input = _target._shader->get_shader_input(name);
|
||||
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
|
||||
Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
|
||||
|
|
@ -968,7 +968,7 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
get_scene()->get_world_transform()->get_mat();
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_view_to_clip_x: {
|
||||
case ShaderExpansion::SMO_view_to_clip_x: {
|
||||
const ShaderInput *input = _target._shader->get_shader_input(name);
|
||||
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
|
||||
Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
|
||||
|
|
@ -978,11 +978,11 @@ fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMa
|
|||
lens->get_projection_mat(_current_stereo_channel);
|
||||
return &t;
|
||||
}
|
||||
case ShaderContext::SMO_apiclip_x_to_view: {
|
||||
case ShaderExpansion::SMO_apiclip_x_to_view: {
|
||||
// NOT IMPLEMENTED
|
||||
return &LMatrix4f::ident_mat();
|
||||
}
|
||||
case ShaderContext::SMO_view_to_apiclip_x: {
|
||||
case ShaderExpansion::SMO_view_to_apiclip_x: {
|
||||
// NOT IMPLEMENTED
|
||||
return &LMatrix4f::ident_mat();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,8 +194,8 @@ public:
|
|||
|
||||
void clear(DrawableRegion *clearable);
|
||||
|
||||
const LMatrix4f *fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered);
|
||||
const LMatrix4f *fetch_specified_part(ShaderContext::ShaderMatInput input, InternalName *name, LMatrix4f &t);
|
||||
const LMatrix4f *fetch_specified_value(ShaderExpansion::ShaderMatSpec &spec, bool altered);
|
||||
const LMatrix4f *fetch_specified_part(ShaderExpansion::ShaderMatInput input, InternalName *name, LMatrix4f &t);
|
||||
|
||||
virtual void prepare_display_region(DisplayRegionPipelineReader *dr,
|
||||
Lens::StereoChannel stereo_channel);
|
||||
|
|
@ -410,6 +410,8 @@ protected:
|
|||
|
||||
static PT(TextureStage) _alpha_scale_texture_stage;
|
||||
|
||||
ShaderExpansion::ShaderCaps _shader_caps;
|
||||
|
||||
public:
|
||||
// Statistics
|
||||
static PStatCollector _vertex_buffer_switch_pcollector;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@
|
|||
#include "pStatTimer.h"
|
||||
#include "pStatCollector.h"
|
||||
#include "wdxGraphicsBuffer9.h"
|
||||
#ifdef HAVE_CG
|
||||
#include "Cg/cgD3D9.h"
|
||||
#endif
|
||||
|
||||
#include <mmsystem.h>
|
||||
|
||||
|
|
@ -147,10 +150,6 @@ DXGraphicsStateGuardian9(GraphicsPipe *pipe) :
|
|||
_vertex_shader_maximum_constants = 0;
|
||||
|
||||
_supports_stream_offset = false;
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
_cg_context = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -169,14 +168,6 @@ DXGraphicsStateGuardian9::
|
|||
delete _lru;
|
||||
_lru = 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
if (_cg_context) {
|
||||
cgD3D9SetDevice (NULL);
|
||||
cgDestroyContext (_cg_context);
|
||||
_cg_context = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -346,10 +337,9 @@ release_texture(TextureContext *tc) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
ShaderContext *CLP(GraphicsStateGuardian)::
|
||||
prepare_shader(ShaderExpansion *se) {
|
||||
#ifdef HAVE_CGDX9
|
||||
#ifdef HAVE_CG
|
||||
CLP(ShaderContext) *result = new CLP(ShaderContext)(se, this);
|
||||
if (this -> _cg_context) return result;
|
||||
delete result;
|
||||
return result;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -2395,7 +2385,6 @@ reset() {
|
|||
|
||||
_vertex_shader_maximum_constants = d3d_caps.MaxVertexShaderConst;
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
switch (_pixel_shader_version_major)
|
||||
{
|
||||
case 0:
|
||||
|
|
@ -2419,11 +2408,49 @@ reset() {
|
|||
_shader_model = SM_40;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
_shader_model = SM_00;
|
||||
#endif
|
||||
|
||||
_auto_detect_shader_model = _shader_model;
|
||||
|
||||
#ifdef HAVE_CG
|
||||
cgD3D9SetDevice (_d3d_device);
|
||||
|
||||
if (cgD3D9IsProfileSupported(CG_PROFILE_PS_2_0) &&
|
||||
cgD3D9IsProfileSupported(CG_PROFILE_VS_2_0)) {
|
||||
_supports_basic_shaders = true;
|
||||
_shader_caps._active_vprofile = (int)cgD3D9GetLatestVertexProfile();
|
||||
_shader_caps._active_fprofile = (int)cgD3D9GetLatestPixelProfile();
|
||||
_shader_caps._ultimate_vprofile = (int)CG_PROFILE_VS_3_0;
|
||||
_shader_caps._ultimate_fprofile = (int)CG_PROFILE_PS_3_0;
|
||||
}
|
||||
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
|
||||
CGprofile vertex_profile;
|
||||
CGprofile pixel_profile;
|
||||
|
||||
vertex_profile = cgD3D9GetLatestVertexProfile( );
|
||||
pixel_profile = cgD3D9GetLatestPixelProfile( );
|
||||
|
||||
const char *vertex_profile_str =
|
||||
cgGetProfileString(vertex_profile);
|
||||
const char *pixel_profile_str =
|
||||
cgGetProfileString(pixel_profile);
|
||||
|
||||
if (vertex_profile_str == NULL) {
|
||||
vertex_profile_str = "(null)";
|
||||
}
|
||||
if (pixel_profile_str == NULL) {
|
||||
pixel_profile_str = "(null)";
|
||||
}
|
||||
|
||||
dxgsg9_cat.debug()
|
||||
<< "\nCg vertex profile = " << vertex_profile_str << " id = " << vertex_profile
|
||||
<< "\nCg pixel profile = " << pixel_profile_str << " id = " << pixel_profile
|
||||
<< "\nshader model = " << _shader_model
|
||||
<< "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
_supports_stream_offset = (d3d_caps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET) != 0;
|
||||
_screen->_supports_dynamic_textures = ((d3d_caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0);
|
||||
_screen->_supports_automatic_mipmap_generation = ((d3d_caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0);
|
||||
|
|
@ -2475,52 +2502,6 @@ reset() {
|
|||
|
||||
this -> reset_render_states ( );
|
||||
|
||||
// duplicates OpenGL version (ARB_vertex_program extension and
|
||||
// ARB_fragment_program extension)
|
||||
if (_vertex_shader_version_major >= 1 &&
|
||||
_pixel_shader_version_major >= 2) {
|
||||
_supports_basic_shaders = true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
if (_cg_context == 0) {
|
||||
_cg_context = cgCreateContext ( );
|
||||
cgD3D9SetDevice (_d3d_device);
|
||||
}
|
||||
else {
|
||||
cgD3D9SetDevice (_d3d_device);
|
||||
}
|
||||
|
||||
if (_cg_context) {
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
|
||||
CGprofile vertex_profile;
|
||||
CGprofile pixel_profile;
|
||||
|
||||
vertex_profile = cgD3D9GetLatestVertexProfile( );
|
||||
pixel_profile = cgD3D9GetLatestPixelProfile( );
|
||||
|
||||
const char *vertex_profile_str =
|
||||
cgGetProfileString(vertex_profile);
|
||||
const char *pixel_profile_str =
|
||||
cgGetProfileString(pixel_profile);
|
||||
|
||||
if (vertex_profile_str == NULL) {
|
||||
vertex_profile_str = "(null)";
|
||||
}
|
||||
if (pixel_profile_str == NULL) {
|
||||
pixel_profile_str = "(null)";
|
||||
}
|
||||
|
||||
dxgsg9_cat.debug()
|
||||
<< "\nCg vertex profile = " << vertex_profile_str << " id = " << vertex_profile
|
||||
<< "\nCg pixel profile = " << pixel_profile_str << " id = " << pixel_profile
|
||||
<< "\nshader model = " << _shader_model
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_max_vertices_per_array = d3d_caps.MaxVertexIndex;
|
||||
_max_vertices_per_primitive = d3d_caps.MaxPrimitiveCount;
|
||||
|
||||
|
|
@ -2945,7 +2926,7 @@ do_issue_shader() {
|
|||
ShaderExpansion *expansion = _target_rs->get_shader_expansion();
|
||||
if (expansion == 0) {
|
||||
if (_target._shader->get_shader() != 0) {
|
||||
expansion = _target._shader->get_shader()->macroexpand(_target_rs);
|
||||
expansion = _target._shader->get_shader()->macroexpand(_target_rs, _shader_caps);
|
||||
// I am casting away the const-ness of this pointer, because
|
||||
// the 'shader-expansion' field is just a cache.
|
||||
((RenderState *)((const RenderState*)_target_rs))->
|
||||
|
|
|
|||
|
|
@ -250,11 +250,7 @@ protected:
|
|||
|
||||
public:
|
||||
DXScreenData *_screen;
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
CGcontext _cg_context;
|
||||
#endif
|
||||
|
||||
|
||||
protected:
|
||||
LPDIRECT3DDEVICE9 _d3d_device; // same as _screen->_d3d_device, cached for spd
|
||||
IDirect3DSwapChain9 *_swap_chain;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CLP(ShaderContext)::
|
||||
valid (GSG *gsg) {
|
||||
return _state;
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,54 +25,14 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_CG
|
||||
#include "Cg/cgD3D9.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG_SHADER 0
|
||||
|
||||
TypeHandle CLP(ShaderContext)::_type_handle;
|
||||
|
||||
static char *vertex_shader_function_name = "vshader";
|
||||
static char *pixel_shader_function_name = "fshader";
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: cg_type_to_panda_type
|
||||
// Access: Public, Static
|
||||
// Description: convert a cg shader-arg type to a panda shader-arg type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static ShaderContext::ShaderArgType
|
||||
cg_type_to_panda_type(CGtype n) {
|
||||
switch (n) {
|
||||
case CG_FLOAT1: return ShaderContext::SAT_float1;
|
||||
case CG_FLOAT2: return ShaderContext::SAT_float2;
|
||||
case CG_FLOAT3: return ShaderContext::SAT_float3;
|
||||
case CG_FLOAT4: return ShaderContext::SAT_float4;
|
||||
case CG_FLOAT4x4: return ShaderContext::SAT_float4x4;
|
||||
case CG_SAMPLER1D: return ShaderContext::SAT_sampler1d;
|
||||
case CG_SAMPLER2D: return ShaderContext::SAT_sampler2d;
|
||||
case CG_SAMPLER3D: return ShaderContext::SAT_sampler3d;
|
||||
case CG_SAMPLERCUBE: return ShaderContext::SAT_samplercube;
|
||||
default: return ShaderContext::SAT_unknown;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_CGDX9
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: cg_dir_to_panda_dir
|
||||
// Access: Public, Static
|
||||
// Description: convert a cg shader-arg type to a panda shader-arg type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static ShaderContext::ShaderArgDir
|
||||
cg_dir_to_panda_dir(CGenum n) {
|
||||
switch (n) {
|
||||
case CG_IN: return ShaderContext::SAD_in;
|
||||
case CG_OUT: return ShaderContext::SAD_out;
|
||||
case CG_INOUT: return ShaderContext::SAD_inout;
|
||||
default: return ShaderContext::SAD_unknown;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_CGDX9
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXShaderContext9::Constructor
|
||||
// Access: Public
|
||||
|
|
@ -80,80 +40,70 @@ cg_dir_to_panda_dir(CGenum n) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CLP(ShaderContext)::
|
||||
CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
|
||||
string header;
|
||||
s->parse_init();
|
||||
s->parse_line(header, true, true);
|
||||
|
||||
_state = false;
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
|
||||
DBG_SH2 dxgsg9_cat.debug ( ) << "SHADER: Create ShaderContext \n"; DBG_E
|
||||
|
||||
_cg_shader = false;
|
||||
|
||||
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
|
||||
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
|
||||
_cg_program[SHADER_type_vert] = (CGprogram)0;
|
||||
_cg_program[SHADER_type_frag] = (CGprogram)0;
|
||||
|
||||
_vertex_size = 0;
|
||||
_vertex_element_array = 0;
|
||||
|
||||
_total_dx_parameters = 0;
|
||||
_dx_parameter_array = 0;
|
||||
|
||||
_transpose_matrix = false;
|
||||
|
||||
_name = s->get_name ( );
|
||||
|
||||
if (header == "//Cg") {
|
||||
#ifdef HAVE_CG
|
||||
if (s->get_header() == "//Cg") {
|
||||
|
||||
// Ask the shader expansion to compile itself for us and
|
||||
// to give us the resulting Cg program objects.
|
||||
|
||||
// CGcontext is created once during Reset ( )
|
||||
if (gsg -> _cg_context == 0) {
|
||||
release_resources();
|
||||
dxgsg9_cat.error() << "Cg not supported by this video card.\n";
|
||||
if (!s->cg_compile_for(gsg->_shader_caps,
|
||||
_cg_context,
|
||||
_cg_vprogram,
|
||||
_cg_fprogram,
|
||||
_cg_parameter_map)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the program.
|
||||
|
||||
// Parse any directives in the source.
|
||||
// IGNORE SPECIFIC PROFILES IN DX FOR NOW
|
||||
if (false) {
|
||||
string directive;
|
||||
while (!s->parse_eof()) {
|
||||
s->parse_line(directive, true, true);
|
||||
vector_string pieces;
|
||||
tokenize(directive, pieces, " \t");
|
||||
if ((pieces.size()==4)&&(pieces[0]=="//Cg")&&(pieces[1]=="profile")) {
|
||||
suggest_cg_profile(pieces[2], pieces[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Select a profile if no preferred profile specified in the source.
|
||||
if (_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN) {
|
||||
_cg_profile[SHADER_type_vert] = cgD3D9GetLatestVertexProfile( );
|
||||
}
|
||||
if (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN) {
|
||||
_cg_profile[SHADER_type_frag] = cgD3D9GetLatestPixelProfile( );
|
||||
}
|
||||
|
||||
// If we still haven't chosen a profile, give up.
|
||||
if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
|
||||
(_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
|
||||
release_resources();
|
||||
dxgsg9_cat.error() << "Cg not supported by this video card.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Compile the program.
|
||||
_cg_shader = true;
|
||||
try_cg_compile(s, gsg);
|
||||
return;
|
||||
}
|
||||
BOOL paramater_shadowing;
|
||||
DWORD assembly_flags;
|
||||
|
||||
paramater_shadowing = FALSE;
|
||||
assembly_flags = 0;
|
||||
|
||||
#if DEBUG_SHADER
|
||||
assembly_flags |= D3DXSHADER_DEBUG;
|
||||
#endif
|
||||
|
||||
dxgsg9_cat.error() << s->get_name() << ": unrecognized shader language " << header << "\n";
|
||||
HRESULT hr;
|
||||
bool success = true;
|
||||
hr = cgD3D9LoadProgram(_cg_vprogram, paramater_shadowing, assembly_flags);
|
||||
if (FAILED (hr)) {
|
||||
dxgsg9_cat.error()
|
||||
<< "vertex shader cgD3D9LoadProgram failed "
|
||||
<< D3DERRORSTRING(hr);
|
||||
|
||||
CGerror error = cgGetError();
|
||||
if (error != CG_NO_ERROR) {
|
||||
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
|
||||
}
|
||||
success = false;
|
||||
}
|
||||
|
||||
hr = cgD3D9LoadProgram(_cg_fprogram, paramater_shadowing, assembly_flags);
|
||||
if (FAILED (hr)) {
|
||||
dxgsg9_cat.error()
|
||||
<< "pixel shader cgD3D9LoadProgram failed "
|
||||
<< D3DERRORSTRING(hr);
|
||||
|
||||
CGerror error = cgGetError();
|
||||
if (error != CG_NO_ERROR) {
|
||||
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
|
||||
}
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
release_resources();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -171,340 +121,53 @@ CLP(ShaderContext)::
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::report_cg_compile_errors
|
||||
// Access: Public, Static
|
||||
// Description: Used only after a Cg compile command, to print
|
||||
// out any error messages that may have occurred
|
||||
// during the Cg shader compilation. The 'file'
|
||||
// is the name of the file containing the Cg code.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
report_cg_compile_errors(const string &file, CGcontext ctx)
|
||||
{
|
||||
CGerror err = cgGetError();
|
||||
if (err != CG_NO_ERROR) {
|
||||
if (err == CG_COMPILER_ERROR) {
|
||||
string listing = cgGetLastListing(ctx);
|
||||
vector_string errlines;
|
||||
tokenize(listing, errlines, "\n");
|
||||
for (int i=0; i<(int)errlines.size(); i++) {
|
||||
string line = trim(errlines[i]);
|
||||
if (line != "") {
|
||||
dxgsg9_cat.error() << file << " " << errlines[i] << "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dxgsg9_cat.error() << file << ": " << cgGetErrorString(err) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // HAVE_CGDX9
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXShaderContext9::suggest_cg_profile
|
||||
// Access: Private
|
||||
// Description: xyz
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef HAVE_CGDX9
|
||||
void CLP(ShaderContext)::
|
||||
suggest_cg_profile(const string &vpro, const string &fpro)
|
||||
{
|
||||
// If a good profile has already been suggested, ignore suggestion.
|
||||
if ((_cg_profile[SHADER_type_vert] != CG_PROFILE_UNKNOWN)||
|
||||
(_cg_profile[SHADER_type_frag] != CG_PROFILE_UNKNOWN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the suggestion. If not parseable, print error and ignore.
|
||||
_cg_profile[SHADER_type_vert] = parse_cg_profile(vpro, true);
|
||||
_cg_profile[SHADER_type_frag] = parse_cg_profile(fpro, false);
|
||||
if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
|
||||
(_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
|
||||
dxgsg9_cat.error() << "Cg: unrecognized profile name: " << vpro << " " << fpro << "\n";
|
||||
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
|
||||
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
|
||||
return;
|
||||
}
|
||||
|
||||
// NO EQUIVALENT FUNCTIONALITY FROM GL TO DX
|
||||
/*
|
||||
// If the suggestion is parseable, but not supported, ignore silently.
|
||||
if ((!cgGLIsProfileSupported(_cg_profile[SHADER_type_vert]))||
|
||||
(!cgGLIsProfileSupported(_cg_profile[SHADER_type_frag]))) {
|
||||
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
|
||||
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXShaderContext9::parse_cg_profile
|
||||
// Access: Private
|
||||
// Description: xyz
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef HAVE_CGDX9
|
||||
CGprofile CLP(ShaderContext)::
|
||||
parse_cg_profile(const string &id, bool vertex)
|
||||
{
|
||||
int i = 0;
|
||||
CGprofile vprofiles[] = { CG_PROFILE_ARBVP1, CG_PROFILE_VP20, CG_PROFILE_VP30, CG_PROFILE_VP40, CG_PROFILE_UNKNOWN };
|
||||
CGprofile fprofiles[] = { CG_PROFILE_ARBFP1, CG_PROFILE_FP20, CG_PROFILE_FP30, CG_PROFILE_FP40, CG_PROFILE_UNKNOWN };
|
||||
|
||||
// near equivalent DX profiles
|
||||
#if (CG_VERSION_NUM >= 1502)
|
||||
CGprofile dx_vprofiles[] = { CG_PROFILE_VS_2_0, CG_PROFILE_VS_1_1, CG_PROFILE_VS_2_X, CG_PROFILE_VS_3_0, CG_PROFILE_UNKNOWN };
|
||||
CGprofile dx_fprofiles[] = { CG_PROFILE_PS_2_0, CG_PROFILE_PS_1_1, CG_PROFILE_PS_2_X, CG_PROFILE_PS_3_0, CG_PROFILE_UNKNOWN };
|
||||
#else
|
||||
CGprofile dx_vprofiles[] = { CG_PROFILE_VS_2_0, CG_PROFILE_VS_1_1, CG_PROFILE_VS_2_X, CG_PROFILE_VS_2_X, CG_PROFILE_UNKNOWN };
|
||||
CGprofile dx_fprofiles[] = { CG_PROFILE_PS_2_0, CG_PROFILE_PS_1_1, CG_PROFILE_PS_2_X, CG_PROFILE_PS_2_X, CG_PROFILE_UNKNOWN };
|
||||
#endif
|
||||
|
||||
if (vertex) {
|
||||
while (vprofiles[i] != CG_PROFILE_UNKNOWN) {
|
||||
if (id == cgGetProfileString(vprofiles[i])) {
|
||||
return dx_vprofiles[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
while (fprofiles[i] != CG_PROFILE_UNKNOWN) {
|
||||
if (id == cgGetProfileString(fprofiles[i])) {
|
||||
return dx_fprofiles[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return CG_PROFILE_UNKNOWN;
|
||||
}
|
||||
#endif // HAVE_CGDX9
|
||||
|
||||
int save_file (int size, void *data, char *file_path)
|
||||
{
|
||||
int state;
|
||||
int file_handle;
|
||||
|
||||
state = false;
|
||||
file_handle = _open (file_path, _O_CREAT | _O_RDWR | _O_TRUNC, _S_IREAD | _S_IWRITE);
|
||||
if (file_handle != -1) {
|
||||
if (_write (file_handle, data, size) == size) {
|
||||
state = true;
|
||||
}
|
||||
_close (file_handle);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXShaderContext9::try_cg_compile
|
||||
// Access: Private
|
||||
// Description: xyz
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef HAVE_CGDX9
|
||||
bool CLP(ShaderContext)::
|
||||
try_cg_compile(ShaderExpansion *s, GSG *gsg)
|
||||
{
|
||||
cgGetError();
|
||||
_cg_program[0] =
|
||||
cgCreateProgram(gsg -> _cg_context, CG_SOURCE, s->_text.c_str(),
|
||||
_cg_profile[0], vertex_shader_function_name, (const char**)NULL);
|
||||
report_cg_compile_errors(s->get_name(), gsg -> _cg_context);
|
||||
|
||||
cgGetError();
|
||||
_cg_program[1] =
|
||||
cgCreateProgram(gsg -> _cg_context, CG_SOURCE, s->_text.c_str(),
|
||||
_cg_profile[1], pixel_shader_function_name, (const char**)NULL);
|
||||
report_cg_compile_errors(s->get_name(), gsg -> _cg_context);
|
||||
|
||||
if ((_cg_program[SHADER_type_vert]==0)||(_cg_program[SHADER_type_frag]==0)) {
|
||||
release_resources();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
// DEBUG: output the generated program
|
||||
const char *vertex_program;
|
||||
const char *pixel_program;
|
||||
|
||||
vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
|
||||
pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
|
||||
|
||||
dxgsg9_cat.debug() << vertex_program << "\n";
|
||||
dxgsg9_cat.debug() << pixel_program << "\n";
|
||||
|
||||
// save the generated program to a file
|
||||
int size;
|
||||
char file_path [512];
|
||||
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
|
||||
_splitpath (_name.c_str ( ), drive, dir, fname, ext);
|
||||
|
||||
size = strlen (vertex_program);
|
||||
sprintf (file_path, "%s.vasm", fname);
|
||||
save_file (size, (void *) vertex_program, file_path);
|
||||
|
||||
size = strlen (pixel_program);
|
||||
sprintf (file_path, "%s.pasm", fname);
|
||||
save_file (size, (void *) pixel_program, file_path);
|
||||
}
|
||||
|
||||
// The following code is present to work around a bug in the Cg compiler.
|
||||
// It does not generate correct code for shadow map lookups when using arbfp1.
|
||||
// This is a particularly onerous limitation, given that arbfp1 is the only
|
||||
// Cg target that works on radeons. I suspect this is an intentional
|
||||
// omission on nvidia's part. The following code fetches the output listing,
|
||||
// detects the error, repairs the code, and resumbits the repaired code to Cg.
|
||||
if ((_cg_profile[1] == CG_PROFILE_ARBFP1) && (gsg->_supports_shadow_filter)) {
|
||||
bool shadowunit[32];
|
||||
bool anyshadow = false;
|
||||
memset(shadowunit, 0, sizeof(shadowunit));
|
||||
vector_string lines;
|
||||
tokenize(cgGetProgramString(_cg_program[1], CG_COMPILED_PROGRAM), lines, "\n");
|
||||
// figure out which texture units contain shadow maps.
|
||||
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
|
||||
if (lines[lineno].compare(0,21,"#var sampler2DSHADOW ")) {
|
||||
continue;
|
||||
}
|
||||
vector_string fields;
|
||||
tokenize(lines[lineno], fields, ":");
|
||||
if (fields.size()!=5) {
|
||||
continue;
|
||||
}
|
||||
vector_string words;
|
||||
tokenize(trim(fields[2]), words, " ");
|
||||
if (words.size()!=2) {
|
||||
continue;
|
||||
}
|
||||
int unit = atoi(words[1].c_str());
|
||||
if ((unit < 0)||(unit >= 32)) {
|
||||
continue;
|
||||
}
|
||||
anyshadow = true;
|
||||
shadowunit[unit] = true;
|
||||
}
|
||||
// modify all TEX statements that use the relevant texture units.
|
||||
if (anyshadow) {
|
||||
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
|
||||
if (lines[lineno].compare(0,4,"TEX ")) {
|
||||
continue;
|
||||
}
|
||||
vector_string fields;
|
||||
tokenize(lines[lineno], fields, ",");
|
||||
if ((fields.size()!=4)||(trim(fields[3]) != "2D;")) {
|
||||
continue;
|
||||
}
|
||||
vector_string texunitf;
|
||||
tokenize(trim(fields[2]), texunitf, "[]");
|
||||
if ((texunitf.size()!=3)||(texunitf[0] != "texture")||(texunitf[2]!="")) {
|
||||
continue;
|
||||
}
|
||||
int unit = atoi(texunitf[1].c_str());
|
||||
if ((unit < 0) || (unit >= 32) || (shadowunit[unit]==false)) {
|
||||
continue;
|
||||
}
|
||||
lines[lineno] = fields[0]+","+fields[1]+","+fields[2]+", SHADOW2D;";
|
||||
}
|
||||
string result = "!!ARBfp1.0\nOPTION ARB_fragment_program_shadow;\n";
|
||||
for (int lineno=1; lineno<(int)lines.size(); lineno++) {
|
||||
result += (lines[lineno] + "\n");
|
||||
}
|
||||
cgDestroyProgram(_cg_program[1]);
|
||||
_cg_program[1] =
|
||||
cgCreateProgram(gsg -> _cg_context, CG_OBJECT, result.c_str(),
|
||||
_cg_profile[1], "fshader", (const char**)NULL);
|
||||
report_cg_compile_errors(s->get_name(), gsg -> _cg_context);
|
||||
if (_cg_program[SHADER_type_frag]==0) {
|
||||
release_resources();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
CGparameter parameter;
|
||||
for (int progindex=0; progindex<2; progindex++) {
|
||||
int nvtx = _var_spec.size();
|
||||
for (parameter = cgGetFirstLeafParameter(_cg_program[progindex],CG_PROGRAM);
|
||||
parameter != 0;
|
||||
parameter = cgGetNextLeafParameter(parameter)) {
|
||||
CGenum vbl = cgGetParameterVariability(parameter);
|
||||
if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)) {
|
||||
success &= compile_parameter(parameter,
|
||||
cgGetParameterName(parameter),
|
||||
cg_type_to_panda_type(cgGetParameterType(parameter)),
|
||||
cg_dir_to_panda_dir(cgGetParameterDirection(parameter)),
|
||||
(vbl == CG_VARYING),
|
||||
dxgsg9_cat.get_safe_ptr());
|
||||
}
|
||||
}
|
||||
if ((progindex == SHADER_type_frag) && (nvtx != _var_spec.size())) {
|
||||
dxgsg9_cat.error() << "Cannot use vtx parameters in an fshader\n";
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
release_resources();
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL paramater_shadowing;
|
||||
DWORD assembly_flags;
|
||||
|
||||
paramater_shadowing = FALSE;
|
||||
assembly_flags = 0;
|
||||
|
||||
#if DEBUG_SHADER
|
||||
assembly_flags |= D3DXSHADER_DEBUG;
|
||||
#endif
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
hr = cgD3D9LoadProgram(_cg_program[SHADER_type_vert], paramater_shadowing, assembly_flags);
|
||||
if (FAILED (hr)) {
|
||||
dxgsg9_cat.error()
|
||||
<< "vertex shader cgD3D9LoadProgram failed "
|
||||
<< D3DERRORSTRING(hr);
|
||||
|
||||
CGerror error = cgGetError();
|
||||
if (error != CG_NO_ERROR) {
|
||||
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
|
||||
}
|
||||
|
||||
release_resources();
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = cgD3D9LoadProgram(_cg_program[SHADER_type_frag], paramater_shadowing, assembly_flags);
|
||||
if (FAILED (hr)) {
|
||||
dxgsg9_cat.error()
|
||||
<< "pixel shader cgD3D9LoadProgram failed "
|
||||
<< D3DERRORSTRING(hr);
|
||||
|
||||
CGerror error = cgGetError();
|
||||
if (error != CG_NO_ERROR) {
|
||||
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
|
||||
}
|
||||
|
||||
release_resources();
|
||||
return false;
|
||||
}
|
||||
|
||||
DBG_SH2 dxgsg9_cat.debug ( ) << "SHADER: end try_cg_compile \n"; DBG_E
|
||||
|
||||
_state = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
// int save_file (int size, void *data, char *file_path)
|
||||
// {
|
||||
// int state;
|
||||
// int file_handle;
|
||||
//
|
||||
// state = false;
|
||||
// file_handle = _open (file_path, _O_CREAT | _O_RDWR | _O_TRUNC, _S_IREAD | _S_IWRITE);
|
||||
// if (file_handle != -1) {
|
||||
// if (_write (file_handle, data, size) == size) {
|
||||
// state = true;
|
||||
// }
|
||||
// _close (file_handle);
|
||||
// }
|
||||
//
|
||||
// return state;
|
||||
// }
|
||||
//
|
||||
// if (dxgsg9_cat.is_debug()) {
|
||||
// // DEBUG: output the generated program
|
||||
// const char *vertex_program;
|
||||
// const char *pixel_program;
|
||||
//
|
||||
// vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
|
||||
// pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
|
||||
//
|
||||
// dxgsg9_cat.debug() << vertex_program << "\n";
|
||||
// dxgsg9_cat.debug() << pixel_program << "\n";
|
||||
//
|
||||
// // save the generated program to a file
|
||||
// int size;
|
||||
// char file_path [512];
|
||||
//
|
||||
// char drive[_MAX_DRIVE];
|
||||
// char dir[_MAX_DIR];
|
||||
// char fname[_MAX_FNAME];
|
||||
// char ext[_MAX_EXT];
|
||||
//
|
||||
// _splitpath (_name.c_str ( ), drive, dir, fname, ext);
|
||||
//
|
||||
// size = strlen (vertex_program);
|
||||
// sprintf (file_path, "%s.vasm", fname);
|
||||
// save_file (size, (void *) vertex_program, file_path);
|
||||
//
|
||||
// size = strlen (pixel_program);
|
||||
// sprintf (file_path, "%s.pasm", fname);
|
||||
// save_file (size, (void *) pixel_program, file_path);
|
||||
// }
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXShaderContext9::release_resources
|
||||
|
|
@ -514,12 +177,13 @@ try_cg_compile(ShaderExpansion *s, GSG *gsg)
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
release_resources() {
|
||||
#ifdef HAVE_CGDX9
|
||||
{
|
||||
_cg_profile[SHADER_type_vert] = (CGprofile)0;
|
||||
_cg_profile[SHADER_type_frag] = (CGprofile)0;
|
||||
_cg_program[SHADER_type_vert] = (CGprogram)0;
|
||||
_cg_program[SHADER_type_frag] = (CGprogram)0;
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
cgDestroyContext(_cg_context);
|
||||
_cg_context = 0;
|
||||
_cg_vprogram = 0;
|
||||
_cg_fprogram = 0;
|
||||
_cg_parameter_map.clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -537,45 +201,42 @@ bind(GSG *gsg) {
|
|||
bool bind_state;
|
||||
|
||||
bind_state = false;
|
||||
#ifdef HAVE_CGDX9
|
||||
if (_state) {
|
||||
if (gsg -> _cg_context != 0) {
|
||||
DBG_SH5 dxgsg9_cat.debug ( ) << "SHADER: bind \n"; DBG_E
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
DBG_SH5 dxgsg9_cat.debug ( ) << "SHADER: bind \n"; DBG_E
|
||||
|
||||
// clear the last cached FVF to make sure the next SetFVF call goes through
|
||||
|
||||
gsg -> _last_fvf = 0;
|
||||
|
||||
// clear the last cached FVF to make sure the next SetFVF call goes through
|
||||
gsg -> _last_fvf = 0;
|
||||
|
||||
// Pass in k-parameters and transform-parameters
|
||||
issue_parameters(gsg, true);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
if (_cg_shader) {
|
||||
// Bind the shaders.
|
||||
bind_state = true;
|
||||
hr = cgD3D9BindProgram(_cg_program[SHADER_type_vert]);
|
||||
if (FAILED (hr)) {
|
||||
dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed " << D3DERRORSTRING(hr);
|
||||
|
||||
CGerror error = cgGetError();
|
||||
if (error != CG_NO_ERROR) {
|
||||
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
|
||||
}
|
||||
|
||||
bind_state = false;
|
||||
}
|
||||
hr = cgD3D9BindProgram(_cg_program[SHADER_type_frag]);
|
||||
if (FAILED (hr)) {
|
||||
dxgsg9_cat.error() << "cgD3D9BindProgram pixel shader failed " << D3DERRORSTRING(hr);
|
||||
|
||||
CGerror error = cgGetError();
|
||||
if (error != CG_NO_ERROR) {
|
||||
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
|
||||
}
|
||||
|
||||
bind_state = false;
|
||||
}
|
||||
// Pass in k-parameters and transform-parameters
|
||||
issue_parameters(gsg, true);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
// Bind the shaders.
|
||||
bind_state = true;
|
||||
hr = cgD3D9BindProgram(_cg_vprogram);
|
||||
if (FAILED (hr)) {
|
||||
dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed " << D3DERRORSTRING(hr);
|
||||
|
||||
CGerror error = cgGetError();
|
||||
if (error != CG_NO_ERROR) {
|
||||
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
|
||||
}
|
||||
|
||||
bind_state = false;
|
||||
}
|
||||
hr = cgD3D9BindProgram(_cg_fprogram);
|
||||
if (FAILED (hr)) {
|
||||
dxgsg9_cat.error() << "cgD3D9BindProgram pixel shader failed " << D3DERRORSTRING(hr);
|
||||
|
||||
CGerror error = cgGetError();
|
||||
if (error != CG_NO_ERROR) {
|
||||
dxgsg9_cat.error() << " CG ERROR: " << cgGetErrorString(error) << "\n";
|
||||
}
|
||||
|
||||
bind_state = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -591,8 +252,8 @@ bind(GSG *gsg) {
|
|||
void CLP(ShaderContext)::
|
||||
unbind(GSG *gsg) {
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
if (_state) {
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
|
||||
DBG_SH5 dxgsg9_cat.debug ( ) << "SHADER: unbind \n"; DBG_E
|
||||
|
||||
|
|
@ -638,12 +299,12 @@ InternalName *global_internal_name_1 = 0;
|
|||
void CLP(ShaderContext)::
|
||||
issue_parameters(GSG *gsg, bool altered)
|
||||
{
|
||||
#ifdef HAVE_CGDX9
|
||||
if (gsg -> _cg_context != 0) {
|
||||
for (int i=0; i<(int)_mat_spec.size(); i++) {
|
||||
if (altered || _mat_spec[i]._trans_dependent) {
|
||||
CGparameter p = (CGparameter)(_mat_spec[i]._parameter);
|
||||
const LMatrix4f *val = gsg->fetch_specified_value(_mat_spec[i], altered);
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
for (int i=0; i<(int)_expansion->_mat_spec.size(); i++) {
|
||||
if (altered || _expansion->_mat_spec[i]._trans_dependent) {
|
||||
CGparameter p = _cg_parameter_map[_expansion->_mat_spec[i]._id._seqno];
|
||||
const LMatrix4f *val = gsg->fetch_specified_value(_expansion->_mat_spec[i], altered);
|
||||
if (val) {
|
||||
HRESULT hr;
|
||||
float v [4];
|
||||
|
|
@ -658,13 +319,13 @@ issue_parameters(GSG *gsg, bool altered)
|
|||
#if DEBUG_SHADER
|
||||
// DEBUG
|
||||
global_data = (float *) data;
|
||||
global_shader_mat_spec = &_mat_spec[i];
|
||||
global_shader_mat_spec = &_expansion->_mat_spec[i];
|
||||
global_internal_name_0 = global_shader_mat_spec -> _arg [0];
|
||||
global_internal_name_1 = global_shader_mat_spec -> _arg [1];
|
||||
#endif
|
||||
|
||||
switch (_mat_spec[i]._piece) {
|
||||
case SMP_whole:
|
||||
switch (_expansion->_mat_spec[i]._piece) {
|
||||
case ShaderExpansion::SMP_whole:
|
||||
// TRANSPOSE REQUIRED
|
||||
temp_matrix.transpose_from (*val);
|
||||
data = temp_matrix.get_data();
|
||||
|
|
@ -672,7 +333,7 @@ issue_parameters(GSG *gsg, bool altered)
|
|||
hr = cgD3D9SetUniform (p, data);
|
||||
|
||||
DBG_SH2
|
||||
dxgsg9_cat.debug ( ) << "SMP_whole MATRIX \n" <<
|
||||
dxgsg9_cat.debug ( ) << "ShaderExpansion::SMP_whole MATRIX \n" <<
|
||||
data[ 0] << " " << data[ 1] << " " << data[ 2] << " " << data[ 3] << "\n" <<
|
||||
data[ 4] << " " << data[ 5] << " " << data[ 6] << " " << data[ 7] << "\n" <<
|
||||
data[ 8] << " " << data[ 9] << " " << data[10] << " " << data[11] << "\n" <<
|
||||
|
|
@ -681,44 +342,44 @@ issue_parameters(GSG *gsg, bool altered)
|
|||
|
||||
break;
|
||||
|
||||
case SMP_transpose:
|
||||
case ShaderExpansion::SMP_transpose:
|
||||
// NO TRANSPOSE REQUIRED
|
||||
hr = cgD3D9SetUniform (p, data);
|
||||
break;
|
||||
|
||||
case SMP_row0:
|
||||
case ShaderExpansion::SMP_row0:
|
||||
hr = cgD3D9SetUniform (p, data + 0);
|
||||
break;
|
||||
case SMP_row1:
|
||||
case ShaderExpansion::SMP_row1:
|
||||
hr = cgD3D9SetUniform (p, data + 4);
|
||||
break;
|
||||
case SMP_row2:
|
||||
case ShaderExpansion::SMP_row2:
|
||||
hr = cgD3D9SetUniform (p, data + 8);
|
||||
break;
|
||||
case SMP_row3:
|
||||
case ShaderExpansion::SMP_row3:
|
||||
hr = cgD3D9SetUniform (p, data + 12);
|
||||
break;
|
||||
|
||||
case SMP_col0:
|
||||
case ShaderExpansion::SMP_col0:
|
||||
v[0] = data[0]; v[1] = data[4]; v[2] = data[8]; v[3] = data[12];
|
||||
hr = cgD3D9SetUniform (p, v);
|
||||
break;
|
||||
case SMP_col1:
|
||||
case ShaderExpansion::SMP_col1:
|
||||
v[0] = data[1]; v[1] = data[5]; v[2] = data[9]; v[3] = data[13];
|
||||
hr = cgD3D9SetUniform (p, v);
|
||||
break;
|
||||
case SMP_col2:
|
||||
case ShaderExpansion::SMP_col2:
|
||||
v[0] = data[2]; v[1] = data[6]; v[2] = data[10]; v[3] = data[14];
|
||||
hr = cgD3D9SetUniform (p, v);
|
||||
break;
|
||||
case SMP_col3:
|
||||
case ShaderExpansion::SMP_col3:
|
||||
v[0] = data[3]; v[1] = data[7]; v[2] = data[11]; v[3] = data[15];
|
||||
hr = cgD3D9SetUniform (p, v);
|
||||
break;
|
||||
|
||||
default:
|
||||
dxgsg9_cat.error()
|
||||
<< "issue_parameters ( ) SMP parameter type not implemented " << _mat_spec[i]._piece << "\n";
|
||||
<< "issue_parameters ( ) SMP parameter type not implemented " << _expansion->_mat_spec[i]._piece << "\n";
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -726,14 +387,14 @@ issue_parameters(GSG *gsg, bool altered)
|
|||
|
||||
string name = "unnamed";
|
||||
|
||||
if (_mat_spec[i]._arg [0]) {
|
||||
name = _mat_spec[i]._arg [0] -> get_basename ( );
|
||||
if (_expansion->_mat_spec[i]._arg [0]) {
|
||||
name = _expansion->_mat_spec[i]._arg [0] -> get_basename ( );
|
||||
}
|
||||
|
||||
dxgsg9_cat.error()
|
||||
<< "NAME " << name << "\n"
|
||||
<< "MAT TYPE "
|
||||
<< _mat_spec[i]._piece
|
||||
<< _expansion->_mat_spec[i]._piece
|
||||
<< " cgD3D9SetUniform failed "
|
||||
<< D3DERRORSTRING(hr);
|
||||
|
||||
|
|
@ -757,14 +418,9 @@ issue_parameters(GSG *gsg, bool altered)
|
|||
void CLP(ShaderContext)::
|
||||
disable_shader_vertex_arrays(GSG *gsg)
|
||||
{
|
||||
#ifdef HAVE_CGDX9
|
||||
if (gsg -> _cg_context) {
|
||||
for (int i=0; i<(int)_var_spec.size(); i++) {
|
||||
CGparameter p = (CGparameter)(_var_spec[i]._parameter);
|
||||
|
||||
// DO NOTHING, CURRENTLY USING ONLY ONE STREAM SOURCE
|
||||
|
||||
}
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
// DO NOTHING, CURRENTLY USING ONLY ONE STREAM SOURCE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -790,8 +446,8 @@ void CLP(ShaderContext)::
|
|||
update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
|
||||
{
|
||||
if (prev) prev->disable_shader_vertex_arrays(gsg);
|
||||
#ifdef HAVE_CGDX9
|
||||
if (gsg -> _cg_context) {
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
|
||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
||||
/*
|
||||
|
|
@ -806,7 +462,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
|
|||
const GeomVertexArrayDataPipelineReader *array_reader;
|
||||
Geom::NumericType numeric_type;
|
||||
int start, stride, num_values;
|
||||
int nvarying = _var_spec.size();
|
||||
int nvarying = _expansion->_var_spec.size();
|
||||
|
||||
int stream_index;
|
||||
VertexElementArray *vertex_element_array;
|
||||
|
|
@ -822,9 +478,9 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
|
|||
#endif
|
||||
|
||||
for (int i=0; i<nvarying; i++) {
|
||||
CGparameter p = (CGparameter)(_var_spec[i]._parameter);
|
||||
InternalName *name = _var_spec[i]._name;
|
||||
int texslot = _var_spec[i]._append_uv;
|
||||
CGparameter p = _cg_parameter_map[_expansion->_var_spec[i]._id._seqno];
|
||||
InternalName *name = _expansion->_var_spec[i]._name;
|
||||
int texslot = _expansion->_var_spec[i]._append_uv;
|
||||
if (texslot >= 0) {
|
||||
const Geom::ActiveTextureStages &active_stages =
|
||||
gsg->_state._texture->get_on_stages();
|
||||
|
|
@ -982,8 +638,8 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
|
|||
|
||||
state = vertex_element_array -> add_end_vertex_element ( );
|
||||
if (state) {
|
||||
if (_cg_shader) {
|
||||
if (cgD3D9ValidateVertexDeclaration (_cg_program [SHADER_type_vert],
|
||||
if (_cg_context) {
|
||||
if (cgD3D9ValidateVertexDeclaration (_cg_vprogram,
|
||||
vertex_element_array -> vertex_element_array) == CG_TRUE) {
|
||||
dxgsg9_cat.debug() << "|||||cgD3D9ValidateVertexDeclaration succeeded\n";
|
||||
}
|
||||
|
|
@ -1013,7 +669,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // HAVE_CGDX9
|
||||
#endif // HAVE_CG
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1024,10 +680,10 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
|
|||
void CLP(ShaderContext)::
|
||||
disable_shader_texture_bindings(GSG *gsg)
|
||||
{
|
||||
#ifdef HAVE_CGDX9
|
||||
if (gsg -> _cg_context) {
|
||||
for (int i=0; i<(int)_tex_spec.size(); i++) {
|
||||
CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
|
||||
CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
|
||||
int texunit = cgGetParameterResourceIndex(p);
|
||||
|
||||
HRESULT hr;
|
||||
|
|
@ -1061,40 +717,40 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg)
|
|||
{
|
||||
if (prev) prev->disable_shader_texture_bindings(gsg);
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
if (gsg -> _cg_context) {
|
||||
for (int i=0; i<(int)_tex_spec.size(); i++) {
|
||||
CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
|
||||
CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
|
||||
Texture *tex = 0;
|
||||
InternalName *id = _tex_spec[i]._name;
|
||||
InternalName *id = _expansion->_tex_spec[i]._name;
|
||||
if (id != 0) {
|
||||
const ShaderInput *input = gsg->_target._shader->get_shader_input(id);
|
||||
tex = input->get_texture();
|
||||
} else {
|
||||
if (_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
|
||||
if (_expansion->_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
|
||||
continue;
|
||||
}
|
||||
TextureStage *stage = gsg->_target._texture->get_on_stage(_tex_spec[i]._stage);
|
||||
TextureStage *stage = gsg->_target._texture->get_on_stage(_expansion->_tex_spec[i]._stage);
|
||||
tex = gsg->_target._texture->get_on_texture(stage);
|
||||
}
|
||||
if (_tex_spec[i]._suffix != 0) {
|
||||
if (_expansion->_tex_spec[i]._suffix != 0) {
|
||||
// The suffix feature is inefficient. It is a temporary hack.
|
||||
if (tex == 0) {
|
||||
continue;
|
||||
}
|
||||
tex = tex->load_related(_tex_spec[i]._suffix);
|
||||
tex = tex->load_related(_expansion->_tex_spec[i]._suffix);
|
||||
}
|
||||
if ((tex == 0) || (tex->get_texture_type() != _tex_spec[i]._desired_type)) {
|
||||
if ((tex == 0) || (tex->get_texture_type() != _expansion->_tex_spec[i]._desired_type)) {
|
||||
continue;
|
||||
}
|
||||
TextureContext *tc = tex->prepare_now(gsg->_prepared_objects, gsg);
|
||||
// TextureContext *tc = tex->prepare_now(gsg->get_prepared_objects(), gsg);
|
||||
// TextureContext *tc = tex->prepare_now(gsg->get_prepared_objects(), gsg);
|
||||
if (tc == (TextureContext*)NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int texunit = cgGetParameterResourceIndex(p);
|
||||
|
||||
|
||||
gsg->apply_texture(texunit, tc);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,11 +21,6 @@
|
|||
|
||||
#include "dtool_config.h"
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_CGDX9
|
||||
#include "Cg/cg.h"
|
||||
#include "Cg/cgGL.h"
|
||||
#include "Cg/cgD3D9.h"
|
||||
#endif
|
||||
#include "string_utils.h"
|
||||
#include "internalName.h"
|
||||
#include "shaderExpansion.h"
|
||||
|
|
@ -39,47 +34,49 @@
|
|||
class VertexElementArray;
|
||||
class CLP(GraphicsStateGuardian);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int vertex_shader;
|
||||
int total_constant_descriptions;
|
||||
D3DXCONSTANT_DESC *constant_description_array;
|
||||
}
|
||||
DX_PARAMETER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int state;
|
||||
union
|
||||
{
|
||||
DIRECT_3D_VERTEX_SHADER direct_3d_vertex_shader;
|
||||
DIRECT_3D_PIXEL_SHADER direct_3d_pixel_shader;
|
||||
};
|
||||
LPD3DXCONSTANTTABLE constant_table;
|
||||
D3DXCONSTANTTABLE_DESC constant_table_description;
|
||||
|
||||
int total_semantics;
|
||||
D3DXSEMANTIC *semantic_array;
|
||||
}
|
||||
DIRECT_3D_SHADER;
|
||||
// Caution: adding HLSL support is going to be tricky, as the parsing needs
|
||||
// to be done in the cull thread, which cannot use the DX API. - Josh
|
||||
//
|
||||
//
|
||||
// typedef struct
|
||||
// {
|
||||
// int vertex_shader;
|
||||
// int total_constant_descriptions;
|
||||
// D3DXCONSTANT_DESC *constant_description_array;
|
||||
// }
|
||||
// DX_PARAMETER;
|
||||
//
|
||||
// typedef struct
|
||||
// {
|
||||
// int state;
|
||||
// union
|
||||
// {
|
||||
// DIRECT_3D_VERTEX_SHADER direct_3d_vertex_shader;
|
||||
// DIRECT_3D_PIXEL_SHADER direct_3d_pixel_shader;
|
||||
// };
|
||||
// LPD3DXCONSTANTTABLE constant_table;
|
||||
// D3DXCONSTANTTABLE_DESC constant_table_description;
|
||||
//
|
||||
// int total_semantics;
|
||||
// D3DXSEMANTIC *semantic_array;
|
||||
// }
|
||||
// DIRECT_3D_SHADER;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : DXShaderContext9
|
||||
// Description : xyz
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef CLP(GraphicsStateGuardian) GSG;
|
||||
|
||||
class EXPCL_PANDADX CLP(ShaderContext): public ShaderContext {
|
||||
public:
|
||||
|
||||
typedef CLP(GraphicsStateGuardian) GSG;
|
||||
|
||||
CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg);
|
||||
~CLP(ShaderContext)();
|
||||
|
||||
INLINE bool valid(GSG *gsg);
|
||||
bool bind(GSG *gsg);
|
||||
void unbind(GSG *gsg);
|
||||
|
||||
void issue_parameters(GSG *gsg, bool altered);
|
||||
void issue_transform(GSG *gsg);
|
||||
void disable_shader_vertex_arrays(GSG *gsg);
|
||||
|
|
@ -87,69 +84,21 @@ public:
|
|||
void disable_shader_texture_bindings(GSG *gsg);
|
||||
void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
|
||||
|
||||
int _vertex_size;
|
||||
class VertexElementArray *_vertex_element_array;
|
||||
|
||||
// FOR DEBUGGING
|
||||
int _vertex_size;
|
||||
string _name;
|
||||
|
||||
bool _state;
|
||||
bool _cg_shader;
|
||||
bool _transpose_matrix;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
#ifdef HAVE_CGDX9
|
||||
struct ShaderAutoBind {
|
||||
CGparameter parameter;
|
||||
int value;
|
||||
DX_PARAMETER *dx_parameter;
|
||||
};
|
||||
struct ShaderArgBind {
|
||||
CGparameter parameter;
|
||||
PT(InternalName) name;
|
||||
DX_PARAMETER *dx_parameter;
|
||||
};
|
||||
struct ShaderTexBind {
|
||||
CGparameter parameter;
|
||||
PT(InternalName) name;
|
||||
int stage;
|
||||
int desiredtype;
|
||||
PT(InternalName) suffix;
|
||||
DX_PARAMETER *dx_parameter;
|
||||
};
|
||||
struct ShaderTransBind {
|
||||
CGparameter parameter;
|
||||
PT(InternalName) src_name;
|
||||
PT(InternalName) rel_name;
|
||||
int trans_piece;
|
||||
DX_PARAMETER *dx_parameter;
|
||||
};
|
||||
struct ShaderVarying {
|
||||
CGparameter parameter;
|
||||
PT(InternalName) name;
|
||||
int append_uv;
|
||||
DX_PARAMETER *dx_parameter;
|
||||
};
|
||||
|
||||
// CGcontext _cg_context;
|
||||
CGprofile _cg_profile[2];
|
||||
CGprogram _cg_program[2];
|
||||
|
||||
void report_cg_compile_errors(const string &file, CGcontext ctx);
|
||||
|
||||
bool try_cg_compile(ShaderExpansion *s, GSG *gsg);
|
||||
void suggest_cg_profile(const string &vpro, const string &fpro);
|
||||
CGprofile parse_cg_profile(const string &id, bool vertex);
|
||||
#ifdef HAVE_CG
|
||||
CGcontext _cg_context;
|
||||
CGprogram _cg_vprogram;
|
||||
CGprogram _cg_fprogram;
|
||||
pvector <CGparameter> _cg_parameter_map;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
DIRECT_3D_SHADER _direct_3d_vertex_shader;
|
||||
DIRECT_3D_SHADER _direct_3d_pixel_shader;
|
||||
int _total_dx_parameters;
|
||||
DX_PARAMETER *_dx_parameter_array;
|
||||
|
||||
private:
|
||||
|
||||
void release_resources(void);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@
|
|||
#include "indirectLess.h"
|
||||
#include "pStatTimer.h"
|
||||
|
||||
#ifdef HAVE_CG
|
||||
#include "Cg/cgGL.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#define DEBUG_BUFFERS false
|
||||
|
|
@ -669,10 +673,14 @@ reset() {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) &&
|
||||
cgGLIsProfileSupported(CG_PROFILE_ARBVP1)) {
|
||||
_supports_basic_shaders = true;
|
||||
_shader_caps._active_vprofile = (int)cgGLGetLatestProfile(CG_GL_VERTEX);
|
||||
_shader_caps._active_fprofile = (int)cgGLGetLatestProfile(CG_GL_FRAGMENT);
|
||||
_shader_caps._ultimate_vprofile = (int)CG_PROFILE_VP40;
|
||||
_shader_caps._ultimate_fprofile = (int)CG_PROFILE_FP40;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1076,7 +1084,7 @@ reset() {
|
|||
void gl_set_stencil_functions (StencilRenderStates *stencil_render_states);
|
||||
gl_set_stencil_functions (_stencil_render_states);
|
||||
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
@ -3357,7 +3365,7 @@ do_issue_shader() {
|
|||
ShaderExpansion *expansion = _target_rs->get_shader_expansion();
|
||||
if (expansion == 0) {
|
||||
if (_target._shader->get_shader() != 0) {
|
||||
expansion = _target._shader->get_shader()->macroexpand(_target_rs);
|
||||
expansion = _target._shader->get_shader()->macroexpand(_target_rs, _shader_caps);
|
||||
// I am casting away the const-ness of this pointer, because
|
||||
// the 'shader-expansion' field is just a cache.
|
||||
((RenderState *)((const RenderState*)_target_rs))->
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CLP(ShaderContext)::
|
||||
valid() {
|
||||
#ifdef HAVE_CGGL
|
||||
if (_state && _cg_context) return true;
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,49 +16,14 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef HAVE_CG
|
||||
#include "Cg/cgGL.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG_GL_SHADER 0
|
||||
|
||||
TypeHandle CLP(ShaderContext)::_type_handle;
|
||||
|
||||
#ifdef HAVE_CGGL
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: cg_type_to_panda_type
|
||||
// Access: Public, Static
|
||||
// Description: convert a cg shader-arg type to a panda shader-arg type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static ShaderContext::ShaderArgType
|
||||
cg_type_to_panda_type(CGtype n) {
|
||||
switch (n) {
|
||||
case CG_FLOAT1: return ShaderContext::SAT_float1;
|
||||
case CG_FLOAT2: return ShaderContext::SAT_float2;
|
||||
case CG_FLOAT3: return ShaderContext::SAT_float3;
|
||||
case CG_FLOAT4: return ShaderContext::SAT_float4;
|
||||
case CG_FLOAT4x4: return ShaderContext::SAT_float4x4;
|
||||
case CG_SAMPLER1D: return ShaderContext::SAT_sampler1d;
|
||||
case CG_SAMPLER2D: return ShaderContext::SAT_sampler2d;
|
||||
case CG_SAMPLER3D: return ShaderContext::SAT_sampler3d;
|
||||
case CG_SAMPLERCUBE: return ShaderContext::SAT_samplercube;
|
||||
default: return ShaderContext::SAT_unknown;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_CGGL
|
||||
|
||||
#ifdef HAVE_CGGL
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: cg_dir_to_panda_dir
|
||||
// Access: Public, Static
|
||||
// Description: convert a cg shader-arg type to a panda shader-arg type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static ShaderContext::ShaderArgDir
|
||||
cg_dir_to_panda_dir(CGenum n) {
|
||||
switch (n) {
|
||||
case CG_IN: return ShaderContext::SAD_in;
|
||||
case CG_OUT: return ShaderContext::SAD_out;
|
||||
case CG_INOUT: return ShaderContext::SAD_inout;
|
||||
default: return ShaderContext::SAD_unknown;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_CGGL
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLShaderContext::Constructor
|
||||
|
|
@ -67,311 +32,34 @@ cg_dir_to_panda_dir(CGenum n) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
CLP(ShaderContext)::
|
||||
CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
|
||||
string header;
|
||||
s->parse_init();
|
||||
s->parse_line(header, true, true);
|
||||
#ifdef HAVE_CG
|
||||
if (s->get_header() == "//Cg") {
|
||||
|
||||
// Ask the shader expansion to compile itself for us and
|
||||
// to give us the resulting Cg program objects.
|
||||
|
||||
_state = false;
|
||||
|
||||
#ifdef HAVE_CGGL
|
||||
_cg_context = (CGcontext)0;
|
||||
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
|
||||
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
|
||||
_cg_program[SHADER_type_vert] = (CGprogram)0;
|
||||
_cg_program[SHADER_type_frag] = (CGprogram)0;
|
||||
_cg_program[2] = (CGprogram)0;
|
||||
|
||||
if (header == "//Cg") {
|
||||
// Create the Cg context.
|
||||
_cg_context = cgCreateContext();
|
||||
if (_cg_context == 0) {
|
||||
release_resources();
|
||||
GLCAT.error() << "Cg not supported by this video card.\n";
|
||||
if (!s->cg_compile_for(gsg->_shader_caps,
|
||||
_cg_context,
|
||||
_cg_vprogram,
|
||||
_cg_fprogram,
|
||||
_cg_parameter_map)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse any directives in the source.
|
||||
string directive;
|
||||
while (!s->parse_eof()) {
|
||||
s->parse_line(directive, true, true);
|
||||
vector_string pieces;
|
||||
tokenize(directive, pieces, " \t");
|
||||
if ((pieces.size()==4)&&(pieces[0]=="//Cg")&&(pieces[1]=="profile")) {
|
||||
suggest_cg_profile(pieces[2], pieces[3]);
|
||||
}
|
||||
}
|
||||
|
||||
// Select a profile if no preferred profile specified in the source.
|
||||
if (_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN) {
|
||||
_cg_profile[SHADER_type_vert] = cgGLGetLatestProfile(CG_GL_VERTEX);
|
||||
}
|
||||
if (_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN) {
|
||||
_cg_profile[SHADER_type_frag] = cgGLGetLatestProfile(CG_GL_FRAGMENT);
|
||||
}
|
||||
|
||||
// If we still haven't chosen a profile, give up.
|
||||
if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
|
||||
(_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
|
||||
|
||||
// Load the program.
|
||||
|
||||
cgGLLoadProgram(_cg_vprogram);
|
||||
CGerror verror = cgGetError();
|
||||
cgGLLoadProgram(_cg_fprogram);
|
||||
CGerror ferror = cgGetError();
|
||||
if ((verror != CG_NO_ERROR)||(ferror != CG_NO_ERROR)) {
|
||||
GLCAT.error() << "Could not load Cg shader:" << s->get_name() << "\n";
|
||||
release_resources();
|
||||
GLCAT.error() << "Cg not supported by this video card.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Compile the program.
|
||||
try_cg_compile(s, gsg);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
GLCAT.error() << s->get_name() << ": unrecognized shader language " << header << "\n";
|
||||
}
|
||||
|
||||
#ifdef HAVE_CGGL
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::report_cg_compile_errors
|
||||
// Access: Public, Static
|
||||
// Description: Used only after a Cg compile command, to print
|
||||
// out any error messages that may have occurred
|
||||
// during the Cg shader compilation. The 'file'
|
||||
// is the name of the file containing the Cg code.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
report_cg_compile_errors(const string &file, CGcontext ctx)
|
||||
{
|
||||
CGerror err = cgGetError();
|
||||
if (err != CG_NO_ERROR) {
|
||||
if (err == CG_COMPILER_ERROR) {
|
||||
string listing = cgGetLastListing(ctx);
|
||||
vector_string errlines;
|
||||
tokenize(listing, errlines, "\n");
|
||||
for (int i=0; i<(int)errlines.size(); i++) {
|
||||
string line = trim(errlines[i]);
|
||||
if (line != "") {
|
||||
GLCAT.error() << file << " " << errlines[i] << "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GLCAT.error() << file << ": " << cgGetErrorString(err) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // HAVE_CGGL
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLShaderContext::suggest_cg_profile
|
||||
// Access: Private
|
||||
// Description: xyz
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef HAVE_CGGL
|
||||
void CLP(ShaderContext)::
|
||||
suggest_cg_profile(const string &vpro, const string &fpro)
|
||||
{
|
||||
// If a good profile has already been suggested, ignore suggestion.
|
||||
if ((_cg_profile[SHADER_type_vert] != CG_PROFILE_UNKNOWN)||
|
||||
(_cg_profile[SHADER_type_frag] != CG_PROFILE_UNKNOWN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the suggestion. If not parseable, print error and ignore.
|
||||
_cg_profile[SHADER_type_vert] = parse_cg_profile(vpro, true);
|
||||
_cg_profile[SHADER_type_frag] = parse_cg_profile(fpro, false);
|
||||
if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
|
||||
(_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
|
||||
GLCAT.error() << "Cg: unrecognized profile name: " << vpro << " " << fpro << "\n";
|
||||
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
|
||||
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
|
||||
return;
|
||||
}
|
||||
|
||||
// If the suggestion is parseable, but not supported, ignore silently.
|
||||
if ((!cgGLIsProfileSupported(_cg_profile[SHADER_type_vert]))||
|
||||
(!cgGLIsProfileSupported(_cg_profile[SHADER_type_frag]))) {
|
||||
_cg_profile[SHADER_type_vert] = CG_PROFILE_UNKNOWN;
|
||||
_cg_profile[SHADER_type_frag] = CG_PROFILE_UNKNOWN;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLShaderContext::parse_cg_profile
|
||||
// Access: Private
|
||||
// Description: xyz
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef HAVE_CGGL
|
||||
CGprofile CLP(ShaderContext)::
|
||||
parse_cg_profile(const string &id, bool vertex)
|
||||
{
|
||||
int nvprofiles = 4;
|
||||
int nfprofiles = 4;
|
||||
CGprofile vprofiles[] = { CG_PROFILE_ARBVP1, CG_PROFILE_VP20, CG_PROFILE_VP30, CG_PROFILE_VP40 };
|
||||
CGprofile fprofiles[] = { CG_PROFILE_ARBFP1, CG_PROFILE_FP20, CG_PROFILE_FP30, CG_PROFILE_FP40 };
|
||||
if (vertex) {
|
||||
for (int i=0; i<nvprofiles; i++) {
|
||||
if (id == cgGetProfileString(vprofiles[i])) {
|
||||
return vprofiles[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<nfprofiles; i++) {
|
||||
if (id == cgGetProfileString(fprofiles[i])) {
|
||||
return fprofiles[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return CG_PROFILE_UNKNOWN;
|
||||
}
|
||||
#endif // HAVE_CGGL
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLShaderContext::try_cg_compile
|
||||
// Access: Private
|
||||
// Description: xyz
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifdef HAVE_CGGL
|
||||
bool CLP(ShaderContext)::
|
||||
try_cg_compile(ShaderExpansion *s, GSG *gsg)
|
||||
{
|
||||
cgGetError();
|
||||
_cg_program[0] =
|
||||
cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
|
||||
_cg_profile[0], "vshader", (const char**)NULL);
|
||||
report_cg_compile_errors(s->get_name(), _cg_context);
|
||||
|
||||
cgGetError();
|
||||
_cg_program[1] =
|
||||
cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
|
||||
_cg_profile[1], "fshader", (const char**)NULL);
|
||||
report_cg_compile_errors(s->get_name(), _cg_context);
|
||||
|
||||
if ((_cg_program[SHADER_type_vert]==0)||(_cg_program[SHADER_type_frag]==0)) {
|
||||
release_resources();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
CGparameter parameter;
|
||||
for (int progindex=0; progindex<2; progindex++) {
|
||||
int nvtx = _var_spec.size();
|
||||
for (parameter = cgGetFirstLeafParameter(_cg_program[progindex],CG_PROGRAM);
|
||||
parameter != 0;
|
||||
parameter = cgGetNextLeafParameter(parameter)) {
|
||||
CGenum vbl = cgGetParameterVariability(parameter);
|
||||
if ((vbl==CG_VARYING)||(vbl==CG_UNIFORM)) {
|
||||
success &= compile_parameter(parameter,
|
||||
cgGetParameterName(parameter),
|
||||
cg_type_to_panda_type(cgGetParameterType(parameter)),
|
||||
cg_dir_to_panda_dir(cgGetParameterDirection(parameter)),
|
||||
(vbl == CG_VARYING),
|
||||
GLCAT.get_safe_ptr());
|
||||
}
|
||||
}
|
||||
if ((progindex == SHADER_type_frag) && (nvtx != _var_spec.size())) {
|
||||
GLCAT.error() << "Cannot use vtx parameters in an fshader\n";
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
release_resources();
|
||||
return false;
|
||||
}
|
||||
|
||||
// DEBUG: output the generated program
|
||||
if (GLCAT.is_debug()) {
|
||||
const char *vertex_program;
|
||||
const char *pixel_program;
|
||||
|
||||
vertex_program = cgGetProgramString (_cg_program[0], CG_COMPILED_PROGRAM);
|
||||
pixel_program = cgGetProgramString (_cg_program[1], CG_COMPILED_PROGRAM);
|
||||
|
||||
GLCAT.debug() << vertex_program << "\n";
|
||||
GLCAT.debug() << pixel_program << "\n";
|
||||
}
|
||||
|
||||
// The following code is present to work around a bug in the Cg compiler.
|
||||
// It does not generate correct code for shadow map lookups when using arbfp1.
|
||||
// This is a particularly onerous limitation, given that arbfp1 is the only
|
||||
// Cg target that works on radeons. I suspect this is an intentional
|
||||
// omission on nvidia's part. The following code fetches the output listing,
|
||||
// detects the error, repairs the code, and resumbits the repaired code to Cg.
|
||||
if ((_cg_profile[1] == CG_PROFILE_ARBFP1) && (gsg->_supports_shadow_filter)) {
|
||||
bool shadowunit[32];
|
||||
bool anyshadow = false;
|
||||
memset(shadowunit, 0, sizeof(shadowunit));
|
||||
vector_string lines;
|
||||
tokenize(cgGetProgramString(_cg_program[SHADER_type_frag],
|
||||
CG_COMPILED_PROGRAM), lines, "\n");
|
||||
// figure out which texture units contain shadow maps.
|
||||
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
|
||||
if (lines[lineno].compare(0,21,"#var sampler2DSHADOW ")) {
|
||||
continue;
|
||||
}
|
||||
vector_string fields;
|
||||
tokenize(lines[lineno], fields, ":");
|
||||
if (fields.size()!=5) {
|
||||
continue;
|
||||
}
|
||||
vector_string words;
|
||||
tokenize(trim(fields[2]), words, " ");
|
||||
if (words.size()!=2) {
|
||||
continue;
|
||||
}
|
||||
int unit = atoi(words[1].c_str());
|
||||
if ((unit < 0)||(unit >= 32)) {
|
||||
continue;
|
||||
}
|
||||
anyshadow = true;
|
||||
shadowunit[unit] = true;
|
||||
}
|
||||
// modify all TEX statements that use the relevant texture units.
|
||||
if (anyshadow) {
|
||||
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
|
||||
if (lines[lineno].compare(0,4,"TEX ")) {
|
||||
continue;
|
||||
}
|
||||
vector_string fields;
|
||||
tokenize(lines[lineno], fields, ",");
|
||||
if ((fields.size()!=4)||(trim(fields[3]) != "2D;")) {
|
||||
continue;
|
||||
}
|
||||
vector_string texunitf;
|
||||
tokenize(trim(fields[2]), texunitf, "[]");
|
||||
if ((texunitf.size()!=3)||(texunitf[0] != "texture")||(texunitf[2]!="")) {
|
||||
continue;
|
||||
}
|
||||
int unit = atoi(texunitf[1].c_str());
|
||||
if ((unit < 0) || (unit >= 32) || (shadowunit[unit]==false)) {
|
||||
continue;
|
||||
}
|
||||
lines[lineno] = fields[0]+","+fields[1]+","+fields[2]+", SHADOW2D;";
|
||||
}
|
||||
string result = "!!ARBfp1.0\nOPTION ARB_fragment_program_shadow;\n";
|
||||
for (int lineno=1; lineno<(int)lines.size(); lineno++) {
|
||||
result += (lines[lineno] + "\n");
|
||||
}
|
||||
_cg_program[2] = _cg_program[SHADER_type_frag];
|
||||
_cg_program[SHADER_type_frag] =
|
||||
cgCreateProgram(_cg_context, CG_OBJECT, result.c_str(),
|
||||
_cg_profile[SHADER_type_frag], "fshader", (const char**)NULL);
|
||||
report_cg_compile_errors(s->get_name(), _cg_context);
|
||||
if (_cg_program[SHADER_type_frag]==0) {
|
||||
release_resources();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cgGLLoadProgram(_cg_program[SHADER_type_vert]);
|
||||
report_cg_compile_errors(s->get_name(), _cg_context);
|
||||
cgGLLoadProgram(_cg_program[SHADER_type_frag]);
|
||||
report_cg_compile_errors(s->get_name(), _cg_context);
|
||||
|
||||
_state = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLShaderContext::Destructor
|
||||
// Access: Public
|
||||
|
|
@ -390,15 +78,13 @@ CLP(ShaderContext)::
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
release_resources() {
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context) {
|
||||
cgDestroyContext(_cg_context);
|
||||
_cg_context = (CGcontext)0;
|
||||
_cg_profile[SHADER_type_vert] = (CGprofile)0;
|
||||
_cg_profile[SHADER_type_frag] = (CGprofile)0;
|
||||
_cg_program[SHADER_type_vert] = (CGprogram)0;
|
||||
_cg_program[SHADER_type_frag] = (CGprogram)0;
|
||||
_cg_program[2] = (CGprogram)0;
|
||||
_cg_context = 0;
|
||||
_cg_vprogram = 0;
|
||||
_cg_fprogram = 0;
|
||||
_cg_parameter_map.clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -412,17 +98,17 @@ release_resources() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
bind(GSG *gsg) {
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context != 0) {
|
||||
|
||||
// Pass in k-parameters and transform-parameters
|
||||
issue_parameters(gsg, true);
|
||||
|
||||
// Bind the shaders.
|
||||
cgGLEnableProfile(_cg_profile[SHADER_type_vert]);
|
||||
cgGLBindProgram(_cg_program[SHADER_type_vert]);
|
||||
cgGLEnableProfile(_cg_profile[SHADER_type_frag]);
|
||||
cgGLBindProgram(_cg_program[SHADER_type_frag]);
|
||||
cgGLEnableProfile(cgGetProgramProfile(_cg_vprogram));
|
||||
cgGLBindProgram(_cg_vprogram);
|
||||
cgGLEnableProfile(cgGetProgramProfile(_cg_fprogram));
|
||||
cgGLBindProgram(_cg_fprogram);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -434,10 +120,10 @@ bind(GSG *gsg) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
unbind() {
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context != 0) {
|
||||
cgGLDisableProfile(_cg_profile[SHADER_type_vert]);
|
||||
cgGLDisableProfile(_cg_profile[SHADER_type_frag]);
|
||||
cgGLDisableProfile(cgGetProgramProfile(_cg_vprogram));
|
||||
cgGLDisableProfile(cgGetProgramProfile(_cg_fprogram));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -459,28 +145,28 @@ unbind() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
issue_parameters(GSG *gsg, bool altered) {
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i<(int)_mat_spec.size(); i++) {
|
||||
if (altered || _mat_spec[i]._trans_dependent) {
|
||||
CGparameter p = (CGparameter)(_mat_spec[i]._parameter);
|
||||
const LMatrix4f *val = gsg->fetch_specified_value(_mat_spec[i], altered);
|
||||
for (int i=0; i<(int)_expansion->_mat_spec.size(); i++) {
|
||||
if (altered || _expansion->_mat_spec[i]._trans_dependent) {
|
||||
CGparameter p = _cg_parameter_map[_expansion->_mat_spec[i]._id._seqno];
|
||||
const LMatrix4f *val = gsg->fetch_specified_value(_expansion->_mat_spec[i], altered);
|
||||
if (val) {
|
||||
const float *data = val->get_data();
|
||||
switch (_mat_spec[i]._piece) {
|
||||
case SMP_whole: cgGLSetMatrixParameterfc(p, data); break;
|
||||
case SMP_transpose: cgGLSetMatrixParameterfr(p, data); break;
|
||||
case SMP_row0: cgGLSetParameter4fv(p, data+ 0); break;
|
||||
case SMP_row1: cgGLSetParameter4fv(p, data+ 4); break;
|
||||
case SMP_row2: cgGLSetParameter4fv(p, data+ 8); break;
|
||||
case SMP_row3: cgGLSetParameter4fv(p, data+12); break;
|
||||
case SMP_col0: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); break;
|
||||
case SMP_col1: cgGLSetParameter4f(p, data[1], data[5], data[ 9], data[13]); break;
|
||||
case SMP_col2: cgGLSetParameter4f(p, data[2], data[6], data[10], data[14]); break;
|
||||
case SMP_col3: cgGLSetParameter4f(p, data[3], data[7], data[11], data[15]); break;
|
||||
switch (_expansion->_mat_spec[i]._piece) {
|
||||
case ShaderExpansion::SMP_whole: cgGLSetMatrixParameterfc(p, data); break;
|
||||
case ShaderExpansion::SMP_transpose: cgGLSetMatrixParameterfr(p, data); break;
|
||||
case ShaderExpansion::SMP_row0: cgGLSetParameter4fv(p, data+ 0); break;
|
||||
case ShaderExpansion::SMP_row1: cgGLSetParameter4fv(p, data+ 4); break;
|
||||
case ShaderExpansion::SMP_row2: cgGLSetParameter4fv(p, data+ 8); break;
|
||||
case ShaderExpansion::SMP_row3: cgGLSetParameter4fv(p, data+12); break;
|
||||
case ShaderExpansion::SMP_col0: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); break;
|
||||
case ShaderExpansion::SMP_col1: cgGLSetParameter4f(p, data[1], data[5], data[ 9], data[13]); break;
|
||||
case ShaderExpansion::SMP_col2: cgGLSetParameter4f(p, data[2], data[6], data[10], data[14]); break;
|
||||
case ShaderExpansion::SMP_col3: cgGLSetParameter4f(p, data[3], data[7], data[11], data[15]); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -495,13 +181,13 @@ issue_parameters(GSG *gsg, bool altered) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
disable_shader_vertex_arrays(GSG *gsg) {
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i<(int)_var_spec.size(); i++) {
|
||||
CGparameter p = (CGparameter)(_var_spec[i]._parameter);
|
||||
for (int i=0; i<(int)_expansion->_var_spec.size(); i++) {
|
||||
CGparameter p = _cg_parameter_map[_expansion->_var_spec[i]._id._seqno];
|
||||
cgGLDisableClientState(p);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -521,7 +207,7 @@ disable_shader_vertex_arrays(GSG *gsg) {
|
|||
void CLP(ShaderContext)::
|
||||
update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
|
||||
if (prev) prev->disable_shader_vertex_arrays(gsg);
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context == 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -535,11 +221,11 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
|
|||
const GeomVertexArrayDataPipelineReader *array_reader;
|
||||
Geom::NumericType numeric_type;
|
||||
int start, stride, num_values;
|
||||
int nvarying = _var_spec.size();
|
||||
int nvarying = _expansion->_var_spec.size();
|
||||
for (int i=0; i<nvarying; i++) {
|
||||
CGparameter p = (CGparameter)(_var_spec[i]._parameter);
|
||||
InternalName *name = _var_spec[i]._name;
|
||||
int texslot = _var_spec[i]._append_uv;
|
||||
CGparameter p = _cg_parameter_map[_expansion->_var_spec[i]._id._seqno];
|
||||
InternalName *name = _expansion->_var_spec[i]._name;
|
||||
int texslot = _expansion->_var_spec[i]._append_uv;
|
||||
if (texslot >= 0) {
|
||||
const Geom::ActiveTextureStages &active_stages =
|
||||
gsg->_state._texture->get_on_stages();
|
||||
|
|
@ -566,7 +252,7 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // HAVE_CGGL
|
||||
#endif // HAVE_CG
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -576,13 +262,13 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
disable_shader_texture_bindings(GSG *gsg) {
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i<(int)_tex_spec.size(); i++) {
|
||||
CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
|
||||
for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
|
||||
CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
|
||||
int texunit = cgGetParameterResourceIndex(p);
|
||||
gsg->_glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
GLP(Disable)(GL_TEXTURE_1D);
|
||||
|
|
@ -613,33 +299,33 @@ disable_shader_texture_bindings(GSG *gsg) {
|
|||
void CLP(ShaderContext)::
|
||||
update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) {
|
||||
if (prev) prev->disable_shader_texture_bindings(gsg);
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i<(int)_tex_spec.size(); i++) {
|
||||
CGparameter p = (CGparameter)(_tex_spec[i]._parameter);
|
||||
for (int i=0; i<(int)_expansion->_tex_spec.size(); i++) {
|
||||
CGparameter p = _cg_parameter_map[_expansion->_tex_spec[i]._id._seqno];
|
||||
Texture *tex = 0;
|
||||
InternalName *id = _tex_spec[i]._name;
|
||||
InternalName *id = _expansion->_tex_spec[i]._name;
|
||||
if (id != 0) {
|
||||
const ShaderInput *input = gsg->_target._shader->get_shader_input(id);
|
||||
tex = input->get_texture();
|
||||
} else {
|
||||
if (_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
|
||||
if (_expansion->_tex_spec[i]._stage >= gsg->_target._texture->get_num_on_stages()) {
|
||||
continue;
|
||||
}
|
||||
TextureStage *stage = gsg->_target._texture->get_on_stage(_tex_spec[i]._stage);
|
||||
TextureStage *stage = gsg->_target._texture->get_on_stage(_expansion->_tex_spec[i]._stage);
|
||||
tex = gsg->_target._texture->get_on_texture(stage);
|
||||
}
|
||||
if (_tex_spec[i]._suffix != 0) {
|
||||
if (_expansion->_tex_spec[i]._suffix != 0) {
|
||||
// The suffix feature is inefficient. It is a temporary hack.
|
||||
if (tex == 0) {
|
||||
continue;
|
||||
}
|
||||
tex = tex->load_related(_tex_spec[i]._suffix);
|
||||
tex = tex->load_related(_expansion->_tex_spec[i]._suffix);
|
||||
}
|
||||
if ((tex == 0) || (tex->get_texture_type() != _tex_spec[i]._desired_type)) {
|
||||
if ((tex == 0) || (tex->get_texture_type() != _expansion->_tex_spec[i]._desired_type)) {
|
||||
continue;
|
||||
}
|
||||
TextureContext *tc = tex->prepare_now(gsg->_prepared_objects, gsg);
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_CGGL
|
||||
#include "Cg/cgGL.h"
|
||||
#endif
|
||||
#include "string_utils.h"
|
||||
#include "internalName.h"
|
||||
#include "shaderExpansion.h"
|
||||
|
|
@ -49,23 +46,18 @@ public:
|
|||
void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg);
|
||||
void disable_shader_texture_bindings(GSG *gsg);
|
||||
void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
|
||||
bool _state;
|
||||
|
||||
private:
|
||||
|
||||
#ifdef HAVE_CGGL
|
||||
#ifdef HAVE_CG
|
||||
CGcontext _cg_context;
|
||||
CGprofile _cg_profile[2];
|
||||
CGprogram _cg_program[3];
|
||||
|
||||
void report_cg_compile_errors(const string &file, CGcontext ctx);
|
||||
bool try_cg_compile(ShaderExpansion *s, GSG *gsg);
|
||||
void suggest_cg_profile(const string &vpro, const string &fpro);
|
||||
CGprofile parse_cg_profile(const string &id, bool vertex);
|
||||
CGprogram _cg_vprogram;
|
||||
CGprogram _cg_fprogram;
|
||||
pvector <CGparameter> _cg_parameter_map;
|
||||
#endif
|
||||
|
||||
void release_resources(void);
|
||||
|
||||
void release_resources(void);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m prc:c
|
||||
//#define OSX_SYS_LIBS mx
|
||||
#define USE_PACKAGES zlib
|
||||
#define USE_PACKAGES zlib cg
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET gobj
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ PreparedGraphicsObjects::
|
|||
sci != _prepared_shaders.end();
|
||||
++sci) {
|
||||
ShaderContext *sc = (*sci);
|
||||
sc->_shader_expansion->clear_prepared(this);
|
||||
sc->_expansion->clear_prepared(this);
|
||||
}
|
||||
|
||||
_prepared_shaders.clear();
|
||||
|
|
@ -460,12 +460,12 @@ void PreparedGraphicsObjects::
|
|||
release_shader(ShaderContext *sc) {
|
||||
ReMutexHolder holder(_lock);
|
||||
|
||||
sc->_shader_expansion->clear_prepared(this);
|
||||
sc->_expansion->clear_prepared(this);
|
||||
|
||||
// We have to set the Shader pointer to NULL at this point, since
|
||||
// the Shader itself might destruct at any time after it has been
|
||||
// released.
|
||||
sc->_shader_expansion = (ShaderExpansion *)NULL;
|
||||
sc->_expansion = (ShaderExpansion *)NULL;
|
||||
|
||||
bool removed = (_prepared_shaders.erase(sc) != 0);
|
||||
nassertv(removed);
|
||||
|
|
@ -492,8 +492,8 @@ release_all_shaders() {
|
|||
sci != _prepared_shaders.end();
|
||||
++sci) {
|
||||
ShaderContext *sc = (*sci);
|
||||
sc->_shader_expansion->clear_prepared(this);
|
||||
sc->_shader_expansion = (ShaderExpansion *)NULL;
|
||||
sc->_expansion->clear_prepared(this);
|
||||
sc->_expansion = (ShaderExpansion *)NULL;
|
||||
|
||||
_released_shaders.insert(sc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ShaderContext::
|
||||
ShaderContext(ShaderExpansion *se) :
|
||||
_shader_expansion(se)
|
||||
_expansion(se)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,678 +22,3 @@
|
|||
|
||||
TypeHandle ShaderContext::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::cp_report_error
|
||||
// Access: Public
|
||||
// Description: Generate an error message including a description
|
||||
// of the specified parameter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ShaderContext::
|
||||
cp_report_error(ShaderArgInfo &p, const string &msg)
|
||||
{
|
||||
string vstr;
|
||||
if (p._varying) vstr = "varying ";
|
||||
else vstr = "uniform ";
|
||||
|
||||
string dstr = "unknown ";
|
||||
if (p._direction == SAD_in) dstr = "in ";
|
||||
if (p._direction == SAD_out) dstr = "out ";
|
||||
if (p._direction == SAD_inout) dstr = "inout ";
|
||||
|
||||
string tstr = "invalid ";
|
||||
switch (p._type) {
|
||||
case SAT_float1: tstr = "float1 "; break;
|
||||
case SAT_float2: tstr = "float2 "; break;
|
||||
case SAT_float3: tstr = "float3 "; break;
|
||||
case SAT_float4: tstr = "float4 "; break;
|
||||
case SAT_float4x4: tstr = "float4x4 "; break;
|
||||
case SAT_sampler1d: tstr = "sampler1d "; break;
|
||||
case SAT_sampler2d: tstr = "sampler2d "; break;
|
||||
case SAT_sampler3d: tstr = "sampler3d "; break;
|
||||
case SAT_samplercube: tstr = "samplercube "; break;
|
||||
case SAT_unknown: tstr = "unknown "; break;
|
||||
}
|
||||
|
||||
string fn = _shader_expansion->get_name();
|
||||
p._cat->error() << fn << ": " << msg << " (" <<
|
||||
vstr << dstr << tstr << p._name << ")\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::cp_errchk_parameter_words
|
||||
// Access: Public, Static
|
||||
// Description: Make sure the provided parameter contains
|
||||
// the specified number of words. If not, print
|
||||
// error message and return false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ShaderContext::
|
||||
cp_errchk_parameter_words(ShaderArgInfo &p, int len)
|
||||
{
|
||||
vector_string words;
|
||||
tokenize(p._name, words, "_");
|
||||
if ((int)words.size() != len) {
|
||||
cp_report_error(p, "parameter name has wrong number of words");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::cp_errchk_parameter_in
|
||||
// Access: Public, Static
|
||||
// Description: Make sure the provided parameter has the
|
||||
// 'in' direction. If not, print
|
||||
// error message and return false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ShaderContext::
|
||||
cp_errchk_parameter_in(ShaderArgInfo &p)
|
||||
{
|
||||
if (p._direction != SAD_in) {
|
||||
cp_report_error(p, "parameter should be declared 'in'");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::cp_errchk_parameter_varying
|
||||
// Access: Public, Static
|
||||
// Description: Make sure the provided parameter has the
|
||||
// correct variance. If not, print
|
||||
// error message and return false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ShaderContext::
|
||||
cp_errchk_parameter_varying(ShaderArgInfo &p)
|
||||
{
|
||||
if (!p._varying) {
|
||||
cp_report_error(p, "parameter should be declared 'varying'");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::cp_errchk_parameter_uniform
|
||||
// Access: Public, Static
|
||||
// Description: Make sure the provided parameter has the
|
||||
// correct variance. If not, print
|
||||
// error message and return false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ShaderContext::
|
||||
cp_errchk_parameter_uniform(ShaderArgInfo &p)
|
||||
{
|
||||
if (p._varying) {
|
||||
cp_report_error(p, "parameter should be declared 'uniform'");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::cp_errchk_parameter_float
|
||||
// Access: Public, Static
|
||||
// Description: Make sure the provided parameter has
|
||||
// a floating point type. If not, print
|
||||
// error message and return false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ShaderContext::
|
||||
cp_errchk_parameter_float(ShaderArgInfo &p, int lo, int hi)
|
||||
{
|
||||
int nfloat;
|
||||
switch (p._type) {
|
||||
case SAT_float1: nfloat = 1; break;
|
||||
case SAT_float2: nfloat = 2; break;
|
||||
case SAT_float3: nfloat = 3; break;
|
||||
case SAT_float4: nfloat = 4; break;
|
||||
case SAT_float4x4: nfloat = 16; break;
|
||||
default: nfloat = 0; break;
|
||||
}
|
||||
if ((nfloat < lo)||(nfloat > hi)) {
|
||||
string msg = "wrong type for parameter: should be float";
|
||||
cp_report_error(p, msg);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::cp_errchk_parameter_sampler
|
||||
// Access: Public, Static
|
||||
// Description: Make sure the provided parameter has
|
||||
// a texture type. If not, print
|
||||
// error message and return false.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ShaderContext::
|
||||
cp_errchk_parameter_sampler(ShaderArgInfo &p)
|
||||
{
|
||||
if ((p._type!=SAT_sampler1d)&&
|
||||
(p._type!=SAT_sampler2d)&&
|
||||
(p._type!=SAT_sampler3d)&&
|
||||
(p._type!=SAT_samplercube)) {
|
||||
cp_report_error(p, "parameter should have a 'sampler' type");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderContext::cp_parse_trans_clause
|
||||
// Access: Public
|
||||
// Description: Parses a single clause of a "trans" parameter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ShaderContext::
|
||||
cp_parse_trans_clause(ShaderArgInfo &p, ShaderMatSpec &spec,
|
||||
int part, const vector_string &pieces,
|
||||
int &next, ShaderMatInput ofop, ShaderMatInput op) {
|
||||
if (pieces[next+1]=="of") {
|
||||
if (pieces[next+2]=="") {
|
||||
cp_report_error(p, "'of' should be followed by a name");
|
||||
return false;
|
||||
}
|
||||
spec._part[part] = ofop;
|
||||
spec._arg[part] = InternalName::make(pieces[next+2]);
|
||||
next += 3;
|
||||
return true;
|
||||
} else {
|
||||
spec._part[part] = op;
|
||||
spec._arg[part] = NULL;
|
||||
next += 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderContext::cp_optimize_mat_spec
|
||||
// Access: Public
|
||||
// Description: Analyzes a ShaderMatSpec and decides what it should
|
||||
// use its cache for. It can cache the results of any
|
||||
// one opcode, or, it can cache the entire result. This
|
||||
// routine needs to be smart enough to know which
|
||||
// data items can be correctly cached, and which cannot.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ShaderContext::
|
||||
cp_optimize_mat_spec(ShaderMatSpec &spec) {
|
||||
|
||||
// If we're composing with identity, simplify.
|
||||
if (spec._func == SMF_compose) {
|
||||
if (spec._part[1] == SMO_identity) {
|
||||
spec._func = SMF_first;
|
||||
}
|
||||
}
|
||||
if (spec._func == SMF_compose) {
|
||||
if (spec._part[0] == SMO_identity) {
|
||||
spec._func = SMF_first;
|
||||
spec._part[0] = spec._part[1];
|
||||
spec._arg[0] = spec._arg[1];
|
||||
}
|
||||
}
|
||||
|
||||
// See if either half can be cached.
|
||||
bool can_cache_part0 = true;
|
||||
bool can_cache_part1 = true;
|
||||
if ((spec._part[0] == SMO_model_to_view)||
|
||||
(spec._part[0] == SMO_view_to_model)) {
|
||||
can_cache_part0 = false;
|
||||
}
|
||||
if ((spec._part[1] == SMO_model_to_view)||
|
||||
(spec._part[1] == SMO_view_to_model)) {
|
||||
can_cache_part1 = false;
|
||||
}
|
||||
|
||||
// See if we can use a compose-with-cache variant.
|
||||
if (spec._func == SMF_compose) {
|
||||
if (can_cache_part0) {
|
||||
spec._func = SMF_compose_cache_first;
|
||||
} else if (can_cache_part1) {
|
||||
spec._func = SMF_compose_cache_second;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine transform-dependence.
|
||||
if (can_cache_part0 && can_cache_part1) {
|
||||
spec._trans_dependent = false;
|
||||
} else {
|
||||
spec._trans_dependent = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderContext::compile_parameter
|
||||
// Access: Public
|
||||
// Description: Analyzes a parameter and decides how to
|
||||
// bind the parameter to some part of panda's
|
||||
// internal state. Updates one of the bind
|
||||
// arrays to cause the binding to occur.
|
||||
//
|
||||
// If there is an error, this routine will append
|
||||
// an error message onto the error messages.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ShaderContext::
|
||||
compile_parameter(void *reference,
|
||||
const string &arg_name,
|
||||
ShaderArgType arg_type,
|
||||
ShaderArgDir arg_direction,
|
||||
bool arg_varying,
|
||||
NotifyCategory *arg_cat)
|
||||
{
|
||||
ShaderArgInfo p;
|
||||
p._name = arg_name;
|
||||
p._type = arg_type;
|
||||
p._direction = arg_direction;
|
||||
p._varying = arg_varying;
|
||||
p._cat = arg_cat;
|
||||
|
||||
if (p._name.size() == 0) return true;
|
||||
if (p._name[0] == '$') return true;
|
||||
vector_string pieces;
|
||||
tokenize(p._name, pieces, "_");
|
||||
|
||||
if (pieces.size() < 2) {
|
||||
cp_report_error(p, "invalid parameter name");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implement vtx parameters - the varying kind.
|
||||
|
||||
if (pieces[0] == "vtx") {
|
||||
if ((!cp_errchk_parameter_in(p)) ||
|
||||
(!cp_errchk_parameter_varying(p)) ||
|
||||
(!cp_errchk_parameter_float(p, 1, 4))) {
|
||||
return false;
|
||||
}
|
||||
ShaderVarSpec bind;
|
||||
bind._parameter = reference;
|
||||
if (pieces.size() == 2) {
|
||||
if (pieces[1]=="position") {
|
||||
bind._name = InternalName::get_vertex();
|
||||
bind._append_uv = -1;
|
||||
_var_spec.push_back(bind);
|
||||
return true;
|
||||
}
|
||||
if (pieces[1].substr(0,8)=="texcoord") {
|
||||
bind._name = InternalName::get_texcoord();
|
||||
bind._append_uv = atoi(pieces[1].c_str()+8);
|
||||
_var_spec.push_back(bind);
|
||||
return true;
|
||||
}
|
||||
if (pieces[1].substr(0,7)=="tangent") {
|
||||
bind._name = InternalName::get_tangent();
|
||||
bind._append_uv = atoi(pieces[1].c_str()+7);
|
||||
_var_spec.push_back(bind);
|
||||
return true;
|
||||
}
|
||||
if (pieces[1].substr(0,8)=="binormal") {
|
||||
bind._name = InternalName::get_binormal();
|
||||
bind._append_uv = atoi(pieces[1].c_str()+8);
|
||||
_var_spec.push_back(bind);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bind._name = InternalName::get_root();
|
||||
bind._append_uv = -1;
|
||||
for (int i=1; i<(int)(pieces.size()-0); i++)
|
||||
bind._name = bind._name->append(pieces[i]);
|
||||
_var_spec.push_back(bind);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Implement some macros. Macros work by altering the
|
||||
// contents of the 'pieces' array, and then falling through.
|
||||
|
||||
if (pieces[0] == "mstrans") {
|
||||
pieces[0] = "trans";
|
||||
pieces.push_back("to");
|
||||
pieces.push_back("model");
|
||||
}
|
||||
if (pieces[0] == "wstrans") {
|
||||
pieces[0] = "trans";
|
||||
pieces.push_back("to");
|
||||
pieces.push_back("world");
|
||||
}
|
||||
if (pieces[0] == "vstrans") {
|
||||
pieces[0] = "trans";
|
||||
pieces.push_back("to");
|
||||
pieces.push_back("view");
|
||||
}
|
||||
if (pieces[0] == "cstrans") {
|
||||
pieces[0] = "trans";
|
||||
pieces.push_back("to");
|
||||
pieces.push_back("clip");
|
||||
}
|
||||
if (pieces[0] == "mspos") {
|
||||
pieces[0] = "row3";
|
||||
pieces.push_back("to");
|
||||
pieces.push_back("model");
|
||||
}
|
||||
if (pieces[0] == "wspos") {
|
||||
pieces[0] = "row3";
|
||||
pieces.push_back("to");
|
||||
pieces.push_back("world");
|
||||
}
|
||||
if (pieces[0] == "vspos") {
|
||||
pieces[0] = "row3";
|
||||
pieces.push_back("to");
|
||||
pieces.push_back("view");
|
||||
}
|
||||
if (pieces[0] == "cspos") {
|
||||
pieces[0] = "row3";
|
||||
pieces.push_back("to");
|
||||
pieces.push_back("clip");
|
||||
}
|
||||
|
||||
// Implement the modelview macros.
|
||||
|
||||
if ((pieces[0] == "mat")||(pieces[0] == "inv")||
|
||||
(pieces[0] == "tps")||(pieces[0] == "itp")) {
|
||||
if (!cp_errchk_parameter_words(p, 2)) {
|
||||
return false;
|
||||
}
|
||||
string trans = pieces[0];
|
||||
string matrix = pieces[1];
|
||||
pieces.clear();
|
||||
if (matrix == "modelview") {
|
||||
tokenize("trans_model_to_apiview", pieces, "_");
|
||||
} else if (matrix == "projection") {
|
||||
tokenize("trans_apiview_to_apiclip", pieces, "_");
|
||||
} else if (matrix == "modelproj") {
|
||||
tokenize("trans_model_to_apiclip", pieces, "_");
|
||||
} else {
|
||||
cp_report_error(p,"unrecognized matrix name");
|
||||
return false;
|
||||
}
|
||||
if (trans=="mat") {
|
||||
pieces[0] = "trans";
|
||||
} else if (trans=="inv") {
|
||||
string t = pieces[1];
|
||||
pieces[1] = pieces[3];
|
||||
pieces[3] = t;
|
||||
} else if (trans=="tps") {
|
||||
pieces[0] = "tpose";
|
||||
} else if (trans=="itp") {
|
||||
string t = pieces[1];
|
||||
pieces[1] = pieces[3];
|
||||
pieces[3] = t;
|
||||
pieces[0] = "tpose";
|
||||
}
|
||||
}
|
||||
|
||||
// Implement the transform-matrix generator.
|
||||
|
||||
if ((pieces[0]=="trans")||
|
||||
(pieces[0]=="tpose")||
|
||||
(pieces[0]=="row0")||
|
||||
(pieces[0]=="row1")||
|
||||
(pieces[0]=="row2")||
|
||||
(pieces[0]=="row3")||
|
||||
(pieces[0]=="col0")||
|
||||
(pieces[0]=="col1")||
|
||||
(pieces[0]=="col2")||
|
||||
(pieces[0]=="col3")) {
|
||||
|
||||
if ((!cp_errchk_parameter_in(p)) ||
|
||||
(!cp_errchk_parameter_uniform(p)))
|
||||
return false;
|
||||
|
||||
ShaderMatSpec bind;
|
||||
bind._parameter = reference;
|
||||
bind._func = SMF_compose;
|
||||
|
||||
int next = 1;
|
||||
pieces.push_back("");
|
||||
|
||||
// Decide whether this is a matrix or vector.
|
||||
if (pieces[0]=="trans") bind._piece = SMP_whole;
|
||||
else if (pieces[0]=="tpose") bind._piece = SMP_transpose;
|
||||
else if (pieces[0]=="row0") bind._piece = SMP_row0;
|
||||
else if (pieces[0]=="row1") bind._piece = SMP_row1;
|
||||
else if (pieces[0]=="row2") bind._piece = SMP_row2;
|
||||
else if (pieces[0]=="row3") bind._piece = SMP_row3;
|
||||
else if (pieces[0]=="col0") bind._piece = SMP_col0;
|
||||
else if (pieces[0]=="col1") bind._piece = SMP_col1;
|
||||
else if (pieces[0]=="col2") bind._piece = SMP_col2;
|
||||
else if (pieces[0]=="col3") bind._piece = SMP_col3;
|
||||
if ((bind._piece == SMP_whole)||(bind._piece == SMP_transpose)) {
|
||||
if (!cp_errchk_parameter_float(p, 16, 16)) return false;
|
||||
} else {
|
||||
if (!cp_errchk_parameter_float(p, 4, 4)) return false;
|
||||
}
|
||||
|
||||
// Parse the first half of the clause.
|
||||
bool ok = true;
|
||||
if ((pieces[next]=="")||(pieces[next]=="of")||(pieces[next]=="to")){
|
||||
cp_report_error(p, "argument missing");
|
||||
return false;
|
||||
} else if (pieces[next] == "world") {
|
||||
bind._part[0] = SMO_world_to_view;
|
||||
bind._arg[0] = NULL;
|
||||
next += 1;
|
||||
} else if (pieces[next] == "model") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_view_x_to_view, SMO_model_to_view);
|
||||
} else if (pieces[next] == "clip") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_clip_x_to_view, SMO_clip_to_view);
|
||||
} else if (pieces[next] == "view") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_view_x_to_view, SMO_identity);
|
||||
} else if (pieces[next] == "apiview") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_apiview_x_to_view, SMO_apiview_to_view);
|
||||
} else if (pieces[next] == "apiclip") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_apiclip_x_to_view, SMO_apiclip_to_view);
|
||||
} else {
|
||||
bind._part[0] = SMO_view_x_to_view;
|
||||
bind._arg[0] = InternalName::make(pieces[next]);
|
||||
next += 1;
|
||||
}
|
||||
|
||||
// Check for errors in the first clause.
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for syntactic well-formed-ness.
|
||||
if (pieces[next] != "to") {
|
||||
cp_report_error(p, "keyword 'to' expected");
|
||||
return false;
|
||||
} else {
|
||||
next += 1;
|
||||
}
|
||||
|
||||
// Parse the second half of the clause.
|
||||
if ((pieces[next]=="")||(pieces[next]=="of")||(pieces[next]=="to")){
|
||||
cp_report_error(p, "argument missing");
|
||||
return false;
|
||||
} else if (pieces[next] == "world") {
|
||||
bind._part[1] = SMO_view_to_world;
|
||||
bind._arg[1] = NULL;
|
||||
next += 1;
|
||||
} else if (pieces[next] == "model") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_view_x, SMO_view_to_model);
|
||||
} else if (pieces[next] == "clip") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_clip_x, SMO_view_to_clip);
|
||||
} else if (pieces[next] == "view") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_view_x, SMO_identity);
|
||||
} else if (pieces[next] == "apiview") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_apiview_x, SMO_view_to_apiview);
|
||||
} else if (pieces[next] == "apiclip") {
|
||||
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_apiclip_x, SMO_view_to_apiclip);
|
||||
} else {
|
||||
bind._part[1] = SMO_view_to_view_x;
|
||||
bind._arg[1] = InternalName::make(pieces[next]);
|
||||
next += 1;
|
||||
}
|
||||
|
||||
// Check for errors in the second clause.
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for syntactic well-formed-ness.
|
||||
if (pieces[next] != "") {
|
||||
cp_report_error(p, "end of line expected");
|
||||
return false;
|
||||
}
|
||||
|
||||
cp_optimize_mat_spec(bind);
|
||||
_mat_spec.push_back(bind);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Keywords to access unusual parameters.
|
||||
|
||||
if (pieces[0] == "sys") {
|
||||
if ((!cp_errchk_parameter_words(p,2)) ||
|
||||
(!cp_errchk_parameter_in(p)) ||
|
||||
(!cp_errchk_parameter_uniform(p))) {
|
||||
return false;
|
||||
}
|
||||
ShaderMatSpec bind;
|
||||
bind._parameter = reference;
|
||||
bind._piece = SMP_row3;
|
||||
bind._func = SMF_first;
|
||||
bind._part[1] = SMO_identity;
|
||||
bind._arg[1] = NULL;
|
||||
if (pieces[1] == "pixelsize") {
|
||||
if (!cp_errchk_parameter_float(p, 2, 2)) {
|
||||
return false;
|
||||
}
|
||||
bind._part[0] = SMO_pixel_size;
|
||||
bind._arg[0] = NULL;
|
||||
} else if (pieces[1] == "windowsize") {
|
||||
if (!cp_errchk_parameter_float(p, 2, 2)) {
|
||||
return false;
|
||||
}
|
||||
bind._part[0] = SMO_window_size;
|
||||
bind._arg[0] = NULL;
|
||||
} else if (pieces[1] == "cardcenter") {
|
||||
if (!cp_errchk_parameter_float(p, 2, 2)) {
|
||||
return false;
|
||||
}
|
||||
bind._part[0] = SMO_card_center;
|
||||
bind._arg[0] = NULL;
|
||||
} else {
|
||||
cp_report_error(p,"unknown system parameter");
|
||||
return false;
|
||||
}
|
||||
|
||||
cp_optimize_mat_spec(bind);
|
||||
_mat_spec.push_back(bind);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Keywords to access textures.
|
||||
|
||||
if (pieces[0] == "tex") {
|
||||
if ((!cp_errchk_parameter_in(p)) ||
|
||||
(!cp_errchk_parameter_uniform(p)) ||
|
||||
(!cp_errchk_parameter_sampler(p)))
|
||||
return false;
|
||||
if ((pieces.size() != 2)&&(pieces.size() != 3)) {
|
||||
cp_report_error(p, "Invalid parameter name");
|
||||
return false;
|
||||
}
|
||||
ShaderTexSpec bind;
|
||||
bind._parameter = reference;
|
||||
bind._name = 0;
|
||||
bind._stage = atoi(pieces[1].c_str());
|
||||
switch (p._type) {
|
||||
case SAT_sampler1d: bind._desired_type = Texture::TT_1d_texture; break;
|
||||
case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture; break;
|
||||
case SAT_sampler3d: bind._desired_type = Texture::TT_3d_texture; break;
|
||||
case SAT_samplercube: bind._desired_type = Texture::TT_cube_map; break;
|
||||
default:
|
||||
cp_report_error(p, "Invalid type for a tex-parameter");
|
||||
return false;
|
||||
}
|
||||
if (pieces.size()==3) {
|
||||
bind._suffix = InternalName::make(((string)"-") + pieces[2]);
|
||||
}
|
||||
_tex_spec.push_back(bind);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Keywords to access constants.
|
||||
|
||||
if (pieces[0] == "k") {
|
||||
if ((!cp_errchk_parameter_words(p,2)) ||
|
||||
(!cp_errchk_parameter_in(p)) ||
|
||||
(!cp_errchk_parameter_uniform(p)))
|
||||
return false;
|
||||
switch (p._type) {
|
||||
case SAT_float4: {
|
||||
ShaderMatSpec bind;
|
||||
bind._parameter = reference;
|
||||
bind._piece = SMP_row3;
|
||||
bind._func = SMF_first;
|
||||
bind._part[0] = SMO_vec_constant_x;
|
||||
bind._arg[0] = InternalName::make(pieces[1]);
|
||||
bind._part[1] = SMO_identity;
|
||||
bind._arg[1] = NULL;
|
||||
cp_optimize_mat_spec(bind);
|
||||
_mat_spec.push_back(bind);
|
||||
break;
|
||||
}
|
||||
case SAT_float4x4: {
|
||||
ShaderMatSpec bind;
|
||||
bind._parameter = reference;
|
||||
bind._piece = SMP_whole;
|
||||
bind._func = SMF_first;
|
||||
bind._part[0] = SMO_vec_constant_x;
|
||||
bind._arg[0] = InternalName::make(pieces[1]);
|
||||
bind._part[1] = SMO_identity;
|
||||
bind._arg[1] = NULL;
|
||||
cp_optimize_mat_spec(bind);
|
||||
_mat_spec.push_back(bind);
|
||||
break;
|
||||
}
|
||||
case SAT_sampler1d: {
|
||||
ShaderTexSpec bind;
|
||||
bind._parameter = reference;
|
||||
bind._name = InternalName::make(pieces[1]);
|
||||
bind._desired_type=Texture::TT_1d_texture;
|
||||
_tex_spec.push_back(bind);
|
||||
break;
|
||||
}
|
||||
case SAT_sampler2d: {
|
||||
ShaderTexSpec bind;
|
||||
bind._parameter = reference;
|
||||
bind._name = InternalName::make(pieces[1]);
|
||||
bind._desired_type=Texture::TT_2d_texture;
|
||||
_tex_spec.push_back(bind);
|
||||
break;
|
||||
}
|
||||
case SAT_sampler3d: {
|
||||
ShaderTexSpec bind;
|
||||
bind._parameter = reference;
|
||||
bind._name = InternalName::make(pieces[1]);
|
||||
bind._desired_type=Texture::TT_3d_texture;
|
||||
_tex_spec.push_back(bind);
|
||||
break;
|
||||
}
|
||||
case SAT_samplercube: {
|
||||
ShaderTexSpec bind;
|
||||
bind._parameter = reference;
|
||||
bind._name = InternalName::make(pieces[1]);
|
||||
bind._desired_type = Texture::TT_cube_map;
|
||||
_tex_spec.push_back(bind);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cp_report_error(p, "Invalid type for a k-parameter");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pieces[0] == "l") {
|
||||
// IMPLEMENT THE ERROR CHECKING
|
||||
return true; // Cg handles this automatically.
|
||||
}
|
||||
|
||||
if (pieces[0] == "o") {
|
||||
// IMPLEMENT THE ERROR CHECKING
|
||||
return true; // Cg handles this automatically.
|
||||
}
|
||||
|
||||
cp_report_error(p, "unrecognized parameter name");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,156 +40,7 @@ class EXPCL_PANDA ShaderContext: public SavedContext {
|
|||
public:
|
||||
INLINE ShaderContext(ShaderExpansion *se);
|
||||
|
||||
ShaderExpansion *_shader_expansion;
|
||||
|
||||
public:
|
||||
enum {
|
||||
SHADER_type_vert=0,
|
||||
SHADER_type_frag=1,
|
||||
SHADER_type_both=2,
|
||||
};
|
||||
|
||||
enum ShaderMatInput {
|
||||
SMO_identity,
|
||||
|
||||
SMO_window_size,
|
||||
SMO_pixel_size,
|
||||
SMO_card_center,
|
||||
|
||||
SMO_mat_constant_x,
|
||||
SMO_vec_constant_x,
|
||||
|
||||
SMO_world_to_view,
|
||||
SMO_view_to_world,
|
||||
|
||||
SMO_model_to_view,
|
||||
SMO_view_to_model,
|
||||
|
||||
SMO_apiview_to_view,
|
||||
SMO_view_to_apiview,
|
||||
|
||||
SMO_clip_to_view,
|
||||
SMO_view_to_clip,
|
||||
|
||||
SMO_apiclip_to_view,
|
||||
SMO_view_to_apiclip,
|
||||
|
||||
SMO_view_x_to_view,
|
||||
SMO_view_to_view_x,
|
||||
|
||||
SMO_apiview_x_to_view,
|
||||
SMO_view_to_apiview_x,
|
||||
|
||||
SMO_clip_x_to_view,
|
||||
SMO_view_to_clip_x,
|
||||
|
||||
SMO_apiclip_x_to_view,
|
||||
SMO_view_to_apiclip_x,
|
||||
};
|
||||
|
||||
enum ShaderArgType {
|
||||
SAT_float1,
|
||||
SAT_float2,
|
||||
SAT_float3,
|
||||
SAT_float4,
|
||||
SAT_float4x4,
|
||||
SAT_sampler1d,
|
||||
SAT_sampler2d,
|
||||
SAT_sampler3d,
|
||||
SAT_samplercube,
|
||||
SAT_unknown,
|
||||
};
|
||||
|
||||
enum ShaderArgDir {
|
||||
SAD_in,
|
||||
SAD_out,
|
||||
SAD_inout,
|
||||
SAD_unknown,
|
||||
};
|
||||
|
||||
enum ShaderMatPiece {
|
||||
SMP_whole,
|
||||
SMP_transpose,
|
||||
SMP_row0,
|
||||
SMP_row1,
|
||||
SMP_row2,
|
||||
SMP_row3,
|
||||
SMP_col0,
|
||||
SMP_col1,
|
||||
SMP_col2,
|
||||
SMP_col3,
|
||||
};
|
||||
|
||||
enum ShaderMatFunc {
|
||||
SMF_compose,
|
||||
SMF_compose_cache_first,
|
||||
SMF_compose_cache_second,
|
||||
SMF_first,
|
||||
};
|
||||
|
||||
struct ShaderMatSpec {
|
||||
ShaderMatFunc _func;
|
||||
ShaderMatInput _part[2];
|
||||
PT(InternalName) _arg[2];
|
||||
LMatrix4f _cache;
|
||||
ShaderMatPiece _piece;
|
||||
bool _trans_dependent;
|
||||
void *_parameter;
|
||||
};
|
||||
|
||||
struct ShaderTexSpec {
|
||||
PT(InternalName) _name;
|
||||
int _stage;
|
||||
int _desired_type;
|
||||
PT(InternalName) _suffix;
|
||||
void *_parameter;
|
||||
};
|
||||
|
||||
struct ShaderVarSpec {
|
||||
PT(InternalName) _name;
|
||||
int _append_uv;
|
||||
void *_parameter;
|
||||
};
|
||||
|
||||
struct ShaderArgInfo {
|
||||
string _name;
|
||||
ShaderArgType _type;
|
||||
ShaderArgDir _direction;
|
||||
bool _varying;
|
||||
NotifyCategory *_cat;
|
||||
};
|
||||
|
||||
protected:
|
||||
pvector <ShaderMatSpec> _mat_spec;
|
||||
pvector <ShaderTexSpec> _tex_spec;
|
||||
pvector <ShaderVarSpec> _var_spec;
|
||||
|
||||
private:
|
||||
// These functions are only called from compile_parameter.
|
||||
|
||||
void cp_report_error(ShaderArgInfo &arg, const string &msg);
|
||||
bool cp_errchk_parameter_words(ShaderArgInfo &arg, int len);
|
||||
bool cp_errchk_parameter_in(ShaderArgInfo &arg);
|
||||
bool cp_errchk_parameter_varying(ShaderArgInfo &arg);
|
||||
bool cp_errchk_parameter_uniform(ShaderArgInfo &arg);
|
||||
bool cp_errchk_parameter_float(ShaderArgInfo &arg, int lo, int hi);
|
||||
bool cp_errchk_parameter_sampler(ShaderArgInfo &arg);
|
||||
bool cp_parse_trans_clause(ShaderArgInfo &arg,
|
||||
ShaderMatSpec &spec,
|
||||
int part,
|
||||
const vector_string &pieces,
|
||||
int &next,
|
||||
ShaderMatInput ofop,
|
||||
ShaderMatInput op);
|
||||
void cp_optimize_mat_spec(ShaderMatSpec &spec);
|
||||
|
||||
protected:
|
||||
bool compile_parameter(void *reference,
|
||||
const string &arg_name,
|
||||
ShaderArgType arg_type,
|
||||
ShaderArgDir arg_direction,
|
||||
bool arg_varying,
|
||||
NotifyCategory *arg_cat);
|
||||
ShaderExpansion *_expansion;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
|
|||
|
|
@ -36,3 +36,69 @@ get_text() const {
|
|||
return _text;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderExpansion::get_header
|
||||
// Access: Public
|
||||
// Description: Return the ShaderExpansion's header line.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &ShaderExpansion::
|
||||
get_header() const {
|
||||
return _header;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderExpansion::get_error_flag
|
||||
// Access: Public
|
||||
// Description: Returns true if the shader contains a compile-time
|
||||
// error. This doesn't tell you whether or not the
|
||||
// shader is supported on the current video card.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ShaderExpansion::
|
||||
get_error_flag() const {
|
||||
return _error_flag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderExpansion::ShaderCapabilities Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ShaderExpansion::ShaderCaps::
|
||||
ShaderCaps() {
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderExpansion::ShaderCapabilities::clear()
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ShaderExpansion::ShaderCaps::
|
||||
clear() {
|
||||
#ifdef HAVE_CG
|
||||
_active_vprofile = 0;
|
||||
_active_fprofile = 0;
|
||||
_ultimate_vprofile = 0;
|
||||
_ultimate_fprofile = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderExpansion::ShaderCapabilities::operator ==
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ShaderExpansion::ShaderCaps::
|
||||
operator == (const ShaderCaps &other) const {
|
||||
#ifdef HAVE_CG
|
||||
if ((_active_vprofile != other._active_vprofile) ||
|
||||
(_active_fprofile != other._active_fprofile) ||
|
||||
(_ultimate_vprofile != other._ultimate_vprofile) ||
|
||||
(_ultimate_fprofile != other._ultimate_fprofile)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -25,29 +25,169 @@
|
|||
#include "graphicsStateGuardianBase.h"
|
||||
#include "internalName.h"
|
||||
|
||||
#ifdef HAVE_CG
|
||||
// I don't want to include the Cg header file into panda as a
|
||||
// whole. Instead, I'll just excerpt some opaque declarations.
|
||||
typedef struct _CGcontext *CGcontext;
|
||||
typedef struct _CGprogram *CGprogram;
|
||||
typedef struct _CGparameter *CGparameter;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ShaderExpansion
|
||||
// Summary: A shader can contain context-sensitive macros.
|
||||
// A ShaderExpansion is the output you get when you
|
||||
// run the macro preprocessor on a shader.
|
||||
// The ShaderExpansion contains the shader's
|
||||
// macroexpanded text, and a map of ShaderContext
|
||||
// macroexpanded text, an analysis of the shader's
|
||||
// parameters, and a map of ShaderContext
|
||||
// objects.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EXPCL_PANDA ShaderExpansion: public TypedReferenceCount {
|
||||
|
||||
PUBLISHED:
|
||||
static PT(ShaderExpansion) make(const string &name, const string &body);
|
||||
|
||||
INLINE const string &get_name() const;
|
||||
INLINE const string &get_text() const;
|
||||
|
||||
INLINE const string &get_header() const;
|
||||
INLINE bool get_error_flag() const;
|
||||
|
||||
void prepare(PreparedGraphicsObjects *prepared_objects);
|
||||
bool release(PreparedGraphicsObjects *prepared_objects);
|
||||
int release_all();
|
||||
|
||||
PUBLISHED:
|
||||
public:
|
||||
|
||||
enum ShaderMatInput {
|
||||
SMO_identity,
|
||||
|
||||
SMO_window_size,
|
||||
SMO_pixel_size,
|
||||
SMO_card_center,
|
||||
|
||||
SMO_mat_constant_x,
|
||||
SMO_vec_constant_x,
|
||||
|
||||
SMO_world_to_view,
|
||||
SMO_view_to_world,
|
||||
|
||||
SMO_model_to_view,
|
||||
SMO_view_to_model,
|
||||
|
||||
SMO_apiview_to_view,
|
||||
SMO_view_to_apiview,
|
||||
|
||||
SMO_clip_to_view,
|
||||
SMO_view_to_clip,
|
||||
|
||||
SMO_apiclip_to_view,
|
||||
SMO_view_to_apiclip,
|
||||
|
||||
SMO_view_x_to_view,
|
||||
SMO_view_to_view_x,
|
||||
|
||||
SMO_apiview_x_to_view,
|
||||
SMO_view_to_apiview_x,
|
||||
|
||||
SMO_clip_x_to_view,
|
||||
SMO_view_to_clip_x,
|
||||
|
||||
SMO_apiclip_x_to_view,
|
||||
SMO_view_to_apiclip_x,
|
||||
};
|
||||
|
||||
enum ShaderArgType {
|
||||
SAT_float1,
|
||||
SAT_float2,
|
||||
SAT_float3,
|
||||
SAT_float4,
|
||||
SAT_float4x4,
|
||||
SAT_sampler1d,
|
||||
SAT_sampler2d,
|
||||
SAT_sampler3d,
|
||||
SAT_samplercube,
|
||||
SAT_unknown,
|
||||
};
|
||||
|
||||
enum ShaderArgDir {
|
||||
SAD_in,
|
||||
SAD_out,
|
||||
SAD_inout,
|
||||
SAD_unknown,
|
||||
};
|
||||
|
||||
enum ShaderMatPiece {
|
||||
SMP_whole,
|
||||
SMP_transpose,
|
||||
SMP_row0,
|
||||
SMP_row1,
|
||||
SMP_row2,
|
||||
SMP_row3,
|
||||
SMP_col0,
|
||||
SMP_col1,
|
||||
SMP_col2,
|
||||
SMP_col3,
|
||||
};
|
||||
|
||||
enum ShaderMatFunc {
|
||||
SMF_compose,
|
||||
SMF_compose_cache_first,
|
||||
SMF_compose_cache_second,
|
||||
SMF_first,
|
||||
};
|
||||
|
||||
struct ShaderArgId {
|
||||
string _name;
|
||||
bool _fshader;
|
||||
int _seqno;
|
||||
};
|
||||
|
||||
struct ShaderMatSpec {
|
||||
ShaderArgId _id;
|
||||
ShaderMatFunc _func;
|
||||
ShaderMatInput _part[2];
|
||||
PT(InternalName) _arg[2];
|
||||
LMatrix4f _cache;
|
||||
ShaderMatPiece _piece;
|
||||
bool _trans_dependent;
|
||||
};
|
||||
|
||||
struct ShaderTexSpec {
|
||||
ShaderArgId _id;
|
||||
PT(InternalName) _name;
|
||||
int _stage;
|
||||
int _desired_type;
|
||||
PT(InternalName) _suffix;
|
||||
};
|
||||
|
||||
struct ShaderVarSpec {
|
||||
ShaderArgId _id;
|
||||
PT(InternalName) _name;
|
||||
int _append_uv;
|
||||
};
|
||||
|
||||
struct ShaderArgInfo {
|
||||
ShaderArgId _id;
|
||||
ShaderArgType _type;
|
||||
ShaderArgDir _direction;
|
||||
bool _varying;
|
||||
NotifyCategory *_cat;
|
||||
};
|
||||
|
||||
struct ShaderCaps {
|
||||
#ifdef HAVE_CG
|
||||
int _active_vprofile;
|
||||
int _active_fprofile;
|
||||
int _ultimate_vprofile;
|
||||
int _ultimate_fprofile;
|
||||
#endif;
|
||||
INLINE void clear();
|
||||
INLINE bool operator == (const ShaderCaps &other) const;
|
||||
INLINE ShaderCaps();
|
||||
};
|
||||
|
||||
private:
|
||||
// These routines help split the shader into sections,
|
||||
// for those shader implementations that need to do so.
|
||||
void parse_init();
|
||||
|
|
@ -57,11 +197,65 @@ PUBLISHED:
|
|||
int parse_lineno();
|
||||
bool parse_eof();
|
||||
|
||||
public:
|
||||
~ShaderExpansion();
|
||||
void cp_report_error(ShaderArgInfo &arg, const string &msg);
|
||||
bool cp_errchk_parameter_words(ShaderArgInfo &arg, int len);
|
||||
bool cp_errchk_parameter_in(ShaderArgInfo &arg);
|
||||
bool cp_errchk_parameter_varying(ShaderArgInfo &arg);
|
||||
bool cp_errchk_parameter_uniform(ShaderArgInfo &arg);
|
||||
bool cp_errchk_parameter_float(ShaderArgInfo &arg, int lo, int hi);
|
||||
bool cp_errchk_parameter_sampler(ShaderArgInfo &arg);
|
||||
bool cp_parse_trans_clause(ShaderArgInfo &arg,
|
||||
ShaderMatSpec &spec,
|
||||
int part,
|
||||
const vector_string &pieces,
|
||||
int &next,
|
||||
ShaderMatInput ofop,
|
||||
ShaderMatInput op);
|
||||
void cp_optimize_mat_spec(ShaderMatSpec &spec);
|
||||
|
||||
bool compile_parameter(const ShaderArgId &arg_id,
|
||||
ShaderArgType arg_type,
|
||||
ShaderArgDir arg_direction,
|
||||
bool arg_varying,
|
||||
NotifyCategory *arg_cat);
|
||||
|
||||
void clear_parameters();
|
||||
|
||||
#ifdef HAVE_CG
|
||||
private:
|
||||
ShaderArgType cg_parameter_type(CGparameter p);
|
||||
ShaderArgDir cg_parameter_dir(CGparameter p);
|
||||
CGprogram cg_compile_entry_point(char *entry, int active, int ultimate);
|
||||
bool cg_analyze_entry_point(CGprogram prog, bool fshader);
|
||||
bool cg_analyze_shader(const ShaderCaps &caps);
|
||||
bool cg_compile_shader(const ShaderCaps &caps);
|
||||
void cg_release_resources();
|
||||
|
||||
ShaderCaps _cg_last_caps;
|
||||
CGcontext _cg_context;
|
||||
CGprogram _cg_vprogram;
|
||||
CGprogram _cg_fprogram;
|
||||
|
||||
public:
|
||||
|
||||
bool cg_compile_for(const ShaderCaps &caps,
|
||||
CGcontext &ctx,
|
||||
CGprogram &vprogram,
|
||||
CGprogram &fprogram,
|
||||
pvector<CGparameter> &map);
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
pvector <ShaderMatSpec> _mat_spec;
|
||||
pvector <ShaderTexSpec> _tex_spec;
|
||||
pvector <ShaderVarSpec> _var_spec;
|
||||
|
||||
protected:
|
||||
string _name;
|
||||
string _text;
|
||||
string _header;
|
||||
bool _error_flag;
|
||||
int _parse;
|
||||
|
||||
typedef pair < string, string > ExpansionKey;
|
||||
|
|
@ -73,15 +267,23 @@ public:
|
|||
|
||||
typedef pmap <PreparedGraphicsObjects *, ShaderContext *> Contexts;
|
||||
Contexts _contexts;
|
||||
|
||||
|
||||
public:
|
||||
ShaderContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
|
||||
GraphicsStateGuardianBase *gsg);
|
||||
|
||||
private:
|
||||
ShaderExpansion();
|
||||
private:
|
||||
ShaderExpansion(const string &name, const string &text,
|
||||
const ShaderCaps &caps);
|
||||
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
|
||||
|
||||
public:
|
||||
public:
|
||||
static PT(ShaderExpansion) make(const string &name, const string &body,
|
||||
const ShaderCaps &caps);
|
||||
|
||||
~ShaderExpansion();
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
|
|
@ -95,7 +297,7 @@ public:
|
|||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -44,9 +44,6 @@
|
|||
#define EXPCL_GL EXPCL_PANDAMESA
|
||||
#define EXPTP_GL EXPTP_PANDAMESA
|
||||
|
||||
#undef HAVE_CGGL // Mesa does not support Nvidia Cg... make sure it tries to compile
|
||||
// without it
|
||||
|
||||
// Don't include Mesa's provided glext.h file; we'll provide our own
|
||||
// that's more current.
|
||||
#define __glext_h_
|
||||
|
|
|
|||
|
|
@ -140,15 +140,19 @@ make(const string &body, int preprocessor) {
|
|||
//
|
||||
// Currently, macroexpand is just a stub that returns an
|
||||
// expansion which is exactly equal to the input string.
|
||||
//
|
||||
// The "caps" parameter should describe the capabilities
|
||||
// of the gsg on which this is intended to run.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(ShaderExpansion) Shader::
|
||||
macroexpand(const RenderState *context) const {
|
||||
macroexpand(const RenderState *context,
|
||||
const ShaderExpansion::ShaderCaps &caps) const {
|
||||
if (_fixed_expansion) {
|
||||
return _fixed_expansion;
|
||||
}
|
||||
// I am casting away the 'const' so as to be able
|
||||
// to write to this field. This field is just a cache.
|
||||
((Shader*)this)->_fixed_expansion = ShaderExpansion::make(_name,_body);
|
||||
((Shader*)this)->_fixed_expansion = ShaderExpansion::make(_name,_body,caps);
|
||||
return _fixed_expansion;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ PUBLISHED:
|
|||
INLINE bool get_loaded() const;
|
||||
INLINE bool get_load_error() const;
|
||||
|
||||
PT(ShaderExpansion) macroexpand(const RenderState *context) const;
|
||||
PT(ShaderExpansion) macroexpand(const RenderState *context,
|
||||
const ShaderExpansion::ShaderCaps &caps) const;
|
||||
|
||||
public:
|
||||
Shader();
|
||||
|
|
|
|||
Loading…
Reference in New Issue