wined3d: Add ability to generate GLSL shader objects for vertex and pixel shaders.

Jason Green jave27 at gmail.com
Fri May 26 10:52:33 CDT 2006


Add ability to generate GLSL shader objects for vertex and pixel shaders.

- Also modifies the baseshader declarations, and a few minor
trace/formatting cleanups.
- With some advice from H. Verbeet.

We still need to change the reg_maps to be bitmaps instead of using
them as masks like we are now, but that's a separate issue.

This patch should have no effect unless you have the registry key
HKLU\Software\Wine\Direct3D\UseGLSL = "enabled".
-------------- next part --------------
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 4e30421..7c24fa0 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -549,8 +549,34 @@ void generate_glsl_declarations(
     shader_reg_maps* reg_maps,
     SHADER_BUFFER* buffer) {
 
+    IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
+    int i;
+
     FIXME("GLSL not fully implemented yet.\n");
 
+    /* Declare the constants (aka uniforms) */
+    shader_addline(buffer, "uniform vec4 C[%u];\n", This->baseShader.limits.constant_float);
+
+    /* Declare address variables */
+    for (i = 0; i < This->baseShader.limits.address; i++) {
+        if (reg_maps->address & (1 << i))
+            shader_addline(buffer, "ivec4 A%ld;\n", i);
+    }
+
+    /* Declare all named attributes (TODO: Add this to the reg_maps
+     * and only declare those that are needed) */
+    for (i = 0; i < This->baseShader.limits.attributes; i++) {
+        shader_addline(buffer, "attribute vec4 attrib%i;\n", i);
+    }
+
+    /* Declare temporary variables */
+    for(i = 0; i < This->baseShader.limits.temporary; i++) {
+        if (reg_maps->temporary & (1 << i))
+            shader_addline(buffer, "vec4 R%lu;\n", i);
+    }
+
+    /* Start the main program */
+    shader_addline(buffer, "void main() {\n");
 }
 
 /** Shared code in order to generate the bulk of the shader string.
@@ -585,7 +611,6 @@ void generate_base_shader(
     /* Pre-declare registers */
     if (wined3d_settings.shader_mode == SHADER_GLSL) {
         generate_glsl_declarations(iface, &reg_maps, buffer);
-        shader_addline(buffer, "void main() {\n");
     } else {
         generate_arb_declarations(iface, &reg_maps, buffer);
     }
@@ -680,8 +705,7 @@ void generate_base_shader(
 /** Prints the GLSL info log which will contain error messages if they exist */
 void print_glsl_info_log(
     WineD3D_GL_Info *gl_info,
-    GLhandleARB obj)
-{
+    GLhandleARB obj) {
     int infologLength = 0;
     char *infoLog;
 
@@ -689,11 +713,13 @@ void print_glsl_info_log(
                GL_OBJECT_INFO_LOG_LENGTH_ARB,
                &infologLength));
 
-    if (infologLength > 0)
+    /* A size of 1 is just a null-terminated string, so the log should be bigger than
+     * that if there are errors. */
+    if (infologLength > 1)
     {
         infoLog = (char *)HeapAlloc(GetProcessHeap(), 0, infologLength);
         GL_EXTCALL(glGetInfoLogARB(obj, infologLength, NULL, infoLog));
-        FIXME("Error received from GLSL shader #%u: %s", obj, debugstr_a(infoLog));
+        FIXME("Error received from GLSL shader #%u: %s\n", obj, debugstr_a(infoLog));
         HeapFree(GetProcessHeap(), 0, infoLog);
     }
 }
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index be4fbb8..283d1f0 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -941,6 +941,7 @@ void pshader_set_version(
       This->baseShader.version = major * 10 + minor;
       TRACE("ps_%lu_%lu\n", major, minor);
 
+      This->baseShader.limits.attributes = 0;
       This->baseShader.limits.address = 0;
 
       switch (This->baseShader.version) {
@@ -1298,8 +1299,28 @@ #endif
     buffer.bsize = 0;
     buffer.lineNo = 0;
 
-    /* TODO: Optionally, generate the GLSL shader instead */
-    if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
+    if (wined3d_settings.shader_mode == SHADER_GLSL) {
+
+        /* Create the hw GLSL shader object and assign it as the baseShader.prgId */
+        GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
+
+        /* Generate the bulk of the shader code */
+        generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
+
+        /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
+        if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
+            shader_addline(&buffer, "glFragColor = R0;\n");
+        shader_addline(&buffer, "}\n\0");
+
+        TRACE("Compiling shader object %u\n", shader_obj);
+        GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
+        GL_EXTCALL(glCompileShaderARB(shader_obj));
+        print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
+
+        /* Store the shader object */
+        This->baseShader.prgId = shader_obj;
+
+    } else if (wined3d_settings.shader_mode == SHADER_ARB) {
         /*  Create the hw ARB shader */
         shader_addline(&buffer, "!!ARBfp1.0\n");
 
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index cb8d973..d82546e 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -842,6 +842,7 @@ void vshader_set_version(
       TRACE("vs_%lu_%lu\n", major, minor);
 
       This->baseShader.limits.texture = 0;
+      This->baseShader.limits.attributes = 16;
 
       /* Must match D3DCAPS9.MaxVertexShaderConst: at least 256 for vs_2_0 */
       This->baseShader.limits.constant_float = WINED3D_VSHADER_MAX_CONSTANTS;
@@ -1063,8 +1064,26 @@ #endif
     buffer.bsize = 0;
     buffer.lineNo = 0;
 
-    /* TODO: Optionally, generate the GLSL shader instead */
-    if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
+    if (wined3d_settings.shader_mode == SHADER_GLSL) {
+
+        /* Create the hw GLSL shader program and assign it as the baseShader.prgId */
+        GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
+
+        /* Generate the bulk of the shader code */
+        generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
+
+        shader_addline(&buffer, "}\n\0");
+
+        TRACE("Compiling shader object %u\n", shader_obj);
+        GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer.buffer, NULL));
+        GL_EXTCALL(glCompileShaderARB(shader_obj));
+        print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
+
+        /* Store the shader object */
+        This->baseShader.prgId = shader_obj;
+
+    } else if (wined3d_settings.shader_mode == SHADER_ARB) {
+
         /*  Create the hw ARB shader */
         shader_addline(&buffer, "!!ARBvp1.0\n");
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3e3bf80..0552ee4 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1282,6 +1282,7 @@ typedef struct SHADER_LIMITS {
     unsigned int constant_float;
     unsigned int constant_bool;
     unsigned int address;
+    unsigned int attributes;
 } SHADER_LIMITS;
 
 /** Keeps track of details for TEX_M#x# shader opcodes which need to 


More information about the wine-patches mailing list