Setting Parameters in Effects

This topic is 4856 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

This question is specific to Managed Direct3D, as it wouldn't be an issue with native Direct3D. I have a structure (well, struct in C#) that I want to set as a parameter to a D3D Effect. I know it's possible, because I have some code in C++ that does exactly that. Normally, you'd set a parameter like this:
int nValue = 1;
myEffect.SetValue(EffectHandle parameter, nValue);


However, for non-integral types it becomes more complicated. There's only two overloads of SetValue that look like they could take a structure:
Effect.SetValue(EffectHandle parameter, GraphicsStream data);
Effect.SetValue(EffectHandle parameter, void* data, int dataSize);


The problem is, I have no idea how to get my struct into a GraphicsStream, or converted to a void*. I've messed around with unsafe pointers, the System.Runtime.InteropServices.Marshal class, etc., but can't get anything to work. Can anyone help? Any assistance would be much appreciated... Tim

Share on other sites
Never mind, I've solved it - in case anybody is interested, here's how to do it (note that the object passed in must be a struct, not a class.

using System.Runtime.InteropServices;public unsafe void SetStructure(string sParameterName, object pObject){	int nSize = Marshal.SizeOf(pObject);	IntPtr pUnmanagedPointer = Marshal.AllocHGlobal(nSize);	Marshal.StructureToPtr(pObject, pUnmanagedPointer, true);	m_pEffect.SetValue(GetEffectHandle(sParameterName), pUnmanagedPointer.ToPointer(), nSize);	Marshal.FreeHGlobal(pUnmanagedPointer);}

Share on other sites
Neat! I was wondering how I would go about integrating shaders with my C# based DX engine and since I have a material (different from DX) structure ...

Thanks for sharing!

Share on other sites
Interesting. That kinda sucks that you can't simply cast to void*. Fortunately for begginners, C# doesn't really deal much with pointers and memory managment. Unfortunately for the advanced developers, it would have come in handy in places like this.

Share on other sites
Indeed. Although it's not really that difficult to get a pointer (once you know how to do it, anyway), and in my (c#-biased) opinion the ease of memory management makes it worth it...

Anyway, there may well be a better method than the one above, but it works, so I'm happy for the moment :)

Tim

Share on other sites
Quote:
 Original post by circlesoftThat kinda sucks that you can't simply cast to void*.

I think you can so long as it is a value type.

Did you try something like this?

unsafe{
m_pEffect.SetValue(sParameterName, (void*)&pObject, nSize);
}

Note that EffectHandles are implicitly cast from strings and the reason that you would use GetParameter to pre fetch a handle is to avoid having the effect look it up every time you set it. Still it is probably going to be hard to make a faster name lookup method than that within the Effect classes. In other words use the string names when you call SetValue unless you know for sure you are making an optimization.

Share on other sites
Hi turnpast,

I did used to pass in the parameter name as a string, but I've since changed it (I store the EffectHandles in a Hashtable, keyed by parameter name). I don't know which is faster as I haven't profiled it yet, but gut feeling is my Hashtable is faster than passing in strings. I've used Reflector and I can't see that the Direct3D code is doing any caching of EffectHandles.

I did also try the code you suggested before I came up with my solution, but the compiler throws this error:

Cannot take the address or size of a variable of a managed type ('object')

The compiler says that even if you pass it a struct (i.e. not boxed into an object).

Tim

Share on other sites
Quote:
 Original post by roastedamoebaCannot take the address or size of a variable of a managed type ('object')The compiler says that even if you pass it a struct (i.e. not boxed into an object).

Yes, you can only take the address of value types (ie. structs) in that way. That said, if you are passing structures into your effects you should probably be using structs and even explicitly laying out the varaibles in your struct with the StructLayout attribute. (then you know the size too).

The other way to access the members of structs in your effect is to pass the EffectHandle of the sturct as the first argument to GetParameter and the name of the member as the second. When you are accessing an array you can also use GetParameterElement to get a handle on a single element of the array.

//Struct:
EffectHandle structHandle = effect.GetParameter(null,"someStruct");
EffectHandle memberHandle = effect.GetParameter(structHandle,"someMember");
//Array:
EffectHandle arrayHandle = effect.GetParameter(null,"someArray");
EffectHandle thirdElementHandle = effect.GetParameterElement(structHandle,2);

One more thing:
Microsoft.DirectX.DXHelp several methods to 'help' with this stuff: CopyObjectDataToPointer, CopyPointerDataToObject, GetObjectSize and GetTypeSize.

Share on other sites
Quote:
 Original post by turnpastYes, you can only take the address of value types (ie. structs) in that way. That said, if you are passing structures into your effects you should probably be using structs and even explicitly laying out the varaibles in your struct with the StructLayout attribute. (then you know the size too).

Yes, that's what I meant - you can't take the address of structs, the compiler throws an error. I think you have to use the "fixed" keyword.

I am passing a struct into my effect, and it seems to be working without the StructLayout attribute.

Quote:
 Original post by turnpastThe other way to access the members of structs in your effect is to pass the EffectHandle of the sturct as the first argument to GetParameter and the name of the member as the second. When you are accessing an array you can also use GetParameterElement to get a handle on a single element of the array.

True, but the whole reason I'm using a struct is so I don't need to pass each member in individually.

Quote:
 Original post by turnpastOne more thing:Microsoft.DirectX.DXHelp several methods to 'help' with this stuff: CopyObjectDataToPointer, CopyPointerDataToObject, GetObjectSize and GetTypeSize.

Interesting - didn't know about those, thank you :) The documentation for CopyObjectDataToPointer says that it copies strings and arrays of strings, nothing about structs, but I haven't tried it.

1. 1
2. 2
3. 3
Rutin
22
4. 4
5. 5

• 11
• 17
• 14
• 9
• 9
• Forum Statistics

• Total Topics
632929
• Total Posts
3009278
• Who's Online (See full list)

There are no registered users currently online

×