LukasBanana / XShaderCompiler

Shader cross compiler to translate HLSL (Shader Model 4 and 5) to GLSL
BSD 3-Clause "New" or "Revised" License
351 stars 48 forks source link

Request: "carried define" #83

Closed cybik closed 6 years ago

cybik commented 6 years ago

So, for specific reasons I don't want to get into, the OpenGL part of an engine I'm working on has a very specific naming convention I need to use (basically, I have only a number to deduce the name of the uniform I'm setting a value to - OpenGL 3.3 Core, cannot use Compatibility).

The only way I've found to do this and use XSC, is to manually change the output's uniform names, from (for example)

uniform mat4 vreg_0;
#define ModelToWorld vreg_0

And then the meat of the code translated via XSC can be used as-is.

My request: Can we somehow have a way to tell XSC to "carry a define through"?

LukasBanana commented 6 years ago

Do you have these macros (i.e. 'defines') in your HLSL code that you'd like to preserve in the output code? Or do you want to add those macros afterwards, so that Xsc inserts them after the #version directive?

Anyways, have you tried to use the shader reflection to automatically generate the macros using the ReflectionData::uniforms member?

cybik commented 6 years ago

Do you have these macros (i.e. 'defines') in your HLSL code that you'd like to preserve in the output code?

That's the short version of it, yes. Technically, we may want to generate the macros through macros :P (a macro that would generate both a variable definition, and another macro defining the name)

Anyways, have you tried to use the shader reflection to automatically generate the macros using the ReflectionData::uniforms member?

That looks interesting. How can I do that?

LukasBanana commented 6 years ago

Xsc currently does not support macro preservation, because all macros must be evaluated before the input shader is parsed and analyzed. So I think the only option right now is to insert your macros afterwards.

Using the shader reflection could look like this:

Xsc::Reflection::ReflectionData myReflect;
if (Xsc::CompileShader(myInputDesc, myOutputDesc, nullptr, &myReflect)) {
    for (const std::string& uniform : myReflect.uniforms) {
        /* Use 'uniform' string to append macro ... */
    }
}

The uniform wvpMatrix in the following HLSL vertex shader will be contained in the shader reflection:

uniform float4x4 wvpMatrix;
float4 main(float4 p : POS) : SV_POSITION {
    return mul(wvpMatrix, p);
}

However, the shader reflection in general is still some how restricted, but maybe it'll work for you.

cybik commented 6 years ago

Those uniforms are only described as Strings and not have "more data"; basically, I can't change their names to match our spec (as I need to change their names AND guess the new names easily). Reflection is unfortunately a nope in this case :(

This may end up becoming a "new feature" of sorts for XSC: Annotations. I'm not "officially" requesting it, but if you could consider it for your personal backlog, it would be grand. (I don't exactly have a clue about how to help implement it, to be honest, or where to throw experimental code for it.)

LukasBanana commented 6 years ago

Shader reflection is only a feedback, that's why you can't change their names. But you can use this feedback to modify the output stream.

Example in Pseudocode:

if Compile(Input, Output, Reflection) {
  for each uniform in Reflection.uniforms {
    Output.AppendFront("#define " + uniform + " <my macro body here...>\n");
  }
}
LukasBanana commented 6 years ago

Does my previous suggestion work for you, or is this still an open issue?

cybik commented 6 years ago

Unfortunately, even with all my experimentation, it still poses an issue as the uniform data is only a String. If the uniform data had more information (like, for example, the HLSL register it's going into), then I could very easily force a define in there.

LukasBanana commented 6 years ago

Can you share such a String please? I still have trouble to understand the situation you are in.

cybik commented 6 years ago

No need, we're kind of abandoning the reflection. I managed to get some data "into" reflection, but it doesn't get into the outgoing GLSL (yet anyway), so it doesn't serve our purposes. We've managed to code a post-processing script for our purposes, so you can consider the issue "somewhat" resolved.

I'd love to discuss the intricacies of what we're trying to accomplish over an IM session!

LukasBanana commented 6 years ago

OK, alternatively you can maybe add the macro output to the GLSL backend in your fork (i.e. the GLSLGenerator.cpp source file).

BTW: what was "IM" again?

cybik commented 6 years ago

Instant Messaging :)

LukasBanana commented 6 years ago

Ok, just use the EMail on my homepage, if you want to go into more details.