OSDN Git Service

extra resources required for generating shader program binary (v3)
authorDongwon Kim <dongwon.kim@intel.com>
Wed, 28 Mar 2018 22:57:45 +0000 (15:57 -0700)
committerKalyan Kondapally <kalyan.kondapally@intel.com>
Sun, 22 Apr 2018 19:02:49 +0000 (12:02 -0700)
Collection of resources needed for pre-processing of prebuilt shader
programs. Its final goal is to generate program binary in the form of
header file that can be included when HWC is built.

'generate_c_arrays.sh' is the starting point of this process. It first
generates shader_test files with given shader source code then passes
those to the 'shader-db' ('shader-db' directory or a symbolic link to
it is required to be in the same directory as this script) to get them
compiled and linked then creates header files with the shader program
binary.

Subsequential patch(es) on gl compostor code will add the option to use
this built-in binaries in generated header files.

v2: more error checks on file stream ptrs and binary_sz in bin_to_c_array.c

v3: 1. bin_to_c_array.c code format adjustment using clang-format
    2. change year to 2018 in license phrase
    3. not printing out usage help (print_usage()) when not needed

Jira: None.
Test: Linux tests continue to work as now.

Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
common/compositor/gl/gl_shader_pre_built/bin_to_c_array.c [new file with mode: 0644]
common/compositor/gl/gl_shader_pre_built/generate_c_arrays.sh [new file with mode: 0755]
common/compositor/gl/gl_shader_pre_built/generate_shader_test.sh [new file with mode: 0755]
common/compositor/gl/gl_shader_pre_built/require.txt [new file with mode: 0644]

diff --git a/common/compositor/gl/gl_shader_pre_built/bin_to_c_array.c b/common/compositor/gl/gl_shader_pre_built/bin_to_c_array.c
new file mode 100644 (file)
index 0000000..8cb89b5
--- /dev/null
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define LICENSE_TERM                                                         \
+  "// Copyright (c) 2018 Intel Corporation\n"                                \
+  "//\n"                                                                     \
+  "// Licensed under the Apache License, Version 2.0 (the \"License\");\n"   \
+  "// you may not use this file except in compliance with the License.\n"    \
+  "// You may obtain a copy of the License at\n"                             \
+  "//\n"                                                                     \
+  "//      http://www.apache.org/licenses/LICENSE-2.0\n"                     \
+  "//\n"                                                                     \
+  "// Unless required by applicable law or agreed to in writing, software\n" \
+  "// distributed under the License is distributed on an \"AS IS\" BASIS,\n" \
+  "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or "      \
+  "implied.\n"                                                               \
+  "// See the License for the specific language governing permissions and\n" \
+  "// limitations under the License.\n"                                      \
+  "\n"                                                                       \
+  "// clang-format off\n"
+
+void print_usage(void) {
+  fprintf(stdout, "./bin_to_c_array <input bin file> <output file>\n");
+  fprintf(stdout,
+          "ex)./bin_to_c_array hwc_shader_prog_1.shader_test.bin "
+          "hwc_shader_prog_1.h\n\n");
+}
+
+int main(int argc, char *argv[]) {
+  FILE *binary_fp, *header_fp;
+  int byte;
+  int i = 0;
+
+  if (argc < 3) {
+    fprintf(stderr, "need input and output file names\n");
+    print_usage();
+    exit(-1);
+  }
+
+  /* print out information */
+  fprintf(stdout, "input file:%s\n", argv[1]);
+  fprintf(stdout, "output file:%s\n", argv[2]);
+
+  binary_fp = fopen(argv[1], "rb");
+
+  if (!binary_fp) {
+    fprintf(stderr, "input file does not exist\n");
+    exit(-1);
+  }
+
+  /* getting the size of binary file */
+  fseek(binary_fp, 0, SEEK_END);
+  long binary_sz = ftell(binary_fp);
+  rewind(binary_fp);
+
+  if (binary_sz == 0) {
+    fprintf(stderr, "binary size is 0.. no data to retrieve..exiting.\n");
+    fclose(binary_fp);
+    exit(-1);
+  }
+
+  header_fp = fopen(argv[2], "wb");
+
+  if (!header_fp) {
+    fprintf(stderr, "failed to create output file\n");
+    fclose(binary_fp);
+    exit(-1);
+  }
+
+  fprintf(header_fp, LICENSE_TERM "\n");
+
+  fprintf(stdout, "file size: %ld\n", binary_sz);
+
+  /* write binary size to the beginning of the file */
+  for (i = 0; i < sizeof(binary_sz); i++) {
+    fprintf(header_fp, "0x%02x, ", (unsigned char)(binary_sz & 0xFF));
+    binary_sz >>= 8;
+  }
+
+  fprintf(header_fp, "// size of this binary\n");
+
+  while (byte != EOF) {
+    for (i = 0; i < 12; i++) {
+      byte = fgetc(binary_fp);
+      fprintf(header_fp, "0x%02x, ", (unsigned char)byte);
+    }
+    fprintf(header_fp, "\n");
+  }
+
+  fprintf(stdout,
+          "Done, file %s has been successfully"
+          " generated\n",
+          argv[2]);
+
+  fclose(header_fp);
+  fclose(binary_fp);
+
+  return 0;
+}
diff --git a/common/compositor/gl/gl_shader_pre_built/generate_c_arrays.sh b/common/compositor/gl/gl_shader_pre_built/generate_c_arrays.sh
new file mode 100755 (executable)
index 0000000..91fd678
--- /dev/null
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+if [ $# -eq 0 ]
+  then
+    echo "Need PCI-ID of the target"
+    exit
+fi
+
+TEMP_LD_LIBRARY_PATH=$LD_LIBRARY_PATH
+unset LD_LIBRARY_PATH
+
+SHADER_PRE_BUILT_PATH=$PWD/compositor/gl/gl_shader_pre_built
+
+TARGET_I965=$WLD/lib/dri
+TARGET_PCI_ID=$1
+
+OUT_DIR=$SHADER_PRE_BUILT_PATH/shader_prog_arrays
+OUT_HEADER=$SHADER_PRE_BUILT_PATH/glprebuiltshaderarray.h
+
+SHADER_TEST_FILE_PREFIX=hwc_shader_prog_
+SHADER_TEST_FOLDER=$SHADER_PRE_BUILT_PATH/shader-test
+BIN_TO_ARRAY=$SHADER_PRE_BUILT_PATH/bin_to_c_array
+SHADER_DB_DIR=$SHADER_PRE_BUILT_PATH/shader-db
+
+MAX_NUM_LAYERS=16
+GEN_SHADER_TEST=$SHADER_PRE_BUILT_PATH/generate_shader_test.sh
+
+#building bin_to_c_arrays
+gcc $BIN_TO_ARRAY.c -o $BIN_TO_ARRAY
+
+i=1
+
+#generate shader-tests
+while [ $i -le $MAX_NUM_LAYERS ]
+do
+   $GEN_SHADER_TEST $i
+   i=$(( $i + 1 ))
+done
+
+mkdir -p $SHADER_TEST_FOLDER
+mv *.shader_test $SHADER_TEST_FOLDER
+
+#pre-build shader-tests to generate shader program binary files
+export LIBGL_DRIVERS_PATH=$TARGET_I965
+export LD_PRELOAD=$SHADER_DB_DIR/intel_stub.so${LD_PRELOAD:+:${LD_PRELOAD}}
+$SHADER_DB_DIR/run -p $TARGET_PCI_ID -b $SHADER_TEST_FOLDER
+unset LIBGL_DRIVERS_PATH
+unset LD_PRELOAD
+mkdir -p $OUT_DIR
+
+#generate arrays of shader program binary
+
+i=1
+while [ $i -le $MAX_NUM_LAYERS ]
+do
+   $BIN_TO_ARRAY $SHADER_TEST_FOLDER/$SHADER_TEST_FILE_PREFIX$i.shader_test.bin $OUT_DIR/$SHADER_TEST_FILE_PREFIX$i.h
+   prebuilt_shader_header+="static uint8_t shader_prog_$i[] = {\n"
+   prebuilt_shader_header+="#include "'"'"./gl_shader_pre_built/shader_prog_arrays/$SHADER_TEST_FILE_PREFIX$i.h"'"'"\n"
+   prebuilt_shader_header+="};\n\n"
+   i=$(( $i + 1 ))
+done
+
+prebuilt_shader_header+="static uint8_t *shader_prog_arrays[] = {\n"
+i=1
+while [ $i -le $MAX_NUM_LAYERS ]
+do
+   prebuilt_shader_header+="shader_prog_$i,\n"
+   i=$(( $i + 1 ))
+done
+prebuilt_shader_header+="};\n"
+
+echo -e $prebuilt_shader_header > $OUT_HEADER
+mv $OUT_HEADER $SHADER_PRE_BUILT_PATH/../
+
+export LD_LIBRARY_PATH=$TEMP_LD_LIBRARY_PATH
+
+echo "ALL DONE"
diff --git a/common/compositor/gl/gl_shader_pre_built/generate_shader_test.sh b/common/compositor/gl/gl_shader_pre_built/generate_shader_test.sh
new file mode 100755 (executable)
index 0000000..8d0dea9
--- /dev/null
@@ -0,0 +1,107 @@
+#!/bin/bash
+
+if [ $# -eq 0 ]
+  then
+    echo "No arguments supplied"
+    echo "Using layer_cnt = 1"
+    layer_cnt=1
+else
+    layer_cnt=$1
+fi
+
+SHADER_PRE_BUILT_PATH=$PWD/compositor/gl/gl_shader_pre_built
+REQ_FILE="$SHADER_PRE_BUILT_PATH/require.txt"
+
+while read -r line
+do
+    shader_test+="$line\n"
+done < "$REQ_FILE"
+
+# vertex shader creation
+shader_test+="\n"
+shader_test+="[vertex shader]\n\n"
+
+shader_test+="#version 300 es\n"
+shader_test+="#define LAYER_COUNT "
+shader_test+="$layer_cnt\n"
+
+shader_test+="precision mediump int;\n"
+shader_test+="uniform vec4 uViewport;\n"
+shader_test+="uniform vec4 uLayerCrop[LAYER_COUNT];\n"
+shader_test+="uniform mat2 uTexMatrix[LAYER_COUNT];\n"
+shader_test+="in vec2 vPosition;\n"
+shader_test+="in vec2 vTexCoords;\n"
+shader_test+="out vec2 fTexCoords[LAYER_COUNT];\n"
+shader_test+="void main() {\n"
+shader_test+="  for (int i = 0; i < LAYER_COUNT; i++) {\n"
+shader_test+="    vec2 tempCoords = vTexCoords * uTexMatrix[i];\n"
+shader_test+="    fTexCoords[i] =\n"
+shader_test+="        uLayerCrop[i].xy + tempCoords * uLayerCrop[i].zw;\n"
+shader_test+="  }\n"
+shader_test+="  vec2 scaledPosition = uViewport.xy + vPosition * uViewport.zw;\n"
+shader_test+="  gl_Position =\n"
+shader_test+="      vec4(scaledPosition * vec2(2.0) - vec2(1.0), 0.0, 1.0);\n"
+shader_test+="}\n"
+
+# fragment shader creation
+shader_test+="\n"
+shader_test+="[fragment shader]\n\n"
+shader_test+="#version 300 es\n"
+shader_test+="#define LAYER_COUNT "
+shader_test+="$layer_cnt\n"
+shader_test+="#extension GL_OES_EGL_image_external : require\n"
+shader_test+="precision mediump float;\n"
+
+i=0
+while [ $i -lt $layer_cnt ]
+do
+   shader_test+="uniform samplerExternalOES uLayerTexture$i;\n"
+   i=$(( $i + 1 ))
+done
+
+shader_test+="uniform float uLayerAlpha[LAYER_COUNT];\n"
+shader_test+="uniform float uLayerPremult[LAYER_COUNT];\n"
+shader_test+="in vec2 fTexCoords[LAYER_COUNT];\n"
+shader_test+="out vec4 oFragColor;\n"
+shader_test+="void main() {\n"
+shader_test+="  vec3 color = vec3(0.0, 0.0, 0.0);\n"
+shader_test+="  float alphaCover = 1.0;\n"
+shader_test+="  vec4 texSample;\n"
+shader_test+="  vec3 multRgb;\n";
+
+i=0
+while [ $i -lt $layer_cnt ]
+do
+   if [ $i -gt 0 ]
+   then
+        shader_test+="  if (alphaCover > 0.5/255.0) {\n"
+   fi
+   shader_test+="  texSample = texture2D(uLayerTexture$i"
+   shader_test+=",\n"
+   shader_test+="                        fTexCoords[$i"
+   shader_test+="]);\n"
+   shader_test+="  multRgb = texSample.rgb *\n"
+   shader_test+="            max(texSample.a, uLayerPremult[$i"
+   shader_test+="]);\n"
+   shader_test+="  color += multRgb * uLayerAlpha[$i"
+   shader_test+="] * alphaCover;\n"
+   shader_test+="  alphaCover *= 1.0 - texSample.a * uLayerAlpha["
+   shader_test+="$i];\n";
+   i=$(( $i + 1 ))
+done
+
+i=1
+while [ $i -lt $layer_cnt ]
+do
+   shader_test+="  }\n"
+   i=$(( $i + 1))
+done
+
+shader_test+="  oFragColor = vec4(color, 1.0 - alphaCover);\n"
+shader_test+="}\n"
+
+outfile_name=hwc_shader_prog_$layer_cnt.shader_test
+
+echo -e "$shader_test" > hwc_shader_prog_$layer_cnt.shader_test
+
+echo "$outfile_name is generated successfully"
diff --git a/common/compositor/gl/gl_shader_pre_built/require.txt b/common/compositor/gl/gl_shader_pre_built/require.txt
new file mode 100644 (file)
index 0000000..3e635ff
--- /dev/null
@@ -0,0 +1,4 @@
+[require]
+GLSL ES >= 3.00
+BindAttribLoc vPosition 0
+BindAttribLoc vTexCords 1