Updated bgfx, bx, and bimg
parent
aca4af5f6a
commit
f716a228f4
|
@ -1,22 +1,21 @@
|
|||
shallow_clone: true
|
||||
|
||||
os:
|
||||
- Visual Studio 2015
|
||||
- Visual Studio 2017
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- TOOLSET: vs2010
|
||||
- TOOLSET: vs2012
|
||||
- TOOLSET: vs2013
|
||||
- TOOLSET: vs2015
|
||||
- TOOLSET: vs2017
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
|
||||
install:
|
||||
- git clone https://github.com/bkaradzic/bx ..\bx
|
||||
- ..\bx\tools\bin\windows\genie --with-tools %TOOLSET%
|
||||
- git clone --depth 1 https://github.com/bkaradzic/bx ..\bx
|
||||
- git clone --depth 1 https://github.com/bkaradzic/bimg ..\bimg
|
||||
- ..\bx\tools\bin\windows\genie --with-tools --with-examples %TOOLSET%
|
||||
|
||||
build:
|
||||
project: .build/projects/$(TOOLSET)/bgfx.sln
|
||||
|
|
|
@ -6,11 +6,22 @@ matrix:
|
|||
- compiler: clang
|
||||
os: osx
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-5
|
||||
- g++-5
|
||||
- clang
|
||||
|
||||
before_script:
|
||||
git clone https://github.com/bkaradzic/bx ../bx
|
||||
- git clone --depth 1 https://github.com/bkaradzic/bx ../bx
|
||||
- git clone --depth 1 https://github.com/bkaradzic/bimg ../bimg
|
||||
|
||||
script:
|
||||
make build
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then make build CXX="g++-5" CC="gcc-5"; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then make build; fi
|
||||
|
||||
branches:
|
||||
only:
|
||||
|
@ -19,4 +30,4 @@ branches:
|
|||
notifications:
|
||||
email: false
|
||||
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode9.3
|
||||
|
|
|
@ -1,580 +0,0 @@
|
|||
/*
|
||||
* edtaa3()
|
||||
*
|
||||
* Sweep-and-update Euclidean distance transform of an
|
||||
* image. Positive pixels are treated as object pixels,
|
||||
* zero or negative pixels are treated as background.
|
||||
* An attempt is made to treat antialiased edges correctly.
|
||||
* The input image must have pixels in the range [0,1],
|
||||
* and the antialiased image should be a box-filter
|
||||
* sampling of the ideal, crisp edge.
|
||||
* If the antialias region is more than 1 pixel wide,
|
||||
* the result from this transform will be inaccurate.
|
||||
*
|
||||
* By Stefan Gustavson (stefan.gustavson@gmail.com).
|
||||
*
|
||||
* Originally written in 1994, based on a verbal
|
||||
* description of Per-Erik Danielsson's SSED8 algorithm
|
||||
* as presented in the PhD dissertation of Ingemar
|
||||
* Ragnemalm. This is Per-Erik Danielsson's scanline
|
||||
* scheme from 1979 - I only implemented it in C.
|
||||
*
|
||||
* Updated in 2004 to treat border pixels correctly,
|
||||
* and cleaned up the code to improve readability.
|
||||
*
|
||||
* Updated in 2009 to handle anti-aliased edges,
|
||||
* as published in the article "Anti-aliased Euclidean
|
||||
* distance transform" by Stefan Gustavson and Robin Strand,
|
||||
* Pattern Recognition Letters 32 (2011) 252–257.
|
||||
*
|
||||
* Updated in 2011 to avoid a corner case causing an
|
||||
* infinite loop for some input data.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Copyright (C) 2011 by Stefan Gustavson
|
||||
|
||||
(stefan.gustavson@liu.se)
|
||||
|
||||
This code is distributed under the permissive "MIT license":
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
* Compute the local gradient at edge pixels using convolution filters.
|
||||
* The gradient is computed only at edge pixels. At other places in the
|
||||
* image, it is never used, and it's mostly zero anyway.
|
||||
*/
|
||||
void computegradient(double *img, int w, int h, double *gx, double *gy)
|
||||
{
|
||||
int i,j,k;
|
||||
double glength;
|
||||
#define SQRT2 1.4142136
|
||||
for(i = 1; i < h-1; i++) { // Avoid edges where the kernels would spill over
|
||||
for(j = 1; j < w-1; j++) {
|
||||
k = i*w + j;
|
||||
if((img[k]>0.0) && (img[k]<1.0)) { // Compute gradient for edge pixels only
|
||||
gx[k] = -img[k-w-1] - SQRT2*img[k-1] - img[k+w-1] + img[k-w+1] + SQRT2*img[k+1] + img[k+w+1];
|
||||
gy[k] = -img[k-w-1] - SQRT2*img[k-w] - img[k-w+1] + img[k+w-1] + SQRT2*img[k+w] + img[k+w+1];
|
||||
glength = gx[k]*gx[k] + gy[k]*gy[k];
|
||||
if(glength > 0.0) { // Avoid division by zero
|
||||
glength = sqrt(glength);
|
||||
gx[k]=gx[k]/glength;
|
||||
gy[k]=gy[k]/glength;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Compute reasonable values for gx, gy also around the image edges.
|
||||
// (These are zero now, which reduces the accuracy for a 1-pixel wide region
|
||||
// around the image edge.) 2x2 kernels would be suitable for this.
|
||||
}
|
||||
|
||||
/*
|
||||
* A somewhat tricky function to approximate the distance to an edge in a
|
||||
* certain pixel, with consideration to either the local gradient (gx,gy)
|
||||
* or the direction to the pixel (dx,dy) and the pixel greyscale value a.
|
||||
* The latter alternative, using (dx,dy), is the metric used by edtaa2().
|
||||
* Using a local estimate of the edge gradient (gx,gy) yields much better
|
||||
* accuracy at and near edges, and reduces the error even at distant pixels
|
||||
* provided that the gradient direction is accurately estimated.
|
||||
*/
|
||||
double edgedf(double gx, double gy, double a)
|
||||
{
|
||||
double df, glength, temp, a1;
|
||||
|
||||
if ((gx == 0) || (gy == 0)) { // Either A) gu or gv are zero, or B) both
|
||||
df = 0.5-a; // Linear approximation is A) correct or B) a fair guess
|
||||
} else {
|
||||
glength = sqrt(gx*gx + gy*gy);
|
||||
if(glength>0) {
|
||||
gx = gx/glength;
|
||||
gy = gy/glength;
|
||||
}
|
||||
/* Everything is symmetric wrt sign and transposition,
|
||||
* so move to first octant (gx>=0, gy>=0, gx>=gy) to
|
||||
* avoid handling all possible edge directions.
|
||||
*/
|
||||
gx = fabs(gx);
|
||||
gy = fabs(gy);
|
||||
if(gx<gy) {
|
||||
temp = gx;
|
||||
gx = gy;
|
||||
gy = temp;
|
||||
}
|
||||
a1 = 0.5*gy/gx;
|
||||
if (a < a1) { // 0 <= a < a1
|
||||
df = 0.5*(gx + gy) - sqrt(2.0*gx*gy*a);
|
||||
} else if (a < (1.0-a1)) { // a1 <= a <= 1-a1
|
||||
df = (0.5-a)*gx;
|
||||
} else { // 1-a1 < a <= 1
|
||||
df = -0.5*(gx + gy) + sqrt(2.0*gx*gy*(1.0-a));
|
||||
}
|
||||
}
|
||||
return df;
|
||||
}
|
||||
|
||||
double distaa3(double *img, double *gximg, double *gyimg, int w, int c, int xc, int yc, int xi, int yi)
|
||||
{
|
||||
double di, df, dx, dy, gx, gy, a;
|
||||
int closest;
|
||||
|
||||
closest = c-xc-yc*w; // Index to the edge pixel pointed to from c
|
||||
a = img[closest]; // Grayscale value at the edge pixel
|
||||
gx = gximg[closest]; // X gradient component at the edge pixel
|
||||
gy = gyimg[closest]; // Y gradient component at the edge pixel
|
||||
|
||||
if(a > 1.0) a = 1.0;
|
||||
if(a < 0.0) a = 0.0; // Clip grayscale values outside the range [0,1]
|
||||
if(a == 0.0) return 1000000.0; // Not an object pixel, return "very far" ("don't know yet")
|
||||
|
||||
dx = (double)xi;
|
||||
dy = (double)yi;
|
||||
di = sqrt(dx*dx + dy*dy); // Length of integer vector, like a traditional EDT
|
||||
if(di==0) { // Use local gradient only at edges
|
||||
// Estimate based on local gradient only
|
||||
df = edgedf(gx, gy, a);
|
||||
} else {
|
||||
// Estimate gradient based on direction to edge (accurate for large di)
|
||||
df = edgedf(dx, dy, a);
|
||||
}
|
||||
return di + df; // Same metric as edtaa2, except at edges (where di=0)
|
||||
}
|
||||
|
||||
// Shorthand macro: add ubiquitous parameters img, gx, gy and w and call distaa3()
|
||||
#define DISTAA(c,xc,yc,xi,yi) (distaa3(img, gx, gy, w, c, xc, yc, xi, yi))
|
||||
|
||||
void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, short *disty, double *dist)
|
||||
{
|
||||
int x, y, i, c;
|
||||
int offset_u, offset_ur, offset_r, offset_rd,
|
||||
offset_d, offset_dl, offset_l, offset_lu;
|
||||
double olddist, newdist;
|
||||
int cdistx, cdisty, newdistx, newdisty;
|
||||
int changed;
|
||||
double epsilon = 1e-3; // Safeguard against errors due to limited precision
|
||||
|
||||
/* Initialize index offsets for the current image width */
|
||||
offset_u = -w;
|
||||
offset_ur = -w+1;
|
||||
offset_r = 1;
|
||||
offset_rd = w+1;
|
||||
offset_d = w;
|
||||
offset_dl = w-1;
|
||||
offset_l = -1;
|
||||
offset_lu = -w-1;
|
||||
|
||||
/* Initialize the distance images */
|
||||
for(i=0; i<w*h; i++) {
|
||||
distx[i] = 0; // At first, all pixels point to
|
||||
disty[i] = 0; // themselves as the closest known.
|
||||
if(img[i] <= 0.0)
|
||||
{
|
||||
dist[i]= 1000000.0; // Big value, means "not set yet"
|
||||
}
|
||||
else if (img[i]<1.0) {
|
||||
dist[i] = edgedf(gx[i], gy[i], img[i]); // Gradient-assisted estimate
|
||||
}
|
||||
else {
|
||||
dist[i]= 0.0; // Inside the object
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform the transformation */
|
||||
do
|
||||
{
|
||||
changed = 0;
|
||||
|
||||
/* Scan rows, except first row */
|
||||
for(y=1; y<h; y++)
|
||||
{
|
||||
|
||||
/* move index to leftmost pixel of current row */
|
||||
i = y*w;
|
||||
|
||||
/* scan right, propagate distances from above & left */
|
||||
|
||||
/* Leftmost pixel is special, has no left neighbors */
|
||||
olddist = dist[i];
|
||||
if(olddist > 0) // If non-zero distance or not set yet
|
||||
{
|
||||
c = i + offset_u; // Index of candidate for testing
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx;
|
||||
newdisty = cdisty+1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_ur;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx-1;
|
||||
newdisty = cdisty+1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
|
||||
/* Middle pixels have all neighbors */
|
||||
for(x=1; x<w-1; x++, i++)
|
||||
{
|
||||
olddist = dist[i];
|
||||
if(olddist <= 0) continue; // No need to update further
|
||||
|
||||
c = i+offset_l;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx+1;
|
||||
newdisty = cdisty;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_lu;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx+1;
|
||||
newdisty = cdisty+1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_u;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx;
|
||||
newdisty = cdisty+1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_ur;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx-1;
|
||||
newdisty = cdisty+1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Rightmost pixel of row is special, has no right neighbors */
|
||||
olddist = dist[i];
|
||||
if(olddist > 0) // If not already zero distance
|
||||
{
|
||||
c = i+offset_l;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx+1;
|
||||
newdisty = cdisty;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_lu;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx+1;
|
||||
newdisty = cdisty+1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_u;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx;
|
||||
newdisty = cdisty+1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move index to second rightmost pixel of current row. */
|
||||
/* Rightmost pixel is skipped, it has no right neighbor. */
|
||||
i = y*w + w-2;
|
||||
|
||||
/* scan left, propagate distance from right */
|
||||
for(x=w-2; x>=0; x--, i--)
|
||||
{
|
||||
olddist = dist[i];
|
||||
if(olddist <= 0) continue; // Already zero distance
|
||||
|
||||
c = i+offset_r;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx-1;
|
||||
newdisty = cdisty;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan rows in reverse order, except last row */
|
||||
for(y=h-2; y>=0; y--)
|
||||
{
|
||||
/* move index to rightmost pixel of current row */
|
||||
i = y*w + w-1;
|
||||
|
||||
/* Scan left, propagate distances from below & right */
|
||||
|
||||
/* Rightmost pixel is special, has no right neighbors */
|
||||
olddist = dist[i];
|
||||
if(olddist > 0) // If not already zero distance
|
||||
{
|
||||
c = i+offset_d;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx;
|
||||
newdisty = cdisty-1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_dl;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx+1;
|
||||
newdisty = cdisty-1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
i--;
|
||||
|
||||
/* Middle pixels have all neighbors */
|
||||
for(x=w-2; x>0; x--, i--)
|
||||
{
|
||||
olddist = dist[i];
|
||||
if(olddist <= 0) continue; // Already zero distance
|
||||
|
||||
c = i+offset_r;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx-1;
|
||||
newdisty = cdisty;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_rd;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx-1;
|
||||
newdisty = cdisty-1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_d;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx;
|
||||
newdisty = cdisty-1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_dl;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx+1;
|
||||
newdisty = cdisty-1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
/* Leftmost pixel is special, has no left neighbors */
|
||||
olddist = dist[i];
|
||||
if(olddist > 0) // If not already zero distance
|
||||
{
|
||||
c = i+offset_r;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx-1;
|
||||
newdisty = cdisty;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_rd;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx-1;
|
||||
newdisty = cdisty-1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
olddist=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
c = i+offset_d;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx;
|
||||
newdisty = cdisty-1;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move index to second leftmost pixel of current row. */
|
||||
/* Leftmost pixel is skipped, it has no left neighbor. */
|
||||
i = y*w + 1;
|
||||
for(x=1; x<w; x++, i++)
|
||||
{
|
||||
/* scan right, propagate distance from left */
|
||||
olddist = dist[i];
|
||||
if(olddist <= 0) continue; // Already zero distance
|
||||
|
||||
c = i+offset_l;
|
||||
cdistx = distx[c];
|
||||
cdisty = disty[c];
|
||||
newdistx = cdistx+1;
|
||||
newdisty = cdisty;
|
||||
newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
|
||||
if(newdist < olddist-epsilon)
|
||||
{
|
||||
distx[i]=newdistx;
|
||||
disty[i]=newdisty;
|
||||
dist[i]=newdist;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while(changed); // Sweep until no more updates are made
|
||||
|
||||
/* The transformation is completed. */
|
||||
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef EDTAA3_H_HEADER_GUARD
|
||||
#define EDTAA3_H_HEADER_GUARD
|
||||
|
||||
extern void computegradient(double *img, int w, int h, double *gx, double *gy);
|
||||
extern void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, short *disty, double *dist);
|
||||
|
||||
#endif // EDTAA3_H_HEADER_GUARD
|
|
@ -1,161 +0,0 @@
|
|||
Apache License
|
||||
|
||||
Version 2.0, January 2004
|
||||
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the
|
||||
copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other
|
||||
entities that control, are controlled by, or are under common control with
|
||||
that entity. For the purposes of this definition, "control" means (i) the
|
||||
power, direct or indirect, to cause the direction or management of such
|
||||
entity, whether by contract or otherwise, or (ii) ownership of fifty
|
||||
percent (50%) or more of the outstanding shares, or (iii) beneficial
|
||||
ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation
|
||||
or translation of a Source form, including but not limited to compiled
|
||||
object code, generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object
|
||||
form, made available under the License, as indicated by a copyright
|
||||
notice that is included in or attached to the work (an example is
|
||||
provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original
|
||||
version of the Work and any modifications or additions to that Work or
|
||||
Derivative Works thereof, that is intentionally submitted to Licensor
|
||||
for inclusion in the Work by the copyright owner or by an individual or
|
||||
Legal Entity authorized to submit on behalf of the copyright owner. For
|
||||
the purposes of this definition, "submitted" means any form of electronic,
|
||||
verbal, or written communication sent to the Licensor or its
|
||||
representatives, including but not limited to communication on electronic
|
||||
mailing lists, source code control systems, and issue tracking systems that
|
||||
are managed by, or on behalf of, the Licensor for the purpose of discussing
|
||||
and improving the Work, but excluding communication that is conspicuously
|
||||
marked or otherwise designated in writing by the copyright owner as "Not
|
||||
a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on
|
||||
behalf of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this
|
||||
License, each Contributor hereby grants to You a perpetual, worldwide,
|
||||
non-exclusive, no-charge, royalty-free, irrevocable copyright license to
|
||||
reproduce, prepare Derivative Works of, publicly display, publicly perform,
|
||||
sublicense, and distribute the Work and such Derivative Works in Source or
|
||||
Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this
|
||||
License, each Contributor hereby grants to You a perpetual, worldwide,
|
||||
non-exclusive, no-charge, royalty-free, irrevocable (except as stated in
|
||||
this section) patent license to make, have made, use, offer to sell, sell,
|
||||
import, and otherwise transfer the Work, where such license applies only to
|
||||
those patent claims licensable by such Contributor that are necessarily
|
||||
infringed by their Contribution(s) alone or by combination of their
|
||||
Contribution(s) with the Work to which such Contribution(s) was submitted.
|
||||
If You institute patent litigation against any entity (including a cross-claim
|
||||
or counterclaim in a lawsuit) alleging that the Work or a Contribution
|
||||
incorporated within the Work constitutes direct or contributory patent
|
||||
infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or
|
||||
Derivative Works thereof in any medium, with or without modifications, and
|
||||
in Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
You must cause any modified files to carry prominent notices stating that
|
||||
You changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You
|
||||
distribute, all copyright, patent, trademark, and attribution notices
|
||||
from the Source form of the Work, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution,
|
||||
then any Derivative Works that You distribute must include a readable
|
||||
copy of the attribution notices contained within such NOTICE file, excluding
|
||||
those notices that do not pertain to any part of the Derivative Works, in
|
||||
at least one of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or documentation, if
|
||||
provided along with the Derivative Works; or, within a display generated by
|
||||
the Derivative Works, if and wherever such third-party notices normally
|
||||
appear. The contents of the NOTICE file are for informational purposes
|
||||
only and do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside or as
|
||||
an addendum to the NOTICE text from the Work, provided that such additional
|
||||
attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a
|
||||
whole, provided Your use, reproduction, and distribution of the Work otherwise
|
||||
complies with the conditions stated in this License.
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any
|
||||
Contribution intentionally submitted for inclusion in the Work by You to the
|
||||
Licensor shall be under the terms and conditions of this License, without any
|
||||
additional terms or conditions. Notwithstanding the above, nothing herein
|
||||
shall supersede or modify the terms of any separate license agreement you
|
||||
may have executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names,
|
||||
trademarks, service marks, or product names of the Licensor, except as
|
||||
required for reasonable and customary use in describing the origin of the
|
||||
Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to
|
||||
in writing, Licensor provides the Work (and each Contributor provides its
|
||||
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
||||
ANY KIND, either express or implied, including, without limitation, any
|
||||
warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining
|
||||
the appropriateness of using or redistributing the Work and assume any risks
|
||||
associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether in
|
||||
tort (including negligence), contract, or otherwise, unless required by
|
||||
applicable law (such as deliberate and grossly negligent acts) or agreed to
|
||||
in writing, shall any Contributor be liable to You for damages, including
|
||||
any direct, indirect, special, incidental, or consequential damages of any
|
||||
character arising as a result of this License or out of the use or inability
|
||||
to use the Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all other
|
||||
commercial damages or losses), even if such Contributor has been advised
|
||||
of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the
|
||||
Work or Derivative Works thereof, You may choose to offer, and charge a
|
||||
fee for, acceptance of support, warranty, indemnity, or other liability
|
||||
obligations and/or rights consistent with this License. However, in accepting
|
||||
such obligations, You may act only on Your own behalf and on Your sole
|
||||
responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any
|
||||
liability incurred by, or claims asserted against, such Contributor by
|
||||
reason of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
|
@ -1,686 +0,0 @@
|
|||
// Copyright 2009 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a fork of the AOSP project ETC1 codec. The original code can be found
|
||||
// at the following web site:
|
||||
// https://android.googlesource.com/platform/frameworks/native/+/master/opengl/include/ETC1/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "etc1.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
/* From http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
|
||||
|
||||
The number of bits that represent a 4x4 texel block is 64 bits if
|
||||
<internalformat> is given by ETC1_RGB8_OES.
|
||||
|
||||
The data for a block is a number of bytes,
|
||||
|
||||
{q0, q1, q2, q3, q4, q5, q6, q7}
|
||||
|
||||
where byte q0 is located at the lowest memory address and q7 at
|
||||
the highest. The 64 bits specifying the block is then represented
|
||||
by the following 64 bit integer:
|
||||
|
||||
int64bit = 256*(256*(256*(256*(256*(256*(256*q0+q1)+q2)+q3)+q4)+q5)+q6)+q7;
|
||||
|
||||
ETC1_RGB8_OES:
|
||||
|
||||
a) bit layout in bits 63 through 32 if diffbit = 0
|
||||
|
||||
63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48
|
||||
-----------------------------------------------
|
||||
| base col1 | base col2 | base col1 | base col2 |
|
||||
| R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)|
|
||||
-----------------------------------------------
|
||||
|
||||
47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
|
||||
---------------------------------------------------
|
||||
| base col1 | base col2 | table | table |diff|flip|
|
||||
| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
|
||||
---------------------------------------------------
|
||||
|
||||
|
||||
b) bit layout in bits 63 through 32 if diffbit = 1
|
||||
|
||||
63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48
|
||||
-----------------------------------------------
|
||||
| base col1 | dcol 2 | base col1 | dcol 2 |
|
||||
| R1' (5 bits) | dR2 | G1' (5 bits) | dG2 |
|
||||
-----------------------------------------------
|
||||
|
||||
47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
|
||||
---------------------------------------------------
|
||||
| base col 1 | dcol 2 | table | table |diff|flip|
|
||||
| B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
|
||||
---------------------------------------------------
|
||||
|
||||
|
||||
c) bit layout in bits 31 through 0 (in both cases)
|
||||
|
||||
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
|
||||
-----------------------------------------------
|
||||
| most significant pixel index bits |
|
||||
| p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a|
|
||||
-----------------------------------------------
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
--------------------------------------------------
|
||||
| least significant pixel index bits |
|
||||
| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
|
||||
--------------------------------------------------
|
||||
|
||||
|
||||
Add table 3.17.2: Intensity modifier sets for ETC1 compressed textures:
|
||||
|
||||
table codeword modifier table
|
||||
------------------ ----------------------
|
||||
0 -8 -2 2 8
|
||||
1 -17 -5 5 17
|
||||
2 -29 -9 9 29
|
||||
3 -42 -13 13 42
|
||||
4 -60 -18 18 60
|
||||
5 -80 -24 24 80
|
||||
6 -106 -33 33 106
|
||||
7 -183 -47 47 183
|
||||
|
||||
|
||||
Add table 3.17.3 Mapping from pixel index values to modifier values for
|
||||
ETC1 compressed textures:
|
||||
|
||||
pixel index value
|
||||
---------------
|
||||
msb lsb resulting modifier value
|
||||
----- ----- -------------------------
|
||||
1 1 -b (large negative value)
|
||||
1 0 -a (small negative value)
|
||||
0 0 a (small positive value)
|
||||
0 1 b (large positive value)
|
||||
|
||||
|
||||
*/
|
||||
|
||||
static const int kModifierTable[] = {
|
||||
/* 0 */2, 8, -2, -8,
|
||||
/* 1 */5, 17, -5, -17,
|
||||
/* 2 */9, 29, -9, -29,
|
||||
/* 3 */13, 42, -13, -42,
|
||||
/* 4 */18, 60, -18, -60,
|
||||
/* 5 */24, 80, -24, -80,
|
||||
/* 6 */33, 106, -33, -106,
|
||||
/* 7 */47, 183, -47, -183 };
|
||||
|
||||
static const int kLookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 };
|
||||
|
||||
static inline etc1_byte clamp(int x) {
|
||||
return (etc1_byte) (x >= 0 ? (x < 255 ? x : 255) : 0);
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert4To8(int b) {
|
||||
int c = b & 0xf;
|
||||
return (c << 4) | c;
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert5To8(int b) {
|
||||
int c = b & 0x1f;
|
||||
return (c << 3) | (c >> 2);
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert6To8(int b) {
|
||||
int c = b & 0x3f;
|
||||
return (c << 2) | (c >> 4);
|
||||
}
|
||||
|
||||
static
|
||||
inline int divideBy255(int d) {
|
||||
return (d + 128 + (d >> 8)) >> 8;
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert8To4(int b) {
|
||||
int c = b & 0xff;
|
||||
return divideBy255(c * 15);
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert8To5(int b) {
|
||||
int c = b & 0xff;
|
||||
return divideBy255(c * 31);
|
||||
}
|
||||
|
||||
static
|
||||
inline int convertDiff(int base, int diff) {
|
||||
return convert5To8((0x1f & base) + kLookup[0x7 & diff]);
|
||||
}
|
||||
|
||||
static
|
||||
void decode_subblock(etc1_byte* pOut, int r, int g, int b, const int* table,
|
||||
etc1_uint32 low, bool second, bool flipped) {
|
||||
int baseX = 0;
|
||||
int baseY = 0;
|
||||
if (second) {
|
||||
if (flipped) {
|
||||
baseY = 2;
|
||||
} else {
|
||||
baseX = 2;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int x, y;
|
||||
if (flipped) {
|
||||
x = baseX + (i >> 1);
|
||||
y = baseY + (i & 1);
|
||||
} else {
|
||||
x = baseX + (i >> 2);
|
||||
y = baseY + (i & 3);
|
||||
}
|
||||
int k = y + (x * 4);
|
||||
int offset = ((low >> k) & 1) | ((low >> (k + 15)) & 2);
|
||||
int delta = table[offset];
|
||||
etc1_byte* q = pOut + 3 * (x + 4 * y);
|
||||
*q++ = clamp(r + delta);
|
||||
*q++ = clamp(g + delta);
|
||||
*q++ = clamp(b + delta);
|
||||
}
|
||||
}
|
||||
|
||||
// Input is an ETC1 compressed version of the data.
|
||||
// Output is a 4 x 4 square of 3-byte pixels in form R, G, B
|
||||
|
||||
void etc1_decode_block(const etc1_byte* pIn, etc1_byte* pOut) {
|
||||
etc1_uint32 high = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3];
|
||||
etc1_uint32 low = (pIn[4] << 24) | (pIn[5] << 16) | (pIn[6] << 8) | pIn[7];
|
||||
int r1, r2, g1, g2, b1, b2;
|
||||
if (high & 2) {
|
||||
// differential
|
||||
int rBase = high >> 27;
|
||||
int gBase = high >> 19;
|
||||
int bBase = high >> 11;
|
||||
r1 = convert5To8(rBase);
|
||||
r2 = convertDiff(rBase, high >> 24);
|
||||
g1 = convert5To8(gBase);
|
||||
g2 = convertDiff(gBase, high >> 16);
|
||||
b1 = convert5To8(bBase);
|
||||
b2 = convertDiff(bBase, high >> 8);
|
||||
} else {
|
||||
// not differential
|
||||
r1 = convert4To8(high >> 28);
|
||||
r2 = convert4To8(high >> 24);
|
||||
g1 = convert4To8(high >> 20);
|
||||
g2 = convert4To8(high >> 16);
|
||||
b1 = convert4To8(high >> 12);
|
||||
b2 = convert4To8(high >> 8);
|
||||
}
|
||||
int tableIndexA = 7 & (high >> 5);
|
||||
int tableIndexB = 7 & (high >> 2);
|
||||
const int* tableA = kModifierTable + tableIndexA * 4;
|
||||
const int* tableB = kModifierTable + tableIndexB * 4;
|
||||
bool flipped = (high & 1) != 0;
|
||||
decode_subblock(pOut, r1, g1, b1, tableA, low, false, flipped);
|
||||
decode_subblock(pOut, r2, g2, b2, tableB, low, true, flipped);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
etc1_uint32 high;
|
||||
etc1_uint32 low;
|
||||
etc1_uint32 score; // Lower is more accurate
|
||||
} etc_compressed;
|
||||
|
||||
static
|
||||
inline void take_best(etc_compressed* a, const etc_compressed* b) {
|
||||
if (a->score > b->score) {
|
||||
*a = *b;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void etc_average_colors_subblock(const etc1_byte* pIn, etc1_uint32 inMask,
|
||||
etc1_byte* pColors, bool flipped, bool second) {
|
||||
int r = 0;
|
||||
int g = 0;
|
||||
int b = 0;
|
||||
|
||||
if (flipped) {
|
||||
int by = 0;
|
||||
if (second) {
|
||||
by = 2;
|
||||
}
|
||||
for (int y = 0; y < 2; y++) {
|
||||
int yy = by + y;
|
||||
for (int x = 0; x < 4; x++) {
|
||||
int i = x + 4 * yy;
|
||||
if (inMask & (1 << i)) {
|
||||
const etc1_byte* p = pIn + i * 3;
|
||||
r += *(p++);
|
||||
g += *(p++);
|
||||
b += *(p++);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int bx = 0;
|
||||
if (second) {
|
||||
bx = 2;
|
||||
}
|
||||
for (int y = 0; y < 4; y++) {
|
||||
for (int x = 0; x < 2; x++) {
|
||||
int xx = bx + x;
|
||||
int i = xx + 4 * y;
|
||||
if (inMask & (1 << i)) {
|
||||
const etc1_byte* p = pIn + i * 3;
|
||||
r += *(p++);
|
||||
g += *(p++);
|
||||
b += *(p++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pColors[0] = (etc1_byte)((r + 4) >> 3);
|
||||
pColors[1] = (etc1_byte)((g + 4) >> 3);
|
||||
pColors[2] = (etc1_byte)((b + 4) >> 3);
|
||||
}
|
||||
|
||||
static
|
||||
inline int square(int x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
static etc1_uint32 chooseModifier(const etc1_byte* pBaseColors,
|
||||
const etc1_byte* pIn, etc1_uint32 *pLow, int bitIndex,
|
||||
const int* pModifierTable) {
|
||||
etc1_uint32 bestScore = ~0;
|
||||
int bestIndex = 0;
|
||||
int pixelR = pIn[0];
|
||||
int pixelG = pIn[1];
|
||||
int pixelB = pIn[2];
|
||||
int r = pBaseColors[0];
|
||||
int g = pBaseColors[1];
|
||||
int b = pBaseColors[2];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int modifier = pModifierTable[i];
|
||||
int decodedG = clamp(g + modifier);
|
||||
etc1_uint32 score = (etc1_uint32) (6 * square(decodedG - pixelG));
|
||||
if (score >= bestScore) {
|
||||
continue;
|
||||
}
|
||||
int decodedR = clamp(r + modifier);
|
||||
score += (etc1_uint32) (3 * square(decodedR - pixelR));
|
||||
if (score >= bestScore) {
|
||||
continue;
|
||||
}
|
||||
int decodedB = clamp(b + modifier);
|
||||
score += (etc1_uint32) square(decodedB - pixelB);
|
||||
if (score < bestScore) {
|
||||
bestScore = score;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
etc1_uint32 lowMask = (((bestIndex >> 1) << 16) | (bestIndex & 1))
|
||||
<< bitIndex;
|
||||
*pLow |= lowMask;
|
||||
return bestScore;
|
||||
}
|
||||
|
||||
static
|
||||
void etc_encode_subblock_helper(const etc1_byte* pIn, etc1_uint32 inMask,
|
||||
etc_compressed* pCompressed, bool flipped, bool second,
|
||||
const etc1_byte* pBaseColors, const int* pModifierTable) {
|
||||
int score = pCompressed->score;
|
||||
if (flipped) {
|
||||
int by = 0;
|
||||
if (second) {
|
||||
by = 2;
|
||||
}
|
||||
for (int y = 0; y < 2; y++) {
|
||||
int yy = by + y;
|
||||
for (int x = 0; x < 4; x++) {
|
||||
int i = x + 4 * yy;
|
||||
if (inMask & (1 << i)) {
|
||||
score += chooseModifier(pBaseColors, pIn + i * 3,
|
||||
&pCompressed->low, yy + x * 4, pModifierTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int bx = 0;
|
||||
if (second) {
|
||||
bx = 2;
|
||||
}
|
||||
for (int y = 0; y < 4; y++) {
|
||||
for (int x = 0; x < 2; x++) {
|
||||
int xx = bx + x;
|
||||
int i = xx + 4 * y;
|
||||
if (inMask & (1 << i)) {
|
||||
score += chooseModifier(pBaseColors, pIn + i * 3,
|
||||
&pCompressed->low, y + xx * 4, pModifierTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pCompressed->score = score;
|
||||
}
|
||||
|
||||
static bool inRange4bitSigned(int color) {
|
||||
return color >= -4 && color <= 3;
|
||||
}
|
||||
|
||||
static void etc_encodeBaseColors(etc1_byte* pBaseColors,
|
||||
const etc1_byte* pColors, etc_compressed* pCompressed) {
|
||||
int r1, g1, b1, r2, g2, b2; // 8 bit base colors for sub-blocks
|
||||
bool differential;
|
||||
{
|
||||
int r51 = convert8To5(pColors[0]);
|
||||
int g51 = convert8To5(pColors[1]);
|
||||
int b51 = convert8To5(pColors[2]);
|
||||
int r52 = convert8To5(pColors[3]);
|
||||
int g52 = convert8To5(pColors[4]);
|
||||
int b52 = convert8To5(pColors[5]);
|
||||
|
||||
r1 = convert5To8(r51);
|
||||
g1 = convert5To8(g51);
|
||||
b1 = convert5To8(b51);
|
||||
|
||||
int dr = r52 - r51;
|
||||
int dg = g52 - g51;
|
||||
int db = b52 - b51;
|
||||
|
||||
differential = inRange4bitSigned(dr) && inRange4bitSigned(dg)
|
||||
&& inRange4bitSigned(db);
|
||||
if (differential) {
|
||||
r2 = convert5To8(r51 + dr);
|
||||
g2 = convert5To8(g51 + dg);
|
||||
b2 = convert5To8(b51 + db);
|
||||
pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19)
|
||||
| ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!differential) {
|
||||
int r41 = convert8To4(pColors[0]);
|
||||
int g41 = convert8To4(pColors[1]);
|
||||
int b41 = convert8To4(pColors[2]);
|
||||
int r42 = convert8To4(pColors[3]);
|
||||
int g42 = convert8To4(pColors[4]);
|
||||
int b42 = convert8To4(pColors[5]);
|
||||
r1 = convert4To8(r41);
|
||||
g1 = convert4To8(g41);
|
||||
b1 = convert4To8(b41);
|
||||
r2 = convert4To8(r42);
|
||||
g2 = convert4To8(g42);
|
||||
b2 = convert4To8(b42);
|
||||
pCompressed->high |= (r41 << 28) | (r42 << 24) | (g41 << 20) | (g42
|
||||
<< 16) | (b41 << 12) | (b42 << 8);
|
||||
}
|
||||
pBaseColors[0] = r1;
|
||||
pBaseColors[1] = g1;
|
||||
pBaseColors[2] = b1;
|
||||
pBaseColors[3] = r2;
|
||||
pBaseColors[4] = g2;
|
||||
pBaseColors[5] = b2;
|
||||
}
|
||||
|
||||
static
|
||||
void etc_encode_block_helper(const etc1_byte* pIn, etc1_uint32 inMask,
|
||||
const etc1_byte* pColors, etc_compressed* pCompressed, bool flipped) {
|
||||
pCompressed->score = ~0;
|
||||
pCompressed->high = (flipped ? 1 : 0);
|
||||
pCompressed->low = 0;
|
||||
|
||||
etc1_byte pBaseColors[6];
|
||||
|
||||
etc_encodeBaseColors(pBaseColors, pColors, pCompressed);
|
||||
|
||||
int originalHigh = pCompressed->high;
|
||||
|
||||
const int* pModifierTable = kModifierTable;
|
||||
for (int i = 0; i < 8; i++, pModifierTable += 4) {
|
||||
etc_compressed temp;
|
||||
temp.score = 0;
|
||||
temp.high = originalHigh | (i << 5);
|
||||
temp.low = 0;
|
||||
etc_encode_subblock_helper(pIn, inMask, &temp, flipped, false,
|
||||
pBaseColors, pModifierTable);
|
||||
take_best(pCompressed, &temp);
|
||||
}
|
||||
pModifierTable = kModifierTable;
|
||||
etc_compressed firstHalf = *pCompressed;
|
||||
for (int i = 0; i < 8; i++, pModifierTable += 4) {
|
||||
etc_compressed temp;
|
||||
temp.score = firstHalf.score;
|
||||
temp.high = firstHalf.high | (i << 2);
|
||||
temp.low = firstHalf.low;
|
||||
etc_encode_subblock_helper(pIn, inMask, &temp, flipped, true,
|
||||
pBaseColors + 3, pModifierTable);
|
||||
if (i == 0) {
|
||||
*pCompressed = temp;
|
||||
} else {
|
||||
take_best(pCompressed, &temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void writeBigEndian(etc1_byte* pOut, etc1_uint32 d) {
|
||||
pOut[0] = (etc1_byte)(d >> 24);
|
||||
pOut[1] = (etc1_byte)(d >> 16);
|
||||
pOut[2] = (etc1_byte)(d >> 8);
|
||||
pOut[3] = (etc1_byte) d;
|
||||
}
|
||||
|
||||
// Input is a 4 x 4 square of 3-byte pixels in form R, G, B
|
||||
// inmask is a 16-bit mask where bit (1 << (x + y * 4)) tells whether the corresponding (x,y)
|
||||
// pixel is valid or not. Invalid pixel color values are ignored when compressing.
|
||||
// Output is an ETC1 compressed version of the data.
|
||||
|
||||
void etc1_encode_block(const etc1_byte* pIn, etc1_uint32 inMask,
|
||||
etc1_byte* pOut) {
|
||||
etc1_byte colors[6];
|
||||
etc1_byte flippedColors[6];
|
||||
etc_average_colors_subblock(pIn, inMask, colors, false, false);
|
||||
etc_average_colors_subblock(pIn, inMask, colors + 3, false, true);
|
||||
etc_average_colors_subblock(pIn, inMask, flippedColors, true, false);
|
||||
etc_average_colors_subblock(pIn, inMask, flippedColors + 3, true, true);
|
||||
|
||||
etc_compressed a, b;
|
||||
etc_encode_block_helper(pIn, inMask, colors, &a, false);
|
||||
etc_encode_block_helper(pIn, inMask, flippedColors, &b, true);
|
||||
take_best(&a, &b);
|
||||
writeBigEndian(pOut, a.high);
|
||||
writeBigEndian(pOut + 4, a.low);
|
||||
}
|
||||
|
||||
// Return the size of the encoded image data (does not include size of PKM header).
|
||||
|
||||
etc1_uint32 etc1_get_encoded_data_size(etc1_uint32 width, etc1_uint32 height) {
|
||||
return (((width + 3) & ~3) * ((height + 3) & ~3)) >> 1;
|
||||
}
|
||||
|
||||
// Encode an entire image.
|
||||
// pIn - pointer to the image data. Formatted such that the Red component of
|
||||
// pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset;
|
||||
// pOut - pointer to encoded data. Must be large enough to store entire encoded image.
|
||||
|
||||
int etc1_encode_image(const etc1_byte* pIn, etc1_uint32 width, etc1_uint32 height,
|
||||
etc1_uint32 pixelSize, etc1_uint32 stride, etc1_byte* pOut) {
|
||||
if (pixelSize < 2 || pixelSize > 4) {
|
||||
return -1;
|
||||
}
|
||||
static const unsigned short kYMask[] = { 0x0, 0xf, 0xff, 0xfff, 0xffff };
|
||||
static const unsigned short kXMask[] = { 0x0, 0x1111, 0x3333, 0x7777,
|
||||
0xffff };
|
||||
etc1_byte block[ETC1_DECODED_BLOCK_SIZE];
|
||||
etc1_byte encoded[ETC1_ENCODED_BLOCK_SIZE];
|
||||
|
||||
etc1_uint32 encodedWidth = (width + 3) & ~3;
|
||||
etc1_uint32 encodedHeight = (height + 3) & ~3;
|
||||
|
||||
for (etc1_uint32 y = 0; y < encodedHeight; y += 4) {
|
||||
etc1_uint32 yEnd = height - y;
|
||||
if (yEnd > 4) {
|
||||
yEnd = 4;
|
||||
}
|
||||
int ymask = kYMask[yEnd];
|
||||
for (etc1_uint32 x = 0; x < encodedWidth; x += 4) {
|
||||
etc1_uint32 xEnd = width - x;
|
||||
if (xEnd > 4) {
|
||||
xEnd = 4;
|
||||
}
|
||||
int mask = ymask & kXMask[xEnd];
|
||||
for (etc1_uint32 cy = 0; cy < yEnd; cy++) {
|
||||
etc1_byte* q = block + (cy * 4) * 3;
|
||||
const etc1_byte* p = pIn + pixelSize * x + stride * (y + cy);
|
||||
if (pixelSize >= 3) {
|
||||
for (etc1_uint32 cx = 0; cx < xEnd; cx++) {
|
||||
memcpy(q, p, 3);
|
||||
q += 3;
|
||||
p += pixelSize;
|
||||
}
|
||||
} else {
|
||||
for (etc1_uint32 cx = 0; cx < xEnd; cx++) {
|
||||
int pixel = (p[1] << 8) | p[0];
|
||||
*q++ = convert5To8(pixel >> 11);
|
||||
*q++ = convert6To8(pixel >> 5);
|
||||
*q++ = convert5To8(pixel);
|
||||
p += pixelSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
etc1_encode_block(block, mask, encoded);
|
||||
memcpy(pOut, encoded, sizeof(encoded));
|
||||
pOut += sizeof(encoded);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Decode an entire image.
|
||||
// pIn - pointer to encoded data.
|
||||
// pOut - pointer to the image data. Will be written such that the Red component of
|
||||
// pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset. Must be
|
||||
// large enough to store entire image.
|
||||
|
||||
|
||||
int etc1_decode_image(const etc1_byte* pIn, etc1_byte* pOut,
|
||||
etc1_uint32 width, etc1_uint32 height,
|
||||
etc1_uint32 pixelSize, etc1_uint32 stride) {
|
||||
if (pixelSize < 2 || pixelSize > 4) {
|
||||
return -1;
|
||||
}
|
||||
etc1_byte block[ETC1_DECODED_BLOCK_SIZE];
|
||||
|
||||
etc1_uint32 encodedWidth = (width + 3) & ~3;
|
||||
etc1_uint32 encodedHeight = (height + 3) & ~3;
|
||||
|
||||
for (etc1_uint32 y = 0; y < encodedHeight; y += 4) {
|
||||
etc1_uint32 yEnd = height - y;
|
||||
if (yEnd > 4) {
|
||||
yEnd = 4;
|
||||
}
|
||||
for (etc1_uint32 x = 0; x < encodedWidth; x += 4) {
|
||||
etc1_uint32 xEnd = width - x;
|
||||
if (xEnd > 4) {
|
||||
xEnd = 4;
|
||||
}
|
||||
etc1_decode_block(pIn, block);
|
||||
pIn += ETC1_ENCODED_BLOCK_SIZE;
|
||||
for (etc1_uint32 cy = 0; cy < yEnd; cy++) {
|
||||
const etc1_byte* q = block + (cy * 4) * 3;
|
||||
etc1_byte* p = pOut + pixelSize * x + stride * (y + cy);
|
||||
if (pixelSize >= 3) {
|
||||
for (etc1_uint32 cx = 0; cx < xEnd; cx++) {
|
||||
memcpy(p, q, 3);
|
||||
q += 3;
|
||||
p += pixelSize;
|
||||
}
|
||||
} else {
|
||||
for (etc1_uint32 cx = 0; cx < xEnd; cx++) {
|
||||
etc1_byte r = *q++;
|
||||
etc1_byte g = *q++;
|
||||
etc1_byte b = *q++;
|
||||
etc1_uint32 pixel = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
|
||||
*p++ = (etc1_byte) pixel;
|
||||
*p++ = (etc1_byte) (pixel >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char kMagic[] = { 'P', 'K', 'M', ' ', '1', '0' };
|
||||
|
||||
static const etc1_uint32 ETC1_PKM_FORMAT_OFFSET = 6;
|
||||
static const etc1_uint32 ETC1_PKM_ENCODED_WIDTH_OFFSET = 8;
|
||||
static const etc1_uint32 ETC1_PKM_ENCODED_HEIGHT_OFFSET = 10;
|
||||
static const etc1_uint32 ETC1_PKM_WIDTH_OFFSET = 12;
|
||||
static const etc1_uint32 ETC1_PKM_HEIGHT_OFFSET = 14;
|
||||
|
||||
static const etc1_uint32 ETC1_RGB_NO_MIPMAPS = 0;
|
||||
|
||||
static void writeBEUint16(etc1_byte* pOut, etc1_uint32 data) {
|
||||
pOut[0] = (etc1_byte) (data >> 8);
|
||||
pOut[1] = (etc1_byte) data;
|
||||
}
|
||||
|
||||
static etc1_uint32 readBEUint16(const etc1_byte* pIn) {
|
||||
return (pIn[0] << 8) | pIn[1];
|
||||
}
|
||||
|
||||
// Format a PKM header
|
||||
|
||||
void etc1_pkm_format_header(etc1_byte* pHeader, etc1_uint32 width, etc1_uint32 height) {
|
||||
memcpy(pHeader, kMagic, sizeof(kMagic));
|
||||
etc1_uint32 encodedWidth = (width + 3) & ~3;
|
||||
etc1_uint32 encodedHeight = (height + 3) & ~3;
|
||||
writeBEUint16(pHeader + ETC1_PKM_FORMAT_OFFSET, ETC1_RGB_NO_MIPMAPS);
|
||||
writeBEUint16(pHeader + ETC1_PKM_ENCODED_WIDTH_OFFSET, encodedWidth);
|
||||
writeBEUint16(pHeader + ETC1_PKM_ENCODED_HEIGHT_OFFSET, encodedHeight);
|
||||
writeBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET, width);
|
||||
writeBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET, height);
|
||||
}
|
||||
|
||||
// Check if a PKM header is correctly formatted.
|
||||
|
||||
etc1_bool etc1_pkm_is_valid(const etc1_byte* pHeader) {
|
||||
if (memcmp(pHeader, kMagic, sizeof(kMagic))) {
|
||||
return false;
|
||||
}
|
||||
etc1_uint32 format = readBEUint16(pHeader + ETC1_PKM_FORMAT_OFFSET);
|
||||
etc1_uint32 encodedWidth = readBEUint16(pHeader + ETC1_PKM_ENCODED_WIDTH_OFFSET);
|
||||
etc1_uint32 encodedHeight = readBEUint16(pHeader + ETC1_PKM_ENCODED_HEIGHT_OFFSET);
|
||||
etc1_uint32 width = readBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET);
|
||||
etc1_uint32 height = readBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET);
|
||||
return format == ETC1_RGB_NO_MIPMAPS &&
|
||||
encodedWidth >= width && encodedWidth - width < 4 &&
|
||||
encodedHeight >= height && encodedHeight - height < 4;
|
||||
}
|
||||
|
||||
// Read the image width from a PKM header
|
||||
|
||||
etc1_uint32 etc1_pkm_get_width(const etc1_byte* pHeader) {
|
||||
return readBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET);
|
||||
}
|
||||
|
||||
// Read the image height from a PKM header
|
||||
|
||||
etc1_uint32 etc1_pkm_get_height(const etc1_byte* pHeader){
|
||||
return readBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET);
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
// Copyright 2009 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a fork of the AOSP project ETC1 codec. The original code can be found
|
||||
// at the following web site:
|
||||
// https://android.googlesource.com/platform/frameworks/native/+/master/opengl/libs/ETC1/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __etc1_h__
|
||||
#define __etc1_h__
|
||||
|
||||
#define ETC1_ENCODED_BLOCK_SIZE 8
|
||||
#define ETC1_DECODED_BLOCK_SIZE 48
|
||||
|
||||
#ifndef ETC1_RGB8_OES
|
||||
#define ETC1_RGB8_OES 0x8D64
|
||||
#endif
|
||||
|
||||
typedef unsigned char etc1_byte;
|
||||
typedef int etc1_bool;
|
||||
typedef unsigned int etc1_uint32;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Encode a block of pixels.
|
||||
//
|
||||
// pIn is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
|
||||
// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
|
||||
// value of pixel (x, y).
|
||||
//
|
||||
// validPixelMask is a 16-bit mask where bit (1 << (x + y * 4)) indicates whether
|
||||
// the corresponding (x,y) pixel is valid. Invalid pixel color values are ignored when compressing.
|
||||
//
|
||||
// pOut is an ETC1 compressed version of the data.
|
||||
|
||||
void etc1_encode_block(const etc1_byte* pIn, etc1_uint32 validPixelMask, etc1_byte* pOut);
|
||||
|
||||
// Decode a block of pixels.
|
||||
//
|
||||
// pIn is an ETC1 compressed version of the data.
|
||||
//
|
||||
// pOut is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
|
||||
// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
|
||||
// value of pixel (x, y).
|
||||
|
||||
void etc1_decode_block(const etc1_byte* pIn, etc1_byte* pOut);
|
||||
|
||||
// Return the size of the encoded image data (does not include size of PKM header).
|
||||
|
||||
etc1_uint32 etc1_get_encoded_data_size(etc1_uint32 width, etc1_uint32 height);
|
||||
|
||||
// Encode an entire image.
|
||||
// pIn - pointer to the image data. Formatted such that
|
||||
// pixel (x,y) is at pIn + pixelSize * x + stride * y;
|
||||
// pOut - pointer to encoded data. Must be large enough to store entire encoded image.
|
||||
// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image.
|
||||
// returns non-zero if there is an error.
|
||||
|
||||
int etc1_encode_image(const etc1_byte* pIn, etc1_uint32 width, etc1_uint32 height,
|
||||
etc1_uint32 pixelSize, etc1_uint32 stride, etc1_byte* pOut);
|
||||
|
||||
// Decode an entire image.
|
||||
// pIn - pointer to encoded data.
|
||||
// pOut - pointer to the image data. Will be written such that
|
||||
// pixel (x,y) is at pIn + pixelSize * x + stride * y. Must be
|
||||
// large enough to store entire image.
|
||||
// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image.
|
||||
// returns non-zero if there is an error.
|
||||
|
||||
int etc1_decode_image(const etc1_byte* pIn, etc1_byte* pOut,
|
||||
etc1_uint32 width, etc1_uint32 height,
|
||||
etc1_uint32 pixelSize, etc1_uint32 stride);
|
||||
|
||||
// Size of a PKM header, in bytes.
|
||||
|
||||
#define ETC_PKM_HEADER_SIZE 16
|
||||
|
||||
// Format a PKM header
|
||||
|
||||
void etc1_pkm_format_header(etc1_byte* pHeader, etc1_uint32 width, etc1_uint32 height);
|
||||
|
||||
// Check if a PKM header is correctly formatted.
|
||||
|
||||
etc1_bool etc1_pkm_is_valid(const etc1_byte* pHeader);
|
||||
|
||||
// Read the image width from a PKM header
|
||||
|
||||
etc1_uint32 etc1_pkm_get_width(const etc1_byte* pHeader);
|
||||
|
||||
// Read the image height from a PKM header
|
||||
|
||||
etc1_uint32 etc1_pkm_get_height(const etc1_byte* pHeader);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,24 +0,0 @@
|
|||
Copyright (c) 2013, Bartosz Taudul <wolf.pld@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,90 +0,0 @@
|
|||
#ifndef __DARKRL__MATH_HPP__
|
||||
#define __DARKRL__MATH_HPP__
|
||||
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
template<typename T>
|
||||
inline T AlignPOT( T val )
|
||||
{
|
||||
if( val == 0 ) return 1;
|
||||
val--;
|
||||
for( unsigned int i=1; i<sizeof( T ) * 8; i <<= 1 )
|
||||
{
|
||||
val |= val >> i;
|
||||
}
|
||||
return val + 1;
|
||||
}
|
||||
|
||||
inline int CountSetBits( uint32 val )
|
||||
{
|
||||
val -= ( val >> 1 ) & 0x55555555;
|
||||
val = ( ( val >> 2 ) & 0x33333333 ) + ( val & 0x33333333 );
|
||||
val = ( ( val >> 4 ) + val ) & 0x0f0f0f0f;
|
||||
val += val >> 8;
|
||||
val += val >> 16;
|
||||
return val & 0x0000003f;
|
||||
}
|
||||
|
||||
inline int CountLeadingZeros( uint32 val )
|
||||
{
|
||||
val |= val >> 1;
|
||||
val |= val >> 2;
|
||||
val |= val >> 4;
|
||||
val |= val >> 8;
|
||||
val |= val >> 16;
|
||||
return 32 - CountSetBits( val );
|
||||
}
|
||||
|
||||
inline float sRGB2linear( float v )
|
||||
{
|
||||
const float a = 0.055f;
|
||||
if( v <= 0.04045f )
|
||||
{
|
||||
return v / 12.92f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return powf( ( v + a ) / ( 1 + a ), 2.4f );
|
||||
}
|
||||
}
|
||||
|
||||
inline float linear2sRGB( float v )
|
||||
{
|
||||
const float a = 0.055f;
|
||||
if( v <= 0.0031308f )
|
||||
{
|
||||
return 12.92f * v;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( 1 + a ) * pow( v, 1/2.4f ) - a;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T SmoothStep( T x )
|
||||
{
|
||||
return x*x*(3-2*x);
|
||||
}
|
||||
|
||||
inline uint8 clampu8( int32 val )
|
||||
{
|
||||
return std::min( std::max( 0, val ), 255 );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T sq( T val )
|
||||
{
|
||||
return val * val;
|
||||
}
|
||||
|
||||
static inline int mul8bit( int a, int b )
|
||||
{
|
||||
int t = a*b + 128;
|
||||
return ( t + ( t >> 8 ) ) >> 8;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||
#ifndef __PROCESSCOMMON_HPP__
|
||||
#define __PROCESSCOMMON_HPP__
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
template<class T>
|
||||
static size_t GetLeastError( const T* err, size_t num )
|
||||
{
|
||||
size_t idx = 0;
|
||||
for( size_t i=1; i<num; i++ )
|
||||
{
|
||||
if( err[i] < err[idx] )
|
||||
{
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
static uint64 FixByteOrder( uint64 d )
|
||||
{
|
||||
return ( ( d & 0x00000000FFFFFFFF ) ) |
|
||||
( ( d & 0xFF00000000000000 ) >> 24 ) |
|
||||
( ( d & 0x000000FF00000000 ) << 24 ) |
|
||||
( ( d & 0x00FF000000000000 ) >> 8 ) |
|
||||
( ( d & 0x0000FF0000000000 ) << 8 );
|
||||
}
|
||||
|
||||
template<class T, class S>
|
||||
static uint64 EncodeSelectors( uint64 d, const T terr[2][8], const S tsel[16][8], const uint32* id )
|
||||
{
|
||||
size_t tidx[2];
|
||||
tidx[0] = GetLeastError( terr[0], 8 );
|
||||
tidx[1] = GetLeastError( terr[1], 8 );
|
||||
|
||||
d |= tidx[0] << 26;
|
||||
d |= tidx[1] << 29;
|
||||
for( int i=0; i<16; i++ )
|
||||
{
|
||||
uint64 t = tsel[i][tidx[id[i]%2]];
|
||||
d |= ( t & 0x1 ) << ( i + 32 );
|
||||
d |= ( t & 0x2 ) << ( i + 47 );
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,719 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "Math.hpp"
|
||||
#include "ProcessCommon.hpp"
|
||||
#include "ProcessRGB.hpp"
|
||||
#include "Tables.hpp"
|
||||
#include "Types.hpp"
|
||||
#include "Vector.hpp"
|
||||
|
||||
#include <bx/endian.h>
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
# ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
# include <Windows.h>
|
||||
# else
|
||||
# include <x86intrin.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
typedef uint16 v4i[4];
|
||||
|
||||
void Average( const uint8* data, v4i* a )
|
||||
{
|
||||
#ifdef __SSE4_1__
|
||||
__m128i d0 = _mm_loadu_si128(((__m128i*)data) + 0);
|
||||
__m128i d1 = _mm_loadu_si128(((__m128i*)data) + 1);
|
||||
__m128i d2 = _mm_loadu_si128(((__m128i*)data) + 2);
|
||||
__m128i d3 = _mm_loadu_si128(((__m128i*)data) + 3);
|
||||
|
||||
__m128i d0l = _mm_unpacklo_epi8(d0, _mm_setzero_si128());
|
||||
__m128i d0h = _mm_unpackhi_epi8(d0, _mm_setzero_si128());
|
||||
__m128i d1l = _mm_unpacklo_epi8(d1, _mm_setzero_si128());
|
||||
__m128i d1h = _mm_unpackhi_epi8(d1, _mm_setzero_si128());
|
||||
__m128i d2l = _mm_unpacklo_epi8(d2, _mm_setzero_si128());
|
||||
__m128i d2h = _mm_unpackhi_epi8(d2, _mm_setzero_si128());
|
||||
__m128i d3l = _mm_unpacklo_epi8(d3, _mm_setzero_si128());
|
||||
__m128i d3h = _mm_unpackhi_epi8(d3, _mm_setzero_si128());
|
||||
|
||||
__m128i sum0 = _mm_add_epi16(d0l, d1l);
|
||||
__m128i sum1 = _mm_add_epi16(d0h, d1h);
|
||||
__m128i sum2 = _mm_add_epi16(d2l, d3l);
|
||||
__m128i sum3 = _mm_add_epi16(d2h, d3h);
|
||||
|
||||
__m128i sum0l = _mm_unpacklo_epi16(sum0, _mm_setzero_si128());
|
||||
__m128i sum0h = _mm_unpackhi_epi16(sum0, _mm_setzero_si128());
|
||||
__m128i sum1l = _mm_unpacklo_epi16(sum1, _mm_setzero_si128());
|
||||
__m128i sum1h = _mm_unpackhi_epi16(sum1, _mm_setzero_si128());
|
||||
__m128i sum2l = _mm_unpacklo_epi16(sum2, _mm_setzero_si128());
|
||||
__m128i sum2h = _mm_unpackhi_epi16(sum2, _mm_setzero_si128());
|
||||
__m128i sum3l = _mm_unpacklo_epi16(sum3, _mm_setzero_si128());
|
||||
__m128i sum3h = _mm_unpackhi_epi16(sum3, _mm_setzero_si128());
|
||||
|
||||
__m128i b0 = _mm_add_epi32(sum0l, sum0h);
|
||||
__m128i b1 = _mm_add_epi32(sum1l, sum1h);
|
||||
__m128i b2 = _mm_add_epi32(sum2l, sum2h);
|
||||
__m128i b3 = _mm_add_epi32(sum3l, sum3h);
|
||||
|
||||
__m128i a0 = _mm_srli_epi32(_mm_add_epi32(_mm_add_epi32(b2, b3), _mm_set1_epi32(4)), 3);
|
||||
__m128i a1 = _mm_srli_epi32(_mm_add_epi32(_mm_add_epi32(b0, b1), _mm_set1_epi32(4)), 3);
|
||||
__m128i a2 = _mm_srli_epi32(_mm_add_epi32(_mm_add_epi32(b1, b3), _mm_set1_epi32(4)), 3);
|
||||
__m128i a3 = _mm_srli_epi32(_mm_add_epi32(_mm_add_epi32(b0, b2), _mm_set1_epi32(4)), 3);
|
||||
|
||||
_mm_storeu_si128((__m128i*)&a[0], _mm_packus_epi32(_mm_shuffle_epi32(a0, _MM_SHUFFLE(3, 0, 1, 2)), _mm_shuffle_epi32(a1, _MM_SHUFFLE(3, 0, 1, 2))));
|
||||
_mm_storeu_si128((__m128i*)&a[2], _mm_packus_epi32(_mm_shuffle_epi32(a2, _MM_SHUFFLE(3, 0, 1, 2)), _mm_shuffle_epi32(a3, _MM_SHUFFLE(3, 0, 1, 2))));
|
||||
#else
|
||||
uint32 r[4];
|
||||
uint32 g[4];
|
||||
uint32 b[4];
|
||||
|
||||
memset(r, 0, sizeof(r));
|
||||
memset(g, 0, sizeof(g));
|
||||
memset(b, 0, sizeof(b));
|
||||
|
||||
for( int j=0; j<4; j++ )
|
||||
{
|
||||
for( int i=0; i<4; i++ )
|
||||
{
|
||||
int index = (j & 2) + (i >> 1);
|
||||
b[index] += *data++;
|
||||
g[index] += *data++;
|
||||
r[index] += *data++;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
a[0][0] = uint16( (r[2] + r[3] + 4) / 8 );
|
||||
a[0][1] = uint16( (g[2] + g[3] + 4) / 8 );
|
||||
a[0][2] = uint16( (b[2] + b[3] + 4) / 8 );
|
||||
a[0][3] = 0;
|
||||
a[1][0] = uint16( (r[0] + r[1] + 4) / 8 );
|
||||
a[1][1] = uint16( (g[0] + g[1] + 4) / 8 );
|
||||
a[1][2] = uint16( (b[0] + b[1] + 4) / 8 );
|
||||
a[1][3] = 0;
|
||||
a[2][0] = uint16( (r[1] + r[3] + 4) / 8 );
|
||||
a[2][1] = uint16( (g[1] + g[3] + 4) / 8 );
|
||||
a[2][2] = uint16( (b[1] + b[3] + 4) / 8 );
|
||||
a[2][3] = 0;
|
||||
a[3][0] = uint16( (r[0] + r[2] + 4) / 8 );
|
||||
a[3][1] = uint16( (g[0] + g[2] + 4) / 8 );
|
||||
a[3][2] = uint16( (b[0] + b[2] + 4) / 8 );
|
||||
a[3][3] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CalcErrorBlock( const uint8* data, uint err[4][4] )
|
||||
{
|
||||
#ifdef __SSE4_1__
|
||||
__m128i d0 = _mm_loadu_si128(((__m128i*)data) + 0);
|
||||
__m128i d1 = _mm_loadu_si128(((__m128i*)data) + 1);
|
||||
__m128i d2 = _mm_loadu_si128(((__m128i*)data) + 2);
|
||||
__m128i d3 = _mm_loadu_si128(((__m128i*)data) + 3);
|
||||
|
||||
__m128i dm0 = _mm_and_si128(d0, _mm_set1_epi32(0x00FFFFFF));
|
||||
__m128i dm1 = _mm_and_si128(d1, _mm_set1_epi32(0x00FFFFFF));
|
||||
__m128i dm2 = _mm_and_si128(d2, _mm_set1_epi32(0x00FFFFFF));
|
||||
__m128i dm3 = _mm_and_si128(d3, _mm_set1_epi32(0x00FFFFFF));
|
||||
|
||||
__m128i d0l = _mm_unpacklo_epi8(dm0, _mm_setzero_si128());
|
||||
__m128i d0h = _mm_unpackhi_epi8(dm0, _mm_setzero_si128());
|
||||
__m128i d1l = _mm_unpacklo_epi8(dm1, _mm_setzero_si128());
|
||||
__m128i d1h = _mm_unpackhi_epi8(dm1, _mm_setzero_si128());
|
||||
__m128i d2l = _mm_unpacklo_epi8(dm2, _mm_setzero_si128());
|
||||
__m128i d2h = _mm_unpackhi_epi8(dm2, _mm_setzero_si128());
|
||||
__m128i d3l = _mm_unpacklo_epi8(dm3, _mm_setzero_si128());
|
||||
__m128i d3h = _mm_unpackhi_epi8(dm3, _mm_setzero_si128());
|
||||
|
||||
__m128i sum0 = _mm_add_epi16(d0l, d1l);
|
||||
__m128i sum1 = _mm_add_epi16(d0h, d1h);
|
||||
__m128i sum2 = _mm_add_epi16(d2l, d3l);
|
||||
__m128i sum3 = _mm_add_epi16(d2h, d3h);
|
||||
|
||||
__m128i sum0l = _mm_unpacklo_epi16(sum0, _mm_setzero_si128());
|
||||
__m128i sum0h = _mm_unpackhi_epi16(sum0, _mm_setzero_si128());
|
||||
__m128i sum1l = _mm_unpacklo_epi16(sum1, _mm_setzero_si128());
|
||||
__m128i sum1h = _mm_unpackhi_epi16(sum1, _mm_setzero_si128());
|
||||
__m128i sum2l = _mm_unpacklo_epi16(sum2, _mm_setzero_si128());
|
||||
__m128i sum2h = _mm_unpackhi_epi16(sum2, _mm_setzero_si128());
|
||||
__m128i sum3l = _mm_unpacklo_epi16(sum3, _mm_setzero_si128());
|
||||
__m128i sum3h = _mm_unpackhi_epi16(sum3, _mm_setzero_si128());
|
||||
|
||||
__m128i b0 = _mm_add_epi32(sum0l, sum0h);
|
||||
__m128i b1 = _mm_add_epi32(sum1l, sum1h);
|
||||
__m128i b2 = _mm_add_epi32(sum2l, sum2h);
|
||||
__m128i b3 = _mm_add_epi32(sum3l, sum3h);
|
||||
|
||||
__m128i a0 = _mm_add_epi32(b2, b3);
|
||||
__m128i a1 = _mm_add_epi32(b0, b1);
|
||||
__m128i a2 = _mm_add_epi32(b1, b3);
|
||||
__m128i a3 = _mm_add_epi32(b0, b2);
|
||||
|
||||
_mm_storeu_si128((__m128i*)&err[0], a0);
|
||||
_mm_storeu_si128((__m128i*)&err[1], a1);
|
||||
_mm_storeu_si128((__m128i*)&err[2], a2);
|
||||
_mm_storeu_si128((__m128i*)&err[3], a3);
|
||||
#else
|
||||
uint terr[4][4];
|
||||
|
||||
memset(terr, 0, 16 * sizeof(uint));
|
||||
|
||||
for( int j=0; j<4; j++ )
|
||||
{
|
||||
for( int i=0; i<4; i++ )
|
||||
{
|
||||
int index = (j & 2) + (i >> 1);
|
||||
uint d = *data++;
|
||||
terr[index][0] += d;
|
||||
d = *data++;
|
||||
terr[index][1] += d;
|
||||
d = *data++;
|
||||
terr[index][2] += d;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
for( int i=0; i<3; i++ )
|
||||
{
|
||||
err[0][i] = terr[2][i] + terr[3][i];
|
||||
err[1][i] = terr[0][i] + terr[1][i];
|
||||
err[2][i] = terr[1][i] + terr[3][i];
|
||||
err[3][i] = terr[0][i] + terr[2][i];
|
||||
}
|
||||
for( int i=0; i<4; i++ )
|
||||
{
|
||||
err[i][3] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint CalcError( const uint block[4], const v4i& average )
|
||||
{
|
||||
uint err = 0x3FFFFFFF; // Big value to prevent negative values, but small enough to prevent overflow
|
||||
err -= block[0] * 2 * average[2];
|
||||
err -= block[1] * 2 * average[1];
|
||||
err -= block[2] * 2 * average[0];
|
||||
err += 8 * ( sq( average[0] ) + sq( average[1] ) + sq( average[2] ) );
|
||||
return err;
|
||||
}
|
||||
|
||||
void ProcessAverages( v4i* a )
|
||||
{
|
||||
#ifdef __SSE4_1__
|
||||
for( int i=0; i<2; i++ )
|
||||
{
|
||||
__m128i d = _mm_loadu_si128((__m128i*)a[i*2]);
|
||||
|
||||
__m128i t = _mm_add_epi16(_mm_mullo_epi16(d, _mm_set1_epi16(31)), _mm_set1_epi16(128));
|
||||
|
||||
__m128i c = _mm_srli_epi16(_mm_add_epi16(t, _mm_srli_epi16(t, 8)), 8);
|
||||
|
||||
__m128i c1 = _mm_shuffle_epi32(c, _MM_SHUFFLE(3, 2, 3, 2));
|
||||
__m128i diff = _mm_sub_epi16(c, c1);
|
||||
diff = _mm_max_epi16(diff, _mm_set1_epi16(-4));
|
||||
diff = _mm_min_epi16(diff, _mm_set1_epi16(3));
|
||||
|
||||
__m128i co = _mm_add_epi16(c1, diff);
|
||||
|
||||
c = _mm_blend_epi16(co, c, 0xF0);
|
||||
|
||||
__m128i a0 = _mm_or_si128(_mm_slli_epi16(c, 3), _mm_srli_epi16(c, 2));
|
||||
|
||||
_mm_storeu_si128((__m128i*)a[4+i*2], a0);
|
||||
}
|
||||
|
||||
for( int i=0; i<2; i++ )
|
||||
{
|
||||
__m128i d = _mm_loadu_si128((__m128i*)a[i*2]);
|
||||
|
||||
__m128i t0 = _mm_add_epi16(_mm_mullo_epi16(d, _mm_set1_epi16(15)), _mm_set1_epi16(128));
|
||||
__m128i t1 = _mm_srli_epi16(_mm_add_epi16(t0, _mm_srli_epi16(t0, 8)), 8);
|
||||
|
||||
__m128i t2 = _mm_or_si128(t1, _mm_slli_epi16(t1, 4));
|
||||
|
||||
_mm_storeu_si128((__m128i*)a[i*2], t2);
|
||||
}
|
||||
#else
|
||||
for( int i=0; i<2; i++ )
|
||||
{
|
||||
for( int j=0; j<3; j++ )
|
||||
{
|
||||
int32 c1 = mul8bit( a[i*2+1][j], 31 );
|
||||
int32 c2 = mul8bit( a[i*2][j], 31 );
|
||||
|
||||
int32 diff = c2 - c1;
|
||||
if( diff > 3 ) diff = 3;
|
||||
else if( diff < -4 ) diff = -4;
|
||||
|
||||
int32 co = c1 + diff;
|
||||
|
||||
a[5+i*2][j] = ( c1 << 3 ) | ( c1 >> 2 );
|
||||
a[4+i*2][j] = ( co << 3 ) | ( co >> 2 );
|
||||
}
|
||||
}
|
||||
|
||||
for( int i=0; i<4; i++ )
|
||||
{
|
||||
a[i][0] = g_avg2[mul8bit( a[i][0], 15 )];
|
||||
a[i][1] = g_avg2[mul8bit( a[i][1], 15 )];
|
||||
a[i][2] = g_avg2[mul8bit( a[i][2], 15 )];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void EncodeAverages( uint64& _d, const v4i* a, size_t idx )
|
||||
{
|
||||
uint64 d = _d;
|
||||
d |= ( idx << 24 );
|
||||
size_t base = idx << 1;
|
||||
|
||||
if( ( idx & 0x2 ) == 0 )
|
||||
{
|
||||
for( int i=0; i<3; i++ )
|
||||
{
|
||||
d |= uint64( a[base+0][i] >> 4 ) << ( i*8 );
|
||||
d |= uint64( a[base+1][i] >> 4 ) << ( i*8 + 4 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i=0; i<3; i++ )
|
||||
{
|
||||
d |= uint64( a[base+1][i] & 0xF8 ) << ( i*8 );
|
||||
int32 c = ( ( a[base+0][i] & 0xF8 ) - ( a[base+1][i] & 0xF8 ) ) >> 3;
|
||||
c &= ~0xFFFFFFF8;
|
||||
d |= ((uint64)c) << ( i*8 );
|
||||
}
|
||||
}
|
||||
_d = d;
|
||||
}
|
||||
|
||||
uint64 CheckSolid( const uint8* src )
|
||||
{
|
||||
#ifdef __SSE4_1__
|
||||
__m128i d0 = _mm_loadu_si128(((__m128i*)src) + 0);
|
||||
__m128i d1 = _mm_loadu_si128(((__m128i*)src) + 1);
|
||||
__m128i d2 = _mm_loadu_si128(((__m128i*)src) + 2);
|
||||
__m128i d3 = _mm_loadu_si128(((__m128i*)src) + 3);
|
||||
|
||||
__m128i c = _mm_shuffle_epi32(d0, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
|
||||
__m128i c0 = _mm_cmpeq_epi8(d0, c);
|
||||
__m128i c1 = _mm_cmpeq_epi8(d1, c);
|
||||
__m128i c2 = _mm_cmpeq_epi8(d2, c);
|
||||
__m128i c3 = _mm_cmpeq_epi8(d3, c);
|
||||
|
||||
__m128i m0 = _mm_and_si128(c0, c1);
|
||||
__m128i m1 = _mm_and_si128(c2, c3);
|
||||
__m128i m = _mm_and_si128(m0, m1);
|
||||
|
||||
if (!_mm_testc_si128(m, _mm_set1_epi32(-1)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
const uint8* ptr = src + 4;
|
||||
for( int i=1; i<16; i++ )
|
||||
{
|
||||
if( memcmp( src, ptr, 4 ) != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ptr += 4;
|
||||
}
|
||||
#endif
|
||||
return 0x02000000 |
|
||||
( uint( src[0] & 0xF8 ) << 16 ) |
|
||||
( uint( src[1] & 0xF8 ) << 8 ) |
|
||||
( uint( src[2] & 0xF8 ) );
|
||||
}
|
||||
|
||||
void PrepareAverages( v4i a[8], const uint8* src, uint err[4] )
|
||||
{
|
||||
Average( src, a );
|
||||
ProcessAverages( a );
|
||||
|
||||
uint errblock[4][4];
|
||||
CalcErrorBlock( src, errblock );
|
||||
|
||||
for( int i=0; i<4; i++ )
|
||||
{
|
||||
err[i/2] += CalcError( errblock[i], a[i] );
|
||||
err[2+i/2] += CalcError( errblock[i], a[i+4] );
|
||||
}
|
||||
}
|
||||
|
||||
void FindBestFit( uint64 terr[2][8], uint16 tsel[16][8], v4i a[8], const uint32* id, const uint8* data )
|
||||
{
|
||||
for( size_t i=0; i<16; i++ )
|
||||
{
|
||||
uint16* sel = tsel[i];
|
||||
uint bid = id[i];
|
||||
uint64* ter = terr[bid%2];
|
||||
|
||||
uint8 b = *data++;
|
||||
uint8 g = *data++;
|
||||
uint8 r = *data++;
|
||||
data++;
|
||||
|
||||
int dr = a[bid][0] - r;
|
||||
int dg = a[bid][1] - g;
|
||||
int db = a[bid][2] - b;
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
// Reference implementation
|
||||
|
||||
__m128i pix = _mm_set1_epi32(dr * 77 + dg * 151 + db * 28);
|
||||
// Taking the absolute value is way faster. The values are only used to sort, so the result will be the same.
|
||||
__m128i error0 = _mm_abs_epi32(_mm_add_epi32(pix, g_table256_SIMD[0]));
|
||||
__m128i error1 = _mm_abs_epi32(_mm_add_epi32(pix, g_table256_SIMD[1]));
|
||||
__m128i error2 = _mm_abs_epi32(_mm_sub_epi32(pix, g_table256_SIMD[0]));
|
||||
__m128i error3 = _mm_abs_epi32(_mm_sub_epi32(pix, g_table256_SIMD[1]));
|
||||
|
||||
__m128i index0 = _mm_and_si128(_mm_cmplt_epi32(error1, error0), _mm_set1_epi32(1));
|
||||
__m128i minError0 = _mm_min_epi32(error0, error1);
|
||||
|
||||
__m128i index1 = _mm_sub_epi32(_mm_set1_epi32(2), _mm_cmplt_epi32(error3, error2));
|
||||
__m128i minError1 = _mm_min_epi32(error2, error3);
|
||||
|
||||
__m128i minIndex0 = _mm_blendv_epi8(index0, index1, _mm_cmplt_epi32(minError1, minError0));
|
||||
__m128i minError = _mm_min_epi32(minError0, minError1);
|
||||
|
||||
// Squaring the minimum error to produce correct values when adding
|
||||
__m128i minErrorLow = _mm_shuffle_epi32(minError, _MM_SHUFFLE(1, 1, 0, 0));
|
||||
__m128i squareErrorLow = _mm_mul_epi32(minErrorLow, minErrorLow);
|
||||
squareErrorLow = _mm_add_epi64(squareErrorLow, _mm_loadu_si128(((__m128i*)ter) + 0));
|
||||
_mm_storeu_si128(((__m128i*)ter) + 0, squareErrorLow);
|
||||
__m128i minErrorHigh = _mm_shuffle_epi32(minError, _MM_SHUFFLE(3, 3, 2, 2));
|
||||
__m128i squareErrorHigh = _mm_mul_epi32(minErrorHigh, minErrorHigh);
|
||||
squareErrorHigh = _mm_add_epi64(squareErrorHigh, _mm_loadu_si128(((__m128i*)ter) + 1));
|
||||
_mm_storeu_si128(((__m128i*)ter) + 1, squareErrorHigh);
|
||||
|
||||
// Taking the absolute value is way faster. The values are only used to sort, so the result will be the same.
|
||||
error0 = _mm_abs_epi32(_mm_add_epi32(pix, g_table256_SIMD[2]));
|
||||
error1 = _mm_abs_epi32(_mm_add_epi32(pix, g_table256_SIMD[3]));
|
||||
error2 = _mm_abs_epi32(_mm_sub_epi32(pix, g_table256_SIMD[2]));
|
||||
error3 = _mm_abs_epi32(_mm_sub_epi32(pix, g_table256_SIMD[3]));
|
||||
|
||||
index0 = _mm_and_si128(_mm_cmplt_epi32(error1, error0), _mm_set1_epi32(1));
|
||||
minError0 = _mm_min_epi32(error0, error1);
|
||||
|
||||
index1 = _mm_sub_epi32(_mm_set1_epi32(2), _mm_cmplt_epi32(error3, error2));
|
||||
minError1 = _mm_min_epi32(error2, error3);
|
||||
|
||||
__m128i minIndex1 = _mm_blendv_epi8(index0, index1, _mm_cmplt_epi32(minError1, minError0));
|
||||
minError = _mm_min_epi32(minError0, minError1);
|
||||
|
||||
// Squaring the minimum error to produce correct values when adding
|
||||
minErrorLow = _mm_shuffle_epi32(minError, _MM_SHUFFLE(1, 1, 0, 0));
|
||||
squareErrorLow = _mm_mul_epi32(minErrorLow, minErrorLow);
|
||||
squareErrorLow = _mm_add_epi64(squareErrorLow, _mm_loadu_si128(((__m128i*)ter) + 2));
|
||||
_mm_storeu_si128(((__m128i*)ter) + 2, squareErrorLow);
|
||||
minErrorHigh = _mm_shuffle_epi32(minError, _MM_SHUFFLE(3, 3, 2, 2));
|
||||
squareErrorHigh = _mm_mul_epi32(minErrorHigh, minErrorHigh);
|
||||
squareErrorHigh = _mm_add_epi64(squareErrorHigh, _mm_loadu_si128(((__m128i*)ter) + 3));
|
||||
_mm_storeu_si128(((__m128i*)ter) + 3, squareErrorHigh);
|
||||
__m128i minIndex = _mm_packs_epi32(minIndex0, minIndex1);
|
||||
_mm_storeu_si128((__m128i*)sel, minIndex);
|
||||
#else
|
||||
int pix = dr * 77 + dg * 151 + db * 28;
|
||||
|
||||
for( int t=0; t<8; t++ )
|
||||
{
|
||||
const int64* tab = g_table256[t];
|
||||
uint idx = 0;
|
||||
uint64 err = sq( tab[0] + pix );
|
||||
for( int j=1; j<4; j++ )
|
||||
{
|
||||
uint64 local = sq( tab[j] + pix );
|
||||
if( local < err )
|
||||
{
|
||||
err = local;
|
||||
idx = j;
|
||||
}
|
||||
}
|
||||
*sel++ = idx;
|
||||
*ter++ += err;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
// Non-reference implementation, but faster. Produces same results as the AVX2 version
|
||||
void FindBestFit( uint32 terr[2][8], uint16 tsel[16][8], v4i a[8], const uint32* id, const uint8* data )
|
||||
{
|
||||
for( size_t i=0; i<16; i++ )
|
||||
{
|
||||
uint16* sel = tsel[i];
|
||||
uint bid = id[i];
|
||||
uint32* ter = terr[bid%2];
|
||||
|
||||
uint8 b = *data++;
|
||||
uint8 g = *data++;
|
||||
uint8 r = *data++;
|
||||
data++;
|
||||
|
||||
int dr = a[bid][0] - r;
|
||||
int dg = a[bid][1] - g;
|
||||
int db = a[bid][2] - b;
|
||||
|
||||
// The scaling values are divided by two and rounded, to allow the differences to be in the range of signed int16
|
||||
// This produces slightly different results, but is significant faster
|
||||
__m128i pixel = _mm_set1_epi16(dr * 38 + dg * 76 + db * 14);
|
||||
__m128i pix = _mm_abs_epi16(pixel);
|
||||
|
||||
// Taking the absolute value is way faster. The values are only used to sort, so the result will be the same.
|
||||
// Since the selector table is symmetrical, we need to calculate the difference only for half of the entries.
|
||||
__m128i error0 = _mm_abs_epi16(_mm_sub_epi16(pix, g_table128_SIMD[0]));
|
||||
__m128i error1 = _mm_abs_epi16(_mm_sub_epi16(pix, g_table128_SIMD[1]));
|
||||
|
||||
__m128i index = _mm_and_si128(_mm_cmplt_epi16(error1, error0), _mm_set1_epi16(1));
|
||||
__m128i minError = _mm_min_epi16(error0, error1);
|
||||
|
||||
// Exploiting symmetry of the selector table and use the sign bit
|
||||
// This produces slightly different results, but is needed to produce same results as AVX2 implementation
|
||||
__m128i indexBit = _mm_andnot_si128(_mm_srli_epi16(pixel, 15), _mm_set1_epi8(-1));
|
||||
__m128i minIndex = _mm_or_si128(index, _mm_add_epi16(indexBit, indexBit));
|
||||
|
||||
// Squaring the minimum error to produce correct values when adding
|
||||
__m128i squareErrorLo = _mm_mullo_epi16(minError, minError);
|
||||
__m128i squareErrorHi = _mm_mulhi_epi16(minError, minError);
|
||||
|
||||
__m128i squareErrorLow = _mm_unpacklo_epi16(squareErrorLo, squareErrorHi);
|
||||
__m128i squareErrorHigh = _mm_unpackhi_epi16(squareErrorLo, squareErrorHi);
|
||||
|
||||
squareErrorLow = _mm_add_epi32(squareErrorLow, _mm_loadu_si128(((__m128i*)ter) + 0));
|
||||
_mm_storeu_si128(((__m128i*)ter) + 0, squareErrorLow);
|
||||
squareErrorHigh = _mm_add_epi32(squareErrorHigh, _mm_loadu_si128(((__m128i*)ter) + 1));
|
||||
_mm_storeu_si128(((__m128i*)ter) + 1, squareErrorHigh);
|
||||
|
||||
_mm_storeu_si128((__m128i*)sel, minIndex);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t convert6(float f)
|
||||
{
|
||||
int i = (std::min(std::max(static_cast<int>(f), 0), 1023) - 15) >> 1;
|
||||
return (i + 11 - ((i + 11) >> 7) - ((i + 4) >> 7)) >> 3;
|
||||
}
|
||||
|
||||
uint8_t convert7(float f)
|
||||
{
|
||||
int i = (std::min(std::max(static_cast<int>(f), 0), 1023) - 15) >> 1;
|
||||
return (i + 9 - ((i + 9) >> 8) - ((i + 6) >> 8)) >> 2;
|
||||
}
|
||||
|
||||
std::pair<uint64, uint64> Planar(const uint8* src)
|
||||
{
|
||||
int32 r = 0;
|
||||
int32 g = 0;
|
||||
int32 b = 0;
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
b += src[i * 4 + 0];
|
||||
g += src[i * 4 + 1];
|
||||
r += src[i * 4 + 2];
|
||||
}
|
||||
|
||||
int32 difRyz = 0;
|
||||
int32 difGyz = 0;
|
||||
int32 difByz = 0;
|
||||
int32 difRxz = 0;
|
||||
int32 difGxz = 0;
|
||||
int32 difBxz = 0;
|
||||
|
||||
const int32 scaling[] = { -255, -85, 85, 255 };
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
int32 difB = (static_cast<int>(src[i * 4 + 0]) << 4) - b;
|
||||
int32 difG = (static_cast<int>(src[i * 4 + 1]) << 4) - g;
|
||||
int32 difR = (static_cast<int>(src[i * 4 + 2]) << 4) - r;
|
||||
|
||||
difRyz += difR * scaling[i % 4];
|
||||
difGyz += difG * scaling[i % 4];
|
||||
difByz += difB * scaling[i % 4];
|
||||
|
||||
difRxz += difR * scaling[i / 4];
|
||||
difGxz += difG * scaling[i / 4];
|
||||
difBxz += difB * scaling[i / 4];
|
||||
}
|
||||
|
||||
const float scale = -4.0f / ((255 * 255 * 8.0f + 85 * 85 * 8.0f) * 16.0f);
|
||||
|
||||
float aR = difRxz * scale;
|
||||
float aG = difGxz * scale;
|
||||
float aB = difBxz * scale;
|
||||
|
||||
float bR = difRyz * scale;
|
||||
float bG = difGyz * scale;
|
||||
float bB = difByz * scale;
|
||||
|
||||
float dR = r * (4.0f / 16.0f);
|
||||
float dG = g * (4.0f / 16.0f);
|
||||
float dB = b * (4.0f / 16.0f);
|
||||
|
||||
// calculating the three colors RGBO, RGBH, and RGBV. RGB = df - af * x - bf * y;
|
||||
float cofR = (aR * 255.0f + (bR * 255.0f + dR));
|
||||
float cofG = (aG * 255.0f + (bG * 255.0f + dG));
|
||||
float cofB = (aB * 255.0f + (bB * 255.0f + dB));
|
||||
float chfR = (aR * -425.0f + (bR * 255.0f + dR));
|
||||
float chfG = (aG * -425.0f + (bG * 255.0f + dG));
|
||||
float chfB = (aB * -425.0f + (bB * 255.0f + dB));
|
||||
float cvfR = (aR * 255.0f + (bR * -425.0f + dR));
|
||||
float cvfG = (aG * 255.0f + (bG * -425.0f + dG));
|
||||
float cvfB = (aB * 255.0f + (bB * -425.0f + dB));
|
||||
|
||||
// convert to r6g7b6
|
||||
int32 coR = convert6(cofR);
|
||||
int32 coG = convert7(cofG);
|
||||
int32 coB = convert6(cofB);
|
||||
int32 chR = convert6(chfR);
|
||||
int32 chG = convert7(chfG);
|
||||
int32 chB = convert6(chfB);
|
||||
int32 cvR = convert6(cvfR);
|
||||
int32 cvG = convert7(cvfG);
|
||||
int32 cvB = convert6(cvfB);
|
||||
|
||||
// Error calculation
|
||||
int32 ro0 = coR;
|
||||
int32 go0 = coG;
|
||||
int32 bo0 = coB;
|
||||
int32 ro1 = (ro0 >> 4) | (ro0 << 2);
|
||||
int32 go1 = (go0 >> 6) | (go0 << 1);
|
||||
int32 bo1 = (bo0 >> 4) | (bo0 << 2);
|
||||
int32 ro2 = (ro1 << 2) + 2;
|
||||
int32 go2 = (go1 << 2) + 2;
|
||||
int32 bo2 = (bo1 << 2) + 2;
|
||||
|
||||
int32 rh0 = chR;
|
||||
int32 gh0 = chG;
|
||||
int32 bh0 = chB;
|
||||
int32 rh1 = (rh0 >> 4) | (rh0 << 2);
|
||||
int32 gh1 = (gh0 >> 6) | (gh0 << 1);
|
||||
int32 bh1 = (bh0 >> 4) | (bh0 << 2);
|
||||
|
||||
int32 rh2 = rh1 - ro1;
|
||||
int32 gh2 = gh1 - go1;
|
||||
int32 bh2 = bh1 - bo1;
|
||||
|
||||
int32 rv0 = cvR;
|
||||
int32 gv0 = cvG;
|
||||
int32 bv0 = cvB;
|
||||
int32 rv1 = (rv0 >> 4) | (rv0 << 2);
|
||||
int32 gv1 = (gv0 >> 6) | (gv0 << 1);
|
||||
int32 bv1 = (bv0 >> 4) | (bv0 << 2);
|
||||
|
||||
int32 rv2 = rv1 - ro1;
|
||||
int32 gv2 = gv1 - go1;
|
||||
int32 bv2 = bv1 - bo1;
|
||||
|
||||
uint64 error = 0;
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
int32 cR = clampu8((rh2 * (i / 4) + rv2 * (i % 4) + ro2) >> 2);
|
||||
int32 cG = clampu8((gh2 * (i / 4) + gv2 * (i % 4) + go2) >> 2);
|
||||
int32 cB = clampu8((bh2 * (i / 4) + bv2 * (i % 4) + bo2) >> 2);
|
||||
|
||||
int32 difB = static_cast<int>(src[i * 4 + 0]) - cB;
|
||||
int32 difG = static_cast<int>(src[i * 4 + 1]) - cG;
|
||||
int32 difR = static_cast<int>(src[i * 4 + 2]) - cR;
|
||||
|
||||
int32 dif = difR * 38 + difG * 76 + difB * 14;
|
||||
|
||||
error += dif * dif;
|
||||
}
|
||||
|
||||
/**/
|
||||
uint32 rgbv = cvB | (cvG << 6) | (cvR << 13);
|
||||
uint32 rgbh = chB | (chG << 6) | (chR << 13);
|
||||
uint32 hi = rgbv | ((rgbh & 0x1FFF) << 19);
|
||||
uint32 lo = (chR & 0x1) | 0x2 | ((chR << 1) & 0x7C);
|
||||
lo |= ((coB & 0x07) << 7) | ((coB & 0x18) << 8) | ((coB & 0x20) << 11);
|
||||
lo |= ((coG & 0x3F) << 17) | ((coG & 0x40) << 18);
|
||||
lo |= coR << 25;
|
||||
|
||||
const int32 idx = (coR & 0x20) | ((coG & 0x20) >> 1) | ((coB & 0x1E) >> 1);
|
||||
|
||||
lo |= g_flags[idx];
|
||||
|
||||
uint64 result = static_cast<uint32>(bx::endianSwap(lo));
|
||||
result |= static_cast<uint64>(static_cast<uint32>(bx::endianSwap(hi))) << 32;
|
||||
|
||||
return std::make_pair(result, error);
|
||||
}
|
||||
|
||||
template<class T, class S>
|
||||
uint64 EncodeSelectors( uint64 d, const T terr[2][8], const S tsel[16][8], const uint32* id, const uint64 value, const uint64 error)
|
||||
{
|
||||
size_t tidx[2];
|
||||
tidx[0] = GetLeastError( terr[0], 8 );
|
||||
tidx[1] = GetLeastError( terr[1], 8 );
|
||||
|
||||
if ((terr[0][tidx[0]] + terr[1][tidx[1]]) >= error)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
d |= tidx[0] << 26;
|
||||
d |= tidx[1] << 29;
|
||||
for( int i=0; i<16; i++ )
|
||||
{
|
||||
uint64 t = tsel[i][tidx[id[i]%2]];
|
||||
d |= ( t & 0x1 ) << ( i + 32 );
|
||||
d |= ( t & 0x2 ) << ( i + 47 );
|
||||
}
|
||||
|
||||
return FixByteOrder(d);
|
||||
}
|
||||
}
|
||||
|
||||
uint64 ProcessRGB( const uint8* src )
|
||||
{
|
||||
uint64 d = CheckSolid( src );
|
||||
if( d != 0 ) return d;
|
||||
|
||||
v4i a[8];
|
||||
uint err[4] = {};
|
||||
PrepareAverages( a, src, err );
|
||||
size_t idx = GetLeastError( err, 4 );
|
||||
EncodeAverages( d, a, idx );
|
||||
|
||||
#if defined __SSE4_1__ && !defined REFERENCE_IMPLEMENTATION
|
||||
uint32 terr[2][8] = {};
|
||||
#else
|
||||
uint64 terr[2][8] = {};
|
||||
#endif
|
||||
uint16 tsel[16][8];
|
||||
const uint32* id = g_id[idx];
|
||||
FindBestFit( terr, tsel, a, id, src );
|
||||
|
||||
return FixByteOrder( EncodeSelectors( d, terr, tsel, id ) );
|
||||
}
|
||||
|
||||
uint64 ProcessRGB_ETC2( const uint8* src )
|
||||
{
|
||||
std::pair<uint64, uint64> result = Planar( src );
|
||||
|
||||
uint64 d = 0;
|
||||
|
||||
v4i a[8];
|
||||
uint err[4] = {};
|
||||
PrepareAverages( a, src, err );
|
||||
size_t idx = GetLeastError( err, 4 );
|
||||
EncodeAverages( d, a, idx );
|
||||
|
||||
uint64 terr[2][8] = {};
|
||||
uint16 tsel[16][8];
|
||||
const uint32* id = g_id[idx];
|
||||
FindBestFit( terr, tsel, a, id, src );
|
||||
|
||||
return EncodeSelectors( d, terr, tsel, id, result.first, result.second );
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef __PROCESSRGB_HPP__
|
||||
#define __PROCESSRGB_HPP__
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
uint64 ProcessRGB( const uint8* src );
|
||||
uint64 ProcessRGB_ETC2( const uint8* src );
|
||||
|
||||
#endif
|
|
@ -1,109 +0,0 @@
|
|||
#include "Tables.hpp"
|
||||
|
||||
const int32 g_table[8][4] = {
|
||||
{ 2, 8, -2, -8 },
|
||||
{ 5, 17, -5, -17 },
|
||||
{ 9, 29, -9, -29 },
|
||||
{ 13, 42, -13, -42 },
|
||||
{ 18, 60, -18, -60 },
|
||||
{ 24, 80, -24, -80 },
|
||||
{ 33, 106, -33, -106 },
|
||||
{ 47, 183, -47, -183 }
|
||||
};
|
||||
|
||||
const int64 g_table256[8][4] = {
|
||||
{ 2*256, 8*256, -2*256, -8*256 },
|
||||
{ 5*256, 17*256, -5*256, -17*256 },
|
||||
{ 9*256, 29*256, -9*256, -29*256 },
|
||||
{ 13*256, 42*256, -13*256, -42*256 },
|
||||
{ 18*256, 60*256, -18*256, -60*256 },
|
||||
{ 24*256, 80*256, -24*256, -80*256 },
|
||||
{ 33*256, 106*256, -33*256, -106*256 },
|
||||
{ 47*256, 183*256, -47*256, -183*256 }
|
||||
};
|
||||
|
||||
const uint32 g_id[4][16] = {
|
||||
{ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2 },
|
||||
{ 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4 },
|
||||
{ 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6 }
|
||||
};
|
||||
|
||||
const uint32 g_avg2[16] = {
|
||||
0x00,
|
||||
0x11,
|
||||
0x22,
|
||||
0x33,
|
||||
0x44,
|
||||
0x55,
|
||||
0x66,
|
||||
0x77,
|
||||
0x88,
|
||||
0x99,
|
||||
0xAA,
|
||||
0xBB,
|
||||
0xCC,
|
||||
0xDD,
|
||||
0xEE,
|
||||
0xFF
|
||||
};
|
||||
|
||||
const uint32 g_flags[64] = {
|
||||
0x80800402, 0x80800402, 0x80800402, 0x80800402,
|
||||
0x80800402, 0x80800402, 0x80800402, 0x8080E002,
|
||||
0x80800402, 0x80800402, 0x8080E002, 0x8080E002,
|
||||
0x80800402, 0x8080E002, 0x8080E002, 0x8080E002,
|
||||
0x80000402, 0x80000402, 0x80000402, 0x80000402,
|
||||
0x80000402, 0x80000402, 0x80000402, 0x8000E002,
|
||||
0x80000402, 0x80000402, 0x8000E002, 0x8000E002,
|
||||
0x80000402, 0x8000E002, 0x8000E002, 0x8000E002,
|
||||
0x00800402, 0x00800402, 0x00800402, 0x00800402,
|
||||
0x00800402, 0x00800402, 0x00800402, 0x0080E002,
|
||||
0x00800402, 0x00800402, 0x0080E002, 0x0080E002,
|
||||
0x00800402, 0x0080E002, 0x0080E002, 0x0080E002,
|
||||
0x00000402, 0x00000402, 0x00000402, 0x00000402,
|
||||
0x00000402, 0x00000402, 0x00000402, 0x0000E002,
|
||||
0x00000402, 0x00000402, 0x0000E002, 0x0000E002,
|
||||
0x00000402, 0x0000E002, 0x0000E002, 0x0000E002
|
||||
};
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
const uint8 g_flags_AVX2[64] =
|
||||
{
|
||||
0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x7D,
|
||||
0x63, 0x63, 0x7D, 0x7D,
|
||||
0x63, 0x7D, 0x7D, 0x7D,
|
||||
0x43, 0x43, 0x43, 0x43,
|
||||
0x43, 0x43, 0x43, 0x5D,
|
||||
0x43, 0x43, 0x5D, 0x5D,
|
||||
0x43, 0x5D, 0x5D, 0x5D,
|
||||
0x23, 0x23, 0x23, 0x23,
|
||||
0x23, 0x23, 0x23, 0x3D,
|
||||
0x23, 0x23, 0x3D, 0x3D,
|
||||
0x23, 0x3D, 0x3D, 0x3D,
|
||||
0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x1D,
|
||||
0x03, 0x03, 0x1D, 0x1D,
|
||||
0x03, 0x1D, 0x1D, 0x1D,
|
||||
};
|
||||
|
||||
const __m128i g_table_SIMD[2] =
|
||||
{
|
||||
_mm_setr_epi16( 2, 5, 9, 13, 18, 24, 33, 47),
|
||||
_mm_setr_epi16( 8, 17, 29, 42, 60, 80, 106, 183)
|
||||
};
|
||||
const __m128i g_table128_SIMD[2] =
|
||||
{
|
||||
_mm_setr_epi16( 2*128, 5*128, 9*128, 13*128, 18*128, 24*128, 33*128, 47*128),
|
||||
_mm_setr_epi16( 8*128, 17*128, 29*128, 42*128, 60*128, 80*128, 106*128, 183*128)
|
||||
};
|
||||
const __m128i g_table256_SIMD[4] =
|
||||
{
|
||||
_mm_setr_epi32( 2*256, 5*256, 9*256, 13*256),
|
||||
_mm_setr_epi32( 8*256, 17*256, 29*256, 42*256),
|
||||
_mm_setr_epi32( 18*256, 24*256, 33*256, 47*256),
|
||||
_mm_setr_epi32( 60*256, 80*256, 106*256, 183*256)
|
||||
};
|
||||
#endif
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
#ifndef __TABLES_HPP__
|
||||
#define __TABLES_HPP__
|
||||
|
||||
#include "Types.hpp"
|
||||
#ifdef __SSE4_1__
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
|
||||
extern const int32 g_table[8][4];
|
||||
extern const int64 g_table256[8][4];
|
||||
|
||||
extern const uint32 g_id[4][16];
|
||||
|
||||
extern const uint32 g_avg2[16];
|
||||
|
||||
extern const uint32 g_flags[64];
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
extern const uint8 g_flags_AVX2[64];
|
||||
extern const __m128i g_table_SIMD[2];
|
||||
extern const __m128i g_table128_SIMD[2];
|
||||
extern const __m128i g_table256_SIMD[4];
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef __DARKRL__TYPES_HPP__
|
||||
#define __DARKRL__TYPES_HPP__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int8_t int8;
|
||||
typedef uint8_t uint8;
|
||||
typedef int16_t int16;
|
||||
typedef uint16_t uint16;
|
||||
typedef int32_t int32;
|
||||
typedef uint32_t uint32;
|
||||
typedef int64_t int64;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
#endif
|
|
@ -1,222 +0,0 @@
|
|||
#ifndef __DARKRL__VECTOR_HPP__
|
||||
#define __DARKRL__VECTOR_HPP__
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
#include "Math.hpp"
|
||||
#include "Types.hpp"
|
||||
|
||||
template<class T>
|
||||
struct Vector2
|
||||
{
|
||||
Vector2() : x( 0 ), y( 0 ) {}
|
||||
Vector2( T v ) : x( v ), y( v ) {}
|
||||
Vector2( T _x, T _y ) : x( _x ), y( _y ) {}
|
||||
|
||||
bool operator==( const Vector2<T>& rhs ) const { return x == rhs.x && y == rhs.y; }
|
||||
bool operator!=( const Vector2<T>& rhs ) const { return !( *this == rhs ); }
|
||||
|
||||
Vector2<T>& operator+=( const Vector2<T>& rhs )
|
||||
{
|
||||
x += rhs.x;
|
||||
y += rhs.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2<T>& operator-=( const Vector2<T>& rhs )
|
||||
{
|
||||
x -= rhs.x;
|
||||
y -= rhs.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2<T>& operator*=( const Vector2<T>& rhs )
|
||||
{
|
||||
x *= rhs.x;
|
||||
y *= rhs.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T x, y;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
Vector2<T> operator+( const Vector2<T>& lhs, const Vector2<T>& rhs )
|
||||
{
|
||||
return Vector2<T>( lhs.x + rhs.x, lhs.y + rhs.y );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector2<T> operator-( const Vector2<T>& lhs, const Vector2<T>& rhs )
|
||||
{
|
||||
return Vector2<T>( lhs.x - rhs.x, lhs.y - rhs.y );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector2<T> operator*( const Vector2<T>& lhs, const float& rhs )
|
||||
{
|
||||
return Vector2<T>( lhs.x * rhs, lhs.y * rhs );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector2<T> operator/( const Vector2<T>& lhs, const T& rhs )
|
||||
{
|
||||
return Vector2<T>( lhs.x / rhs, lhs.y / rhs );
|
||||
}
|
||||
|
||||
|
||||
typedef Vector2<int32> v2i;
|
||||
typedef Vector2<float> v2f;
|
||||
|
||||
|
||||
template<class T>
|
||||
struct Vector3
|
||||
{
|
||||
Vector3() : x( 0 ), y( 0 ), z( 0 ) {}
|
||||
Vector3( T v ) : x( v ), y( v ), z( v ) {}
|
||||
Vector3( T _x, T _y, T _z ) : x( _x ), y( _y ), z( _z ) {}
|
||||
template<class Y>
|
||||
Vector3( const Vector3<Y>& v ) : x( T( v.x ) ), y( T( v.y ) ), z( T( v.z ) ) {}
|
||||
|
||||
T Luminance() const { return T( x * 0.3f + y * 0.59f + z * 0.11f ); }
|
||||
void Clamp()
|
||||
{
|
||||
x = std::min( T(1), std::max( T(0), x ) );
|
||||
y = std::min( T(1), std::max( T(0), y ) );
|
||||
z = std::min( T(1), std::max( T(0), z ) );
|
||||
}
|
||||
|
||||
bool operator==( const Vector3<T>& rhs ) const { return x == rhs.x && y == rhs.y && z == rhs.z; }
|
||||
bool operator!=( const Vector2<T>& rhs ) const { return !( *this == rhs ); }
|
||||
|
||||
T& operator[]( uint idx ) { assert( idx < 3 ); return ((T*)this)[idx]; }
|
||||
const T& operator[]( uint idx ) const { assert( idx < 3 ); return ((T*)this)[idx]; }
|
||||
|
||||
Vector3<T> operator+=( const Vector3<T>& rhs )
|
||||
{
|
||||
x += rhs.x;
|
||||
y += rhs.y;
|
||||
z += rhs.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3<T> operator*=( const Vector3<T>& rhs )
|
||||
{
|
||||
x *= rhs.x;
|
||||
y *= rhs.y;
|
||||
z *= rhs.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3<T> operator*=( const float& rhs )
|
||||
{
|
||||
x *= rhs;
|
||||
y *= rhs;
|
||||
z *= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T x, y, z;
|
||||
T padding;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
Vector3<T> operator+( const Vector3<T>& lhs, const Vector3<T>& rhs )
|
||||
{
|
||||
return Vector3<T>( lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> operator-( const Vector3<T>& lhs, const Vector3<T>& rhs )
|
||||
{
|
||||
return Vector3<T>( lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> operator*( const Vector3<T>& lhs, const Vector3<T>& rhs )
|
||||
{
|
||||
return Vector3<T>( lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> operator*( const Vector3<T>& lhs, const float& rhs )
|
||||
{
|
||||
return Vector3<T>( T( lhs.x * rhs ), T( lhs.y * rhs ), T( lhs.z * rhs ) );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> operator/( const Vector3<T>& lhs, const T& rhs )
|
||||
{
|
||||
return Vector3<T>( lhs.x / rhs, lhs.y / rhs, lhs.z / rhs );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool operator<( const Vector3<T>& lhs, const Vector3<T>& rhs )
|
||||
{
|
||||
return lhs.Luminance() < rhs.Luminance();
|
||||
}
|
||||
|
||||
typedef Vector3<int32> v3i;
|
||||
typedef Vector3<float> v3f;
|
||||
typedef Vector3<uint8> v3b;
|
||||
|
||||
|
||||
static inline v3b v3f_to_v3b( const v3f& v )
|
||||
{
|
||||
return v3b( uint8( std::min( 1.f, v.x ) * 255 ), uint8( std::min( 1.f, v.y ) * 255 ), uint8( std::min( 1.f, v.z ) * 255 ) );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> Mix( const Vector3<T>& v1, const Vector3<T>& v2, float amount )
|
||||
{
|
||||
return v1 + ( v2 - v1 ) * amount;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline v3b Mix( const v3b& v1, const v3b& v2, float amount )
|
||||
{
|
||||
return v3b( v3f( v1 ) + ( v3f( v2 ) - v3f( v1 ) ) * amount );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> Desaturate( const Vector3<T>& v )
|
||||
{
|
||||
T l = v.Luminance();
|
||||
return Vector3<T>( l, l, l );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> Desaturate( const Vector3<T>& v, float mul )
|
||||
{
|
||||
T l = T( v.Luminance() * mul );
|
||||
return Vector3<T>( l, l, l );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> pow( const Vector3<T>& base, float exponent )
|
||||
{
|
||||
return Vector3<T>(
|
||||
pow( base.x, exponent ),
|
||||
pow( base.y, exponent ),
|
||||
pow( base.z, exponent ) );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> sRGB2linear( const Vector3<T>& v )
|
||||
{
|
||||
return Vector3<T>(
|
||||
sRGB2linear( v.x ),
|
||||
sRGB2linear( v.y ),
|
||||
sRGB2linear( v.z ) );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Vector3<T> linear2sRGB( const Vector3<T>& v )
|
||||
{
|
||||
return Vector3<T>(
|
||||
linear2sRGB( v.x ),
|
||||
linear2sRGB( v.y ),
|
||||
linear2sRGB( v.z ) );
|
||||
}
|
||||
|
||||
#endif
|
|
@ -42,6 +42,7 @@ int fppPreProcess(struct fppTag *tags)
|
|||
{
|
||||
size_t i=0;
|
||||
ReturnCode ret; /* cpp return code */
|
||||
int retVal; /* fppPreProcess return code */
|
||||
struct Global *global;
|
||||
|
||||
global=(struct Global *)malloc(sizeof(struct Global));
|
||||
|
@ -144,10 +145,16 @@ int fppPreProcess(struct fppTag *tags)
|
|||
}
|
||||
fflush(stdout);
|
||||
// BK - fclose(stdout);
|
||||
delalldefines(global);
|
||||
|
||||
retVal = IO_NORMAL;
|
||||
if (global->errors > 0 && !global->eflag)
|
||||
return(IO_ERROR);
|
||||
return(IO_NORMAL); /* No errors or -E option set */
|
||||
retVal = IO_ERROR;
|
||||
free(global->tokenbuf);
|
||||
free(global->functionname);
|
||||
free(global->spacebuf);
|
||||
free(global);
|
||||
return retVal; /* No errors or -E option set */
|
||||
}
|
||||
|
||||
INLINE FILE_LOCAL
|
||||
|
|
|
@ -363,7 +363,7 @@ ReturnCode initdefines(struct Global *global)
|
|||
return(FPP_OK);
|
||||
}
|
||||
|
||||
void deldefines(struct Global *global)
|
||||
void delbuiltindefines(struct Global *global)
|
||||
{
|
||||
/*
|
||||
* Delete the built-in #define's.
|
||||
|
|
|
@ -619,12 +619,35 @@ DEFBUF *defendel(struct Global *global,
|
|||
}
|
||||
|
||||
|
||||
void delalldefines(struct Global *global)
|
||||
{
|
||||
/*
|
||||
* Delete all the defines in the tables and free memory
|
||||
*/
|
||||
|
||||
DEFBUF *dp;
|
||||
DEFBUF *prevp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SBSIZE; ++i)
|
||||
{
|
||||
prevp = global->symtab[i];
|
||||
while ((dp = prevp) != (DEFBUF *)NULL) {
|
||||
prevp = dp->link;
|
||||
free(dp->repl); /* Free the replacement */
|
||||
free((char *)dp); /* Free the symbol */
|
||||
}
|
||||
global->symtab[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void outdefines(struct Global *global)
|
||||
{
|
||||
DEFBUF *dp;
|
||||
DEFBUF **syp;
|
||||
|
||||
deldefines(global); /* Delete built-in #defines */
|
||||
delbuiltindefines(global); /* Delete built-in #defines */
|
||||
for (syp = global->symtab; syp < &global->symtab[SBSIZE]; syp++) {
|
||||
if ((dp = *syp) != (DEFBUF *) NULL) {
|
||||
do {
|
||||
|
|
|
@ -407,7 +407,8 @@ void dumpadef(char *, register DEFBUF *);
|
|||
#endif
|
||||
ReturnCode openfile(struct Global *,char *);
|
||||
int cget(struct Global *);
|
||||
void deldefines(struct Global *);
|
||||
void delbuiltindefines(struct Global *);
|
||||
void delalldefines(struct Global *);
|
||||
char *Getmem(struct Global *, int);
|
||||
ReturnCode openinclude(struct Global *, char *, int);
|
||||
ReturnCode expstuff(struct Global *, char *, char *);
|
||||
|
|
|
@ -14,18 +14,14 @@
|
|||
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Forsyth
|
||||
{
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned char byte;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// OptimizeFaces
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -36,13 +32,27 @@ namespace Forsyth
|
|||
// the number of indices in the list
|
||||
// vertexCount
|
||||
// the largest index value in indexList
|
||||
// vertexBaseIndex
|
||||
// starting vertex index subtracted from each index in indexList to
|
||||
// allow safe operation on multiple objects in a single index buffer
|
||||
// newIndexList
|
||||
// a pointer to a preallocated buffer the same size as indexList to
|
||||
// hold the optimized index list
|
||||
// lruCacheSize
|
||||
// the size of the simulated post-transform cache (max:64)
|
||||
//-----------------------------------------------------------------------------
|
||||
void OptimizeFaces(const uint16* indexList, uint indexCount, uint vertexCount, uint16* newIndexList, uint16 lruCacheSize);
|
||||
template<class IndexT>
|
||||
void OptimizeFacesImpl(const IndexT* indexList, uint32_t indexCount, uint32_t vertexCount, IndexT vertexBaseIndex, IndexT* newIndexList, uint16_t lruCacheSize);
|
||||
|
||||
void OptimizeFaces(const uint16_t* indexList, uint32_t indexCount, uint32_t vertexCount, uint16_t vertexBaseIndex, uint16_t* newIndexList, uint16_t lruCacheSize)
|
||||
{
|
||||
OptimizeFacesImpl<uint16_t>( indexList, indexCount, vertexCount, vertexBaseIndex, newIndexList, lruCacheSize );
|
||||
}
|
||||
|
||||
void OptimizeFaces(const uint32_t* indexList, uint32_t indexCount, uint32_t vertexCount, uint32_t vertexBaseIndex, uint32_t* newIndexList, uint16_t lruCacheSize)
|
||||
{
|
||||
OptimizeFacesImpl<uint32_t>( indexList, indexCount, vertexCount, vertexBaseIndex, newIndexList, lruCacheSize );
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -82,7 +92,7 @@ namespace Forsyth
|
|||
return score;
|
||||
}
|
||||
|
||||
float ComputeVertexValenceScore(uint numActiveFaces)
|
||||
float ComputeVertexValenceScore(uint32_t numActiveFaces)
|
||||
{
|
||||
const float FindVertexScore_ValenceBoostScale = 2.0f;
|
||||
const float FindVertexScore_ValenceBoostPower = 0.5f;
|
||||
|
@ -100,7 +110,7 @@ namespace Forsyth
|
|||
|
||||
|
||||
const int kMaxVertexCacheSize = 64;
|
||||
const uint kMaxPrecomputedVertexValenceScores = 64;
|
||||
const uint32_t kMaxPrecomputedVertexValenceScores = 64;
|
||||
float s_vertexCacheScores[kMaxVertexCacheSize+1][kMaxVertexCacheSize];
|
||||
float s_vertexValenceScores[kMaxPrecomputedVertexValenceScores];
|
||||
|
||||
|
@ -114,7 +124,7 @@ namespace Forsyth
|
|||
}
|
||||
}
|
||||
|
||||
for (uint valence=0; valence<kMaxPrecomputedVertexValenceScores; ++valence)
|
||||
for (uint32_t valence=0; valence<kMaxPrecomputedVertexValenceScores; ++valence)
|
||||
{
|
||||
s_vertexValenceScores[valence] = ComputeVertexValenceScore(valence);
|
||||
}
|
||||
|
@ -133,7 +143,7 @@ namespace Forsyth
|
|||
// return s_vertexValenceScores[numActiveTris];
|
||||
// }
|
||||
|
||||
float FindVertexScore(uint numActiveFaces, uint cachePosition, uint vertexCacheSize)
|
||||
float FindVertexScore(uint32_t numActiveFaces, uint32_t cachePosition, uint32_t vertexCacheSize)
|
||||
{
|
||||
assert(s_vertexScoresComputed); (void)s_vertexScoresComputed;
|
||||
|
||||
|
@ -163,37 +173,38 @@ namespace Forsyth
|
|||
|
||||
struct OptimizeVertexData
|
||||
{
|
||||
float score;
|
||||
uint activeFaceListStart;
|
||||
uint activeFaceListSize;
|
||||
uint16 cachePos0;
|
||||
uint16 cachePos1;
|
||||
float score;
|
||||
uint32_t activeFaceListStart;
|
||||
uint32_t activeFaceListSize;
|
||||
uint16_t cachePos0;
|
||||
uint16_t cachePos1;
|
||||
OptimizeVertexData() : score(0.f), activeFaceListStart(0), activeFaceListSize(0), cachePos0(0), cachePos1(0) { }
|
||||
};
|
||||
}
|
||||
|
||||
void OptimizeFaces(const uint16* indexList, uint indexCount, uint vertexCount, uint16* newIndexList, uint16 lruCacheSize)
|
||||
template<class IndexT>
|
||||
void OptimizeFacesImpl(const IndexT* indexList, uint32_t indexCount, uint32_t vertexCount, IndexT vertexBaseIndex, IndexT* newIndexList, uint16_t lruCacheSize)
|
||||
{
|
||||
std::vector<OptimizeVertexData> vertexDataList;
|
||||
std::vector< OptimizeVertexData > vertexDataList;
|
||||
vertexDataList.resize(vertexCount);
|
||||
|
||||
// compute face count per vertex
|
||||
for (uint i=0; i<indexCount; ++i)
|
||||
for (uint32_t i=0; i<indexCount; ++i)
|
||||
{
|
||||
uint16 index = indexList[i];
|
||||
assert(index < vertexCount);
|
||||
IndexT index = indexList[i] - vertexBaseIndex;
|
||||
assert((index >= 0) && (index < vertexCount));
|
||||
OptimizeVertexData& vertexData = vertexDataList[index];
|
||||
vertexData.activeFaceListSize++;
|
||||
}
|
||||
|
||||
std::vector<uint> activeFaceList;
|
||||
std::vector<uint32_t> activeFaceList;
|
||||
|
||||
const uint16 kEvictedCacheIndex = std::numeric_limits<uint16>::max();
|
||||
const IndexT kEvictedCacheIndex = std::numeric_limits<uint16_t>::max();
|
||||
|
||||
{
|
||||
// allocate face list per vertex
|
||||
uint curActiveFaceListPos = 0;
|
||||
for (uint i=0; i<vertexCount; ++i)
|
||||
uint32_t curActiveFaceListPos = 0;
|
||||
for (uint32_t i=0; i<vertexCount; ++i)
|
||||
{
|
||||
OptimizeVertexData& vertexData = vertexDataList[i];
|
||||
vertexData.cachePos0 = kEvictedCacheIndex;
|
||||
|
@ -207,45 +218,45 @@ namespace Forsyth
|
|||
}
|
||||
|
||||
// fill out face list per vertex
|
||||
for (uint i=0; i<indexCount; i+=3)
|
||||
for (uint32_t i=0; i<indexCount; i+=3)
|
||||
{
|
||||
for (uint j=0; j<3; ++j)
|
||||
for (uint32_t j=0; j<3; ++j)
|
||||
{
|
||||
uint16 index = indexList[i+j];
|
||||
IndexT index = indexList[i+j] - vertexBaseIndex;
|
||||
OptimizeVertexData& vertexData = vertexDataList[index];
|
||||
activeFaceList[vertexData.activeFaceListStart + vertexData.activeFaceListSize] = i;
|
||||
vertexData.activeFaceListSize++;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<byte> processedFaceList;
|
||||
std::vector<uint8_t> processedFaceList;
|
||||
processedFaceList.resize(indexCount);
|
||||
|
||||
uint16 vertexCacheBuffer[(kMaxVertexCacheSize+3)*2];
|
||||
uint16* cache0 = vertexCacheBuffer;
|
||||
uint16* cache1 = vertexCacheBuffer+(kMaxVertexCacheSize+3);
|
||||
uint16 entriesInCache0 = 0;
|
||||
IndexT vertexCacheBuffer[(kMaxVertexCacheSize+3)*2];
|
||||
IndexT* cache0 = vertexCacheBuffer;
|
||||
IndexT* cache1 = vertexCacheBuffer+(kMaxVertexCacheSize+3);
|
||||
IndexT entriesInCache0 = 0;
|
||||
|
||||
uint bestFace = 0;
|
||||
uint32_t bestFace = 0;
|
||||
float bestScore = -1.f;
|
||||
|
||||
const float maxValenceScore = FindVertexScore(1, kEvictedCacheIndex, lruCacheSize) * 3.f;
|
||||
|
||||
for (uint i = 0; i < indexCount; i += 3)
|
||||
for (uint32_t i = 0; i < indexCount; i += 3)
|
||||
{
|
||||
if (bestScore < 0.f)
|
||||
{
|
||||
// no verts in the cache are used by any unprocessed faces so
|
||||
// search all unprocessed faces for a new starting point
|
||||
for (uint j = 0; j < indexCount; j += 3)
|
||||
for (uint32_t j = 0; j < indexCount; j += 3)
|
||||
{
|
||||
if (processedFaceList[j] == 0)
|
||||
{
|
||||
uint face = j;
|
||||
uint32_t face = j;
|
||||
float faceScore = 0.f;
|
||||
for (uint k=0; k<3; ++k)
|
||||
for (uint32_t k=0; k<3; ++k)
|
||||
{
|
||||
uint16 index = indexList[face+k];
|
||||
IndexT index = indexList[face+k] - vertexBaseIndex;
|
||||
OptimizeVertexData& vertexData = vertexDataList[index];
|
||||
assert(vertexData.activeFaceListSize > 0);
|
||||
assert(vertexData.cachePos0 >= lruCacheSize);
|
||||
|
@ -269,13 +280,13 @@ namespace Forsyth
|
|||
}
|
||||
|
||||
processedFaceList[bestFace] = 1;
|
||||
uint16 entriesInCache1 = 0;
|
||||
uint16_t entriesInCache1 = 0;
|
||||
|
||||
// add bestFace to LRU cache and to newIndexList
|
||||
for (uint v = 0; v < 3; ++v)
|
||||
for (uint32_t v = 0; v < 3; ++v)
|
||||
{
|
||||
uint16 index = indexList[bestFace+v];
|
||||
newIndexList[i+v] = index;
|
||||
IndexT index = indexList[bestFace+v] - vertexBaseIndex;
|
||||
newIndexList[i+v] = index + vertexBaseIndex;
|
||||
|
||||
OptimizeVertexData& vertexData = vertexDataList[index];
|
||||
|
||||
|
@ -292,9 +303,9 @@ namespace Forsyth
|
|||
}
|
||||
|
||||
assert(vertexData.activeFaceListSize > 0);
|
||||
uint* begin = &activeFaceList[vertexData.activeFaceListStart];
|
||||
uint* end = &(activeFaceList[vertexData.activeFaceListStart + vertexData.activeFaceListSize - 1]) + 1;
|
||||
uint* it = std::find(begin, end, bestFace);
|
||||
uint32_t* begin = &activeFaceList[vertexData.activeFaceListStart];
|
||||
uint32_t* end = &(activeFaceList[vertexData.activeFaceListStart + vertexData.activeFaceListSize - 1]) + 1;
|
||||
uint32_t* it = std::find(begin, end, bestFace);
|
||||
assert(it != end);
|
||||
std::swap(*it, *(end-1));
|
||||
--vertexData.activeFaceListSize;
|
||||
|
@ -303,9 +314,9 @@ namespace Forsyth
|
|||
}
|
||||
|
||||
// move the rest of the old verts in the cache down and compute their new scores
|
||||
for (uint c0 = 0; c0 < entriesInCache0; ++c0)
|
||||
for (uint32_t c0 = 0; c0 < entriesInCache0; ++c0)
|
||||
{
|
||||
uint16 index = cache0[c0];
|
||||
IndexT index = cache0[c0];
|
||||
OptimizeVertexData& vertexData = vertexDataList[index];
|
||||
|
||||
if (vertexData.cachePos1 >= entriesInCache1)
|
||||
|
@ -318,19 +329,19 @@ namespace Forsyth
|
|||
|
||||
// find the best scoring triangle in the current cache (including up to 3 that were just evicted)
|
||||
bestScore = -1.f;
|
||||
for (uint c1 = 0; c1 < entriesInCache1; ++c1)
|
||||
for (uint32_t c1 = 0; c1 < entriesInCache1; ++c1)
|
||||
{
|
||||
uint16 index = cache1[c1];
|
||||
IndexT index = cache1[c1];
|
||||
OptimizeVertexData& vertexData = vertexDataList[index];
|
||||
vertexData.cachePos0 = vertexData.cachePos1;
|
||||
vertexData.cachePos1 = kEvictedCacheIndex;
|
||||
for (uint j=0; j<vertexData.activeFaceListSize; ++j)
|
||||
for (uint32_t j=0; j<vertexData.activeFaceListSize; ++j)
|
||||
{
|
||||
uint face = activeFaceList[vertexData.activeFaceListStart+j];
|
||||
uint32_t face = activeFaceList[vertexData.activeFaceListStart+j];
|
||||
float faceScore = 0.f;
|
||||
for (uint v=0; v<3; v++)
|
||||
for (uint32_t v=0; v<3; v++)
|
||||
{
|
||||
uint16 faceIndex = indexList[face+v];
|
||||
IndexT faceIndex = indexList[face+v] - vertexBaseIndex;
|
||||
OptimizeVertexData& faceVertexData = vertexDataList[faceIndex];
|
||||
faceScore += faceVertexData.score;
|
||||
}
|
||||
|
|
|
@ -21,23 +21,27 @@
|
|||
|
||||
namespace Forsyth
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
// OptimizeFaces
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parameters:
|
||||
// indexList
|
||||
// input index list
|
||||
// indexCount
|
||||
// the number of indices in the list
|
||||
// vertexCount
|
||||
// the largest index value in indexList
|
||||
// newIndexList
|
||||
// a pointer to a preallocated buffer the same size as indexList to
|
||||
// hold the optimized index list
|
||||
// lruCacheSize
|
||||
// the size of the simulated post-transform cache (max:64)
|
||||
//-----------------------------------------------------------------------------
|
||||
void OptimizeFaces(const uint16_t* indexList, uint32_t indexCount, uint32_t vertexCount, uint16_t* newIndexList, uint16_t lruCacheSize);
|
||||
//-----------------------------------------------------------------------------
|
||||
// OptimizeFaces
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parameters:
|
||||
// indexList
|
||||
// input index list
|
||||
// indexCount
|
||||
// the number of indices in the list
|
||||
// vertexCount
|
||||
// the largest index value in indexList
|
||||
// vertexBaseIndex
|
||||
// starting vertex index subtracted from each index in indexList to
|
||||
// allow safe operation on multiple objects in a single index buffer
|
||||
// newIndexList
|
||||
// a pointer to a preallocated buffer the same size as indexList to
|
||||
// hold the optimized index list
|
||||
// lruCacheSize
|
||||
// the size of the simulated post-transform cache (max:64)
|
||||
//-----------------------------------------------------------------------------
|
||||
void OptimizeFaces(const uint16_t* indexList, uint32_t indexCount, uint32_t vertexCount, uint16_t vertexBaseIndex, uint16_t* newIndexList, uint16_t lruCacheSize);
|
||||
void OptimizeFaces(const uint32_t* indexList, uint32_t indexCount, uint32_t vertexCount, uint32_t vertexBaseIndex, uint32_t* newIndexList, uint16_t lruCacheSize);
|
||||
|
||||
} // namespace Forsyth
|
||||
|
||||
|
|
|
@ -73,10 +73,8 @@
|
|||
// BK - STFU!
|
||||
# pragma GCC diagnostic ignored "-Wunknown-pragmas" // for clang to disable GCC pragmas
|
||||
# pragma GCC diagnostic ignored "-Wpragmas" // for GCC to disable clang pragmas
|
||||
# pragma GCC diagnostic ignored "-Wformat="
|
||||
# pragma GCC diagnostic ignored "-Wformat-extra-args"
|
||||
# pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
# pragma GCC diagnostic ignored "-Wreorder"
|
||||
# pragma GCC diagnostic ignored "-Woverloaded-virtual"
|
||||
|
@ -85,6 +83,13 @@
|
|||
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
# pragma GCC diagnostic ignored "-Wunused-private-field"
|
||||
# pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
# pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
||||
|
||||
# if !defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Wformat="
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -161,6 +161,9 @@ lod_exists_in_stage(const _mesa_glsl_parse_state *state)
|
|||
*/
|
||||
return state->stage == MESA_SHADER_VERTEX ||
|
||||
state->is_version(130, 300) ||
|
||||
state->EXT_texture_array_enable || /* BK - don't complain about texture array in fragment shaders. */
|
||||
state->OES_texture_3D_enable || /* BK - shut up */
|
||||
state->EXT_shader_texture_lod_enable || /* BK - pretend it's ok too */
|
||||
state->ARB_shader_texture_lod_enable;
|
||||
}
|
||||
|
||||
|
|
|
@ -170,6 +170,10 @@ struct glslopt_shader
|
|||
{
|
||||
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++)
|
||||
ralloc_free(whole_program->_LinkedShaders[i]);
|
||||
for(GLuint i =0;i< whole_program->NumShaders;i++)
|
||||
ralloc_free(whole_program->Shaders[i]);
|
||||
ralloc_free(whole_program->Shaders);
|
||||
ralloc_free(whole_program->InfoLog);
|
||||
ralloc_free(whole_program);
|
||||
ralloc_free(rawOutput);
|
||||
ralloc_free(optimizedOutput);
|
||||
|
|
|
@ -568,9 +568,9 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
|
|||
EXT(EXT_separate_shader_objects, false, true, dummy_true),
|
||||
EXT(EXT_shader_framebuffer_fetch, false, true, EXT_shader_framebuffer_fetch),
|
||||
EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix),
|
||||
EXT(EXT_shader_texture_lod, false, true, ARB_shader_texture_lod),
|
||||
EXT(EXT_shader_texture_lod, true, true, ARB_shader_texture_lod), // BK - made it available in GLSL
|
||||
EXT(EXT_shadow_samplers, false, true, EXT_shadow_samplers),
|
||||
EXT(EXT_texture_array, true, false, EXT_texture_array),
|
||||
EXT(EXT_texture_array, true, true, EXT_texture_array), // BK - made it available in ESSL
|
||||
};
|
||||
|
||||
#undef EXT
|
||||
|
|
|
@ -7,7 +7,7 @@ version: "{build}"
|
|||
os: Visual Studio 2013
|
||||
|
||||
platform:
|
||||
- Any CPU
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
|
@ -17,6 +17,13 @@ branches:
|
|||
only:
|
||||
- master
|
||||
|
||||
# Travis advances the master-tot tag to current top of the tree after
|
||||
# each push into the master branch, because it relies on that tag to
|
||||
# upload build artifacts to the master-tot release. This will cause
|
||||
# double testing for each push on Appveyor: one for the push, one for
|
||||
# the tag advance. Disable testing tags.
|
||||
skip_tags: true
|
||||
|
||||
clone_depth: 5
|
||||
|
||||
matrix:
|
||||
|
@ -25,6 +32,7 @@ matrix:
|
|||
# scripts that run after cloning repository
|
||||
install:
|
||||
- git clone https://github.com/google/googletest.git External/googletest
|
||||
- C:/Python27/python.exe update_glslang_sources.py
|
||||
|
||||
build:
|
||||
parallel: true # enable MSBuild parallel builds
|
||||
|
@ -38,3 +46,45 @@ build_script:
|
|||
test_script:
|
||||
- ctest -C %CONFIGURATION% --output-on-failure
|
||||
- cd ../Test && bash runtests
|
||||
- cd ../build
|
||||
|
||||
after_test:
|
||||
# For debug build, the generated dll has a postfix "d" in its name.
|
||||
- ps: >-
|
||||
If ($env:configuration -Match "Debug") {
|
||||
$env:SUFFIX="d"
|
||||
} Else {
|
||||
$env:SUFFIX=""
|
||||
}
|
||||
- cd install
|
||||
# Zip all glslang artifacts for uploading and deploying
|
||||
- 7z a glslang-master-windows-"%PLATFORM%"-"%CONFIGURATION%".zip
|
||||
bin\glslangValidator.exe
|
||||
include\glslang\*
|
||||
include\SPIRV\*
|
||||
lib\glslang%SUFFIX%.lib
|
||||
lib\HLSL%SUFFIX%.lib
|
||||
lib\OGLCompiler%SUFFIX%.lib
|
||||
lib\OSDependent%SUFFIX%.lib
|
||||
lib\SPIRV%SUFFIX%.lib
|
||||
lib\SPVRemapper%SUFFIX%.lib
|
||||
lib\SPIRV-Tools%SUFFIX%.lib
|
||||
lib\SPIRV-Tools-opt%SUFFIX%.lib
|
||||
|
||||
artifacts:
|
||||
- path: build\install\*.zip
|
||||
name: artifacts-zip
|
||||
|
||||
deploy:
|
||||
- provider: GitHub
|
||||
auth_token:
|
||||
secure: YglcSYdl0TylEa59H4K6lylBEDr586NAt2EMgZquSo+iuPrwgZQuJLPCoihSm9y6
|
||||
release: master-tot
|
||||
description: "Continuous build of the latest master branch by Appveyor and Travis CI"
|
||||
artifact: artifacts-zip
|
||||
draft: false
|
||||
prerelease: false
|
||||
force_update: true
|
||||
on:
|
||||
branch: master
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
|
|
|
@ -6,8 +6,5 @@ tags
|
|||
TAGS
|
||||
build/
|
||||
Test/localResults/
|
||||
Test/multiThread.out
|
||||
Test/singleThread.out
|
||||
Test/vert.spv
|
||||
Test/frag.spv
|
||||
External/googletest
|
||||
External/spirv-tools
|
||||
|
|
|
@ -7,12 +7,15 @@ os:
|
|||
- osx
|
||||
|
||||
# Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment.
|
||||
sudo: required
|
||||
sudo: false
|
||||
dist: trusty
|
||||
|
||||
env:
|
||||
- GLSLANG_BUILD_TYPE=Release
|
||||
- GLSLANG_BUILD_TYPE=Debug
|
||||
global:
|
||||
- secure: aGFrgzyKp+84hKrGkxVWg8cHV61uqrKEHT38gfSQK6+WS4GfLOyH83p7WnsEBb7AMhzU7LMNFdvOFr6+NaMpVnqRvc40CEG1Q+lNg9Pq9mhIZLowvDrfqTL9kQ+8Nbw5Q6/dg6CTvY7fvRfpfCEmKIUZBRkoKUuHeuM1uy3IupFcdNuL5bSYn3Beo+apSJginh9DI4BLDXFUgBzTRSLLyCX5g3cpaeGGOCr8quJlYx75W6HRck5g9SZuLtUoH9GFEV3l+ZEWB8noErW+J56L03bwNwFuuAh321evw++oQk5KFa8rlDvar3SJ3b1RHB8u/eq5DBYMyaK/fS8+Q7QbGr8diF/wDe68bKO7U9IhpNfExXmczCpExjHomW5TQv4rYdGhygPMfW97aIsPRYyNKcl4fkmb7NDrM8w0Jscdq2g5c2Kz0ItyZoBri/NXLwFQQjaVCs7Pf97TjuMA7mK0GJmDTRzi6SrDYlWMt5BQL3y0CCojyfLIRcTh0CQjQI29s97bLfQrYAxt9GNNFR+HTXRLLrkaAlJkPGEPwUywlSfEThnvHLesNxYqemolAYpQT4ithoL4GehGIHmaxsW295aKVhuRf8K9eBODNqrfblvM42UHhjntT+92ZnQ/Gkq80GqaMxnxi4PO5FyPIxt0r981b54YBkWi8YA4P7w5pNI=
|
||||
matrix:
|
||||
- GLSLANG_BUILD_TYPE=Release
|
||||
- GLSLANG_BUILD_TYPE=Debug
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
|
@ -24,6 +27,9 @@ matrix:
|
|||
# Skip GCC builds on Mac OS X.
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
include:
|
||||
# Additional build using Android NDK.
|
||||
- env: BUILD_NDK=ON
|
||||
|
||||
cache:
|
||||
apt: true
|
||||
|
@ -36,25 +42,82 @@ addons:
|
|||
apt:
|
||||
packages:
|
||||
- clang-3.6
|
||||
- ninja-build
|
||||
|
||||
install:
|
||||
# Install ninja on Mac OS X.
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update && brew install ninja; fi
|
||||
# Make sure that clang-3.6 is selected.
|
||||
# Make sure that clang-3.6 is selected on Linux.
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "clang" ]]; then
|
||||
export CC=clang-3.6 CXX=clang++-3.6;
|
||||
fi
|
||||
# Download Android NDK and Android CMake toolchain file.
|
||||
- if [[ "$BUILD_NDK" == "ON" ]]; then
|
||||
git clone --depth=1 https://github.com/urho3d/android-ndk.git $HOME/android-ndk;
|
||||
export ANDROID_NDK=$HOME/android-ndk;
|
||||
git clone --depth=1 https://github.com/taka-no-me/android-cmake.git $HOME/android-cmake;
|
||||
export TOOLCHAIN_PATH=$HOME/android-cmake/android.toolchain.cmake;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- git clone https://github.com/google/googletest.git External/googletest
|
||||
- git clone --depth=1 https://github.com/google/googletest.git External/googletest
|
||||
- ./update_glslang_sources.py
|
||||
|
||||
script:
|
||||
- mkdir build && cd build
|
||||
# We need to install the compiled binaries so the paths in the runtests script can resolve correctly.
|
||||
- cmake -GNinja -DCMAKE_BUILD_TYPE=${GLSLANG_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=`pwd`/install ..
|
||||
- ninja install
|
||||
# Run Google-Test-based tests.
|
||||
- ctest --output-on-failure
|
||||
# Run runtests-based tests.
|
||||
- cd ../Test && ./runtests
|
||||
# For Android, do release building using NDK without testing.
|
||||
# For Linux and macOS, do debug/release building with testing.
|
||||
- if [[ "$BUILD_NDK" == "ON" ]]; then
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_PATH}
|
||||
-DANDROID_NATIVE_API_LEVEL=android-12
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DANDROID_ABI="armeabi-v7a with NEON"
|
||||
-DBUILD_TESTING=OFF ..;
|
||||
make -j4;
|
||||
else
|
||||
cmake -DCMAKE_BUILD_TYPE=${GLSLANG_BUILD_TYPE}
|
||||
-DCMAKE_INSTALL_PREFIX=`pwd`/install ..;
|
||||
make -j4 install;
|
||||
ctest --output-on-failure &&
|
||||
cd ../Test && ./runtests;
|
||||
fi
|
||||
|
||||
after_success:
|
||||
# For debug build, the generated dll has a postfix "d" in its name.
|
||||
- if [[ "${GLSLANG_BUILD_TYPE}" == "Debug" ]]; then
|
||||
export SUFFIX="d";
|
||||
else
|
||||
export SUFFIX="";
|
||||
fi
|
||||
# Create tarball for deployment
|
||||
- if [[ ${CC} == clang* && "${BUILD_NDK}" != "ON" ]]; then
|
||||
cd ../build/install;
|
||||
export TARBALL=glslang-master-${TRAVIS_OS_NAME}-${GLSLANG_BUILD_TYPE}.zip;
|
||||
zip ${TARBALL}
|
||||
bin/glslangValidator
|
||||
include/glslang/*
|
||||
include/SPIRV/*
|
||||
lib/libglslang${SUFFIX}.a
|
||||
lib/libHLSL${SUFFIX}.a
|
||||
lib/libOGLCompiler${SUFFIX}.a
|
||||
lib/libOSDependent${SUFFIX}.a
|
||||
lib/libSPIRV${SUFFIX}.a
|
||||
lib/libSPVRemapper${SUFFIX}.a
|
||||
lib/libSPIRV-Tools${SUFFIX}.a
|
||||
lib/libSPIRV-Tools-opt${SUFFIX}.a;
|
||||
fi
|
||||
|
||||
before_deploy:
|
||||
# Tag the current top of the tree as "master-tot".
|
||||
# Travis CI replies on the tag name to properly push to GitHub Releases.
|
||||
- git config --global user.name "Travis CI"
|
||||
- git config --global user.email "builds@travis-ci.org"
|
||||
- git tag -f master-tot
|
||||
- git push -q -f https://${glslangtoken}@github.com/KhronosGroup/glslang --tags
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: ${glslangtoken}
|
||||
on:
|
||||
branch: master
|
||||
condition: ${CC} == clang* && ${BUILD_NDK} != ON
|
||||
file: ${TARBALL}
|
||||
skip_cleanup: true
|
||||
overwrite: true
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
cmake_minimum_required(VERSION 2.8.11)
|
||||
# increase to 3.1 once all major distributions
|
||||
# include a version of CMake >= 3.1
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
endif()
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# Adhere to GNU filesystem layout conventions
|
||||
include(GNUInstallDirs)
|
||||
|
||||
option(SKIP_GLSLANG_INSTALL "Skip installation" ${SKIP_GLSLANG_INSTALL})
|
||||
if(NOT ${SKIP_GLSLANG_INSTALL})
|
||||
set(ENABLE_GLSLANG_INSTALL ON)
|
||||
endif()
|
||||
|
||||
option(ENABLE_AMD_EXTENSIONS "Enables support of AMD-specific extensions" ON)
|
||||
option(ENABLE_GLSLANG_BINARIES "Builds glslangValidator and spirv-remap" ON)
|
||||
|
||||
|
@ -8,11 +21,15 @@ option(ENABLE_NV_EXTENSIONS "Enables support of Nvidia-specific extensions" ON)
|
|||
|
||||
option(ENABLE_HLSL "Enables HLSL input support" ON)
|
||||
|
||||
enable_testing()
|
||||
option(ENABLE_OPT "Enables spirv-opt capability if present" ON)
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "prefix")
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND WIN32)
|
||||
set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "..." FORCE)
|
||||
endif()
|
||||
|
||||
project(glslang)
|
||||
# make testing optional
|
||||
include(CTest)
|
||||
|
||||
if(ENABLE_AMD_EXTENSIONS)
|
||||
add_definitions(-DAMD_EXTENSIONS)
|
||||
|
@ -33,42 +50,59 @@ if(WIN32)
|
|||
endif(MSVC)
|
||||
add_definitions(-DGLSLANG_OSINCLUDE_WIN32)
|
||||
elseif(UNIX)
|
||||
add_definitions(-fPIC)
|
||||
add_definitions(-DGLSLANG_OSINCLUDE_UNIX)
|
||||
else(WIN32)
|
||||
message("unknown platform")
|
||||
endif(WIN32)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
add_definitions(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs
|
||||
-Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable)
|
||||
add_definitions(-Wno-reorder) # disable this from -Wall, since it happens all over.
|
||||
add_definitions(-std=c++11)
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||
add_compile_options(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs
|
||||
-Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions)
|
||||
add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over.
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||
add_definitions(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs
|
||||
-Wunused-parameter -Wunused-value -Wunused-variable)
|
||||
add_definitions(-Wno-reorder) # disable this from -Wall, since it happens all over.
|
||||
add_definitions(-std=c++11)
|
||||
add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs
|
||||
-Wunused-parameter -Wunused-value -Wunused-variable)
|
||||
add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over.
|
||||
endif()
|
||||
|
||||
# Request C++11
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.1)
|
||||
# CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD
|
||||
# remove this block once CMake >=3.1 has fixated in the ecosystem
|
||||
add_compile_options(-std=c++11)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
|
||||
function(glslang_set_link_args TARGET)
|
||||
# For MinGW compiles, statically link against the GCC and C++ runtimes.
|
||||
# This avoids the need to ship those runtimes as DLLs.
|
||||
if(WIN32)
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||
set_target_properties(${TARGET} PROPERTIES
|
||||
LINK_FLAGS "-static -static-libgcc -static-libstdc++")
|
||||
endif()
|
||||
endif(WIN32)
|
||||
if(WIN32 AND ${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||
set_target_properties(${TARGET} PROPERTIES
|
||||
LINK_FLAGS "-static -static-libgcc -static-libstdc++")
|
||||
endif()
|
||||
endfunction(glslang_set_link_args)
|
||||
|
||||
# We depend on these for later projects, so they should come first.
|
||||
add_subdirectory(External)
|
||||
|
||||
if(NOT TARGET SPIRV-Tools-opt)
|
||||
set(ENABLE_OPT OFF)
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPT)
|
||||
message(STATUS "optimizer enabled")
|
||||
add_definitions(-DENABLE_OPT)
|
||||
elseif(ENABLE_HLSL)
|
||||
message(STATUS "spirv-tools not linked - illegal SPIRV may be generated for HLSL")
|
||||
endif()
|
||||
|
||||
add_subdirectory(glslang)
|
||||
add_subdirectory(OGLCompilersDLL)
|
||||
if(ENABLE_GLSLANG_BINARIES)
|
||||
add_subdirectory(StandAlone)
|
||||
add_subdirectory(StandAlone)
|
||||
endif()
|
||||
add_subdirectory(SPIRV)
|
||||
if(ENABLE_HLSL)
|
||||
|
|
|
@ -1,34 +1,43 @@
|
|||
# Suppress all warnings from external projects.
|
||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w)
|
||||
|
||||
if (TARGET gmock)
|
||||
message(STATUS "Google Mock already configured - use it")
|
||||
elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
|
||||
# We need to make sure Google Test does not mess up with the
|
||||
# global CRT settings on Windows.
|
||||
if(WIN32)
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
endif(WIN32)
|
||||
add_subdirectory(googletest)
|
||||
set(GTEST_TARGETS
|
||||
gtest
|
||||
gtest_main
|
||||
gmock
|
||||
gmock_main
|
||||
)
|
||||
foreach(target ${GTEST_TARGETS})
|
||||
set_property(TARGET ${target} PROPERTY FOLDER gtest)
|
||||
endforeach()
|
||||
mark_as_advanced(gmock_build_tests
|
||||
BUILD_GMOCK
|
||||
BUILD_GTEST
|
||||
BUILD_SHARED_LIBS
|
||||
gtest_build_samples
|
||||
gtest_build_tests
|
||||
gtest_disable_pthreads
|
||||
gtest_force_shared_crt
|
||||
gtest_hide_internal_symbols)
|
||||
else()
|
||||
message(STATUS
|
||||
"Google Mock was not found - tests based on that will not build")
|
||||
if(BUILD_TESTING)
|
||||
if(TARGET gmock)
|
||||
message(STATUS "Google Mock already configured - use it")
|
||||
elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
|
||||
# We need to make sure Google Test does not mess up with the
|
||||
# global CRT settings on Windows.
|
||||
if(WIN32)
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
endif(WIN32)
|
||||
add_subdirectory(googletest)
|
||||
set(GTEST_TARGETS
|
||||
gtest
|
||||
gtest_main
|
||||
gmock
|
||||
gmock_main)
|
||||
foreach(target ${GTEST_TARGETS})
|
||||
set_property(TARGET ${target} PROPERTY FOLDER gtest)
|
||||
endforeach()
|
||||
mark_as_advanced(gmock_build_tests
|
||||
BUILD_GMOCK
|
||||
BUILD_GTEST
|
||||
BUILD_SHARED_LIBS
|
||||
gtest_build_samples
|
||||
gtest_build_tests
|
||||
gtest_disable_pthreads
|
||||
gtest_force_shared_crt
|
||||
gtest_hide_internal_symbols)
|
||||
else()
|
||||
message(STATUS
|
||||
"Google Mock was not found - tests based on that will not build")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPT AND NOT TARGET SPIRV-Tools-opt)
|
||||
if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/spirv-tools)
|
||||
set(SPIRV_SKIP_TESTS ON CACHE BOOL "Skip building SPIRV-Tools tests")
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/spirv-tools spirv-tools)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -2,10 +2,13 @@ set(SOURCES InitializeDll.cpp InitializeDll.h)
|
|||
|
||||
add_library(OGLCompiler STATIC ${SOURCES})
|
||||
set_property(TARGET OGLCompiler PROPERTY FOLDER glslang)
|
||||
set_property(TARGET OGLCompiler PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if(WIN32)
|
||||
source_group("Source" FILES ${SOURCES})
|
||||
endif(WIN32)
|
||||
|
||||
install(TARGETS OGLCompiler
|
||||
ARCHIVE DESTINATION lib)
|
||||
if(ENABLE_GLSLANG_INSTALL)
|
||||
install(TARGETS OGLCompiler
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif(ENABLE_GLSLANG_INSTALL)
|
||||
|
|
|
@ -38,13 +38,17 @@
|
|||
|
||||
#include "InitializeDll.h"
|
||||
#include "../glslang/Include/InitializeGlobals.h"
|
||||
|
||||
#include "../glslang/Public/ShaderLang.h"
|
||||
#include "../glslang/Include/PoolAlloc.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
|
||||
|
||||
// Per-process initialization.
|
||||
// Needs to be called at least once before parsing, etc. is done.
|
||||
// Will also do thread initialization for the calling thread; other
|
||||
// threads will need to do that explicitly.
|
||||
bool InitProcess()
|
||||
{
|
||||
glslang::GetGlobalLock();
|
||||
|
@ -85,7 +89,9 @@ bool InitProcess()
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Per-thread scoped initialization.
|
||||
// Must be called at least once by each new thread sharing the
|
||||
// symbol tables, etc., needed to parse.
|
||||
bool InitThread()
|
||||
{
|
||||
//
|
||||
|
@ -99,17 +105,21 @@ bool InitThread()
|
|||
if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
|
||||
return true;
|
||||
|
||||
InitializeMemoryPools();
|
||||
|
||||
if (! OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
|
||||
assert(0 && "InitThread(): Unable to set init flag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
glslang::SetThreadPoolAllocator(nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Not necessary to call this: InitThread() is reentrant, and the need
|
||||
// to do per thread tear down has been removed.
|
||||
//
|
||||
// This is kept, with memory management removed, to satisfy any exiting
|
||||
// calls to it that rely on it.
|
||||
bool DetachThread()
|
||||
{
|
||||
bool success = true;
|
||||
|
@ -125,14 +135,18 @@ bool DetachThread()
|
|||
assert(0 && "DetachThread(): Unable to clear init flag.");
|
||||
success = false;
|
||||
}
|
||||
|
||||
FreeGlobalPools();
|
||||
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Not necessary to call this: InitProcess() is reentrant.
|
||||
//
|
||||
// This is kept, with memory management removed, to satisfy any exiting
|
||||
// calls to it that rely on it.
|
||||
//
|
||||
// Users of glslang should call shFinalize() or glslang::FinalizeProcess() for
|
||||
// process-scoped memory tear down.
|
||||
bool DetachProcess()
|
||||
{
|
||||
bool success = true;
|
||||
|
@ -140,12 +154,8 @@ bool DetachProcess()
|
|||
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
|
||||
return true;
|
||||
|
||||
ShFinalize();
|
||||
|
||||
success = DetachThread();
|
||||
|
||||
FreePoolIndex();
|
||||
|
||||
OS_FreeTLSIndex(ThreadInitializeIndex);
|
||||
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ namespace glslang {
|
|||
|
||||
bool InitProcess();
|
||||
bool InitThread();
|
||||
bool DetachThread();
|
||||
bool DetachProcess();
|
||||
bool DetachThread(); // not called from standalone, perhaps other tools rely on parts of it
|
||||
bool DetachProcess(); // not called from standalone, perhaps other tools rely on parts of it
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
|
|
|
@ -49,21 +49,30 @@ There is also a non-shader extension
|
|||
Building
|
||||
--------
|
||||
|
||||
Instead of building manually, you can also download the binaries for your
|
||||
platform directly from the [master-tot release][master-tot-release] on GitHub.
|
||||
Those binaries are automatically uploaded by the buildbots after successful
|
||||
testing and they always reflect the current top of the tree of the master
|
||||
branch.
|
||||
|
||||
### Dependencies
|
||||
|
||||
* A C++11 compiler
|
||||
* [CMake][cmake]: for generating compilation targets.
|
||||
* make: _Linux_, ninja is an alternative, if configured.
|
||||
* [Python 2.7][python]: for executing SPIRV-Tools scripts. (Optional if not using SPIRV-Tools.)
|
||||
* [bison][bison]: _optional_, but needed when changing the grammar (glslang.y).
|
||||
* [googletest][googletest]: _optional_, but should use if making any changes to glslang.
|
||||
|
||||
### Build steps
|
||||
|
||||
The following steps assume a Bash shell. On Windows, that could be the Git Bash
|
||||
shell or some other shell of your choosing.
|
||||
|
||||
#### 1) Check-Out this project
|
||||
|
||||
```bash
|
||||
cd <parent of where you want glslang to be>
|
||||
# If using SSH
|
||||
git clone git@github.com:KhronosGroup/glslang.git
|
||||
# Or if using HTTPS
|
||||
git clone https://github.com/KhronosGroup/glslang.git
|
||||
```
|
||||
|
||||
|
@ -74,24 +83,35 @@ cd <the directory glslang was cloned to, "External" will be a subdirectory>
|
|||
git clone https://github.com/google/googletest.git External/googletest
|
||||
```
|
||||
|
||||
#### 3) Configure
|
||||
|
||||
Assume the source directory is `$SOURCE_DIR` and
|
||||
the build directory is `$BUILD_DIR`:
|
||||
|
||||
For building on Linux (assuming using the Ninja generator):
|
||||
If you wish to assure that SPIR-V generated from HLSL is legal for Vulkan,
|
||||
or wish to invoke -Os to reduce SPIR-V size from HLSL or GLSL, install
|
||||
spirv-tools with this:
|
||||
|
||||
```bash
|
||||
cd $BUILD_DIR
|
||||
./update_glslang_sources.py
|
||||
```
|
||||
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE={Debug|Release|RelWithDebInfo} \
|
||||
-DCMAKE_INSTALL_PREFIX=`pwd`/install $SOURCE_DIR
|
||||
#### 3) Configure
|
||||
|
||||
Assume the source directory is `$SOURCE_DIR` and the build directory is
|
||||
`$BUILD_DIR`. First ensure the build directory exists, then navigate to it:
|
||||
|
||||
```bash
|
||||
mkdir -p $BUILD_DIR
|
||||
cd $BUILD_DIR
|
||||
```
|
||||
|
||||
For building on Linux:
|
||||
|
||||
```bash
|
||||
cmake -DCMAKE_BUILD_TYPE={Debug|Release|RelWithDebInfo} \
|
||||
-DCMAKE_INSTALL_PREFIX="$(pwd)/install" $SOURCE_DIR
|
||||
```
|
||||
|
||||
For building on Windows:
|
||||
|
||||
```bash
|
||||
cmake $SOURCE_DIR -DCMAKE_INSTALL_PREFIX=`pwd`/install
|
||||
cmake $SOURCE_DIR -DCMAKE_INSTALL_PREFIX="$(pwd)/install"
|
||||
# The CMAKE_INSTALL_PREFIX part is for testing (explained later).
|
||||
```
|
||||
|
||||
|
@ -101,7 +121,7 @@ The CMake GUI also works for Windows (version 3.4.1 tested).
|
|||
|
||||
```bash
|
||||
# for Linux:
|
||||
ninja install
|
||||
make -j4 install
|
||||
|
||||
# for Windows:
|
||||
cmake --build . --config {Release|Debug|MinSizeRel|RelWithDebInfo} \
|
||||
|
@ -301,6 +321,8 @@ Basic Internal Operation
|
|||
|
||||
|
||||
[cmake]: https://cmake.org/
|
||||
[python]: https://www.python.org/
|
||||
[bison]: https://www.gnu.org/software/bison/
|
||||
[googletest]: https://github.com/google/googletest
|
||||
[bison-gnu-win32]: http://gnuwin32.sourceforge.net/packages/bison.htm
|
||||
[master-tot-release]: https://github.com/KhronosGroup/glslang/releases/tag/master-tot
|
||||
|
|
|
@ -41,17 +41,30 @@ endif(ENABLE_NV_EXTENSIONS)
|
|||
|
||||
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
|
||||
set_property(TARGET SPIRV PROPERTY FOLDER glslang)
|
||||
target_link_libraries(SPIRV glslang)
|
||||
set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
add_library(SPVRemapper STATIC ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS})
|
||||
set_property(TARGET SPVRemapper PROPERTY FOLDER glslang)
|
||||
set_property(TARGET SPVRemapper PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if(ENABLE_OPT)
|
||||
target_include_directories(SPIRV
|
||||
PRIVATE ${spirv-tools_SOURCE_DIR}/include
|
||||
PRIVATE ${spirv-tools_SOURCE_DIR}/source
|
||||
)
|
||||
target_link_libraries(SPIRV glslang SPIRV-Tools-opt SPVRemapper)
|
||||
else()
|
||||
target_link_libraries(SPIRV glslang)
|
||||
endif(ENABLE_OPT)
|
||||
|
||||
if(WIN32)
|
||||
source_group("Source" FILES ${SOURCES} ${HEADERS})
|
||||
source_group("Source" FILES ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS})
|
||||
endif(WIN32)
|
||||
|
||||
install(TARGETS SPIRV SPVRemapper
|
||||
ARCHIVE DESTINATION lib)
|
||||
if(ENABLE_GLSLANG_INSTALL)
|
||||
install(TARGETS SPIRV SPVRemapper
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION include/SPIRV/)
|
||||
install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SPIRV/)
|
||||
endif(ENABLE_GLSLANG_INSTALL)
|
||||
|
|
|
@ -28,24 +28,16 @@
|
|||
#define GLSLextAMD_H
|
||||
|
||||
enum BuiltIn;
|
||||
enum Capability;
|
||||
enum Decoration;
|
||||
enum Op;
|
||||
|
||||
static const int GLSLextAMDVersion = 100;
|
||||
static const int GLSLextAMDRevision = 2;
|
||||
static const int GLSLextAMDRevision = 6;
|
||||
|
||||
// SPV_AMD_shader_ballot
|
||||
static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot";
|
||||
|
||||
static const Op OpGroupIAddNonUniformAMD = static_cast<Op>(5000);
|
||||
static const Op OpGroupFAddNonUniformAMD = static_cast<Op>(5001);
|
||||
static const Op OpGroupFMinNonUniformAMD = static_cast<Op>(5002);
|
||||
static const Op OpGroupUMinNonUniformAMD = static_cast<Op>(5003);
|
||||
static const Op OpGroupSMinNonUniformAMD = static_cast<Op>(5004);
|
||||
static const Op OpGroupFMaxNonUniformAMD = static_cast<Op>(5005);
|
||||
static const Op OpGroupUMaxNonUniformAMD = static_cast<Op>(5006);
|
||||
static const Op OpGroupSMaxNonUniformAMD = static_cast<Op>(5007);
|
||||
|
||||
enum ShaderBallotAMD {
|
||||
ShaderBallotBadAMD = 0, // Don't use
|
||||
|
||||
|
@ -79,16 +71,6 @@ enum ShaderTrinaryMinMaxAMD {
|
|||
// SPV_AMD_shader_explicit_vertex_parameter
|
||||
static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter";
|
||||
|
||||
static const BuiltIn BuiltInBaryCoordNoPerspAMD = static_cast<BuiltIn>(4992);
|
||||
static const BuiltIn BuiltInBaryCoordNoPerspCentroidAMD = static_cast<BuiltIn>(4993);
|
||||
static const BuiltIn BuiltInBaryCoordNoPerspSampleAMD = static_cast<BuiltIn>(4994);
|
||||
static const BuiltIn BuiltInBaryCoordSmoothAMD = static_cast<BuiltIn>(4995);
|
||||
static const BuiltIn BuiltInBaryCoordSmoothCentroidAMD = static_cast<BuiltIn>(4996);
|
||||
static const BuiltIn BuiltInBaryCoordSmoothSampleAMD = static_cast<BuiltIn>(4997);
|
||||
static const BuiltIn BuiltInBaryCoordPullModelAMD = static_cast<BuiltIn>(4998);
|
||||
|
||||
static const Decoration DecorationExplicitInterpAMD = static_cast<Decoration>(4999);
|
||||
|
||||
enum ShaderExplicitVertexParameterAMD {
|
||||
ShaderExplicitVertexParameterBadAMD = 0, // Don't use
|
||||
|
||||
|
@ -113,4 +95,16 @@ enum GcnShaderAMD {
|
|||
// SPV_AMD_gpu_shader_half_float
|
||||
static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float";
|
||||
|
||||
// SPV_AMD_texture_gather_bias_lod
|
||||
static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod";
|
||||
|
||||
// SPV_AMD_gpu_shader_int16
|
||||
static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16";
|
||||
|
||||
// SPV_AMD_shader_image_load_store_lod
|
||||
static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod";
|
||||
|
||||
// SPV_AMD_shader_fragment_mask
|
||||
static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask";
|
||||
|
||||
#endif // #ifndef GLSLextAMD_H
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef GLSLextEXT_H
|
||||
#define GLSLextEXT_H
|
||||
|
||||
enum BuiltIn;
|
||||
enum Op;
|
||||
enum Capability;
|
||||
|
||||
static const int GLSLextEXTVersion = 100;
|
||||
static const int GLSLextEXTRevision = 1;
|
||||
|
||||
static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
|
||||
|
||||
#endif // #ifndef GLSLextEXT_H
|
|
@ -32,12 +32,17 @@ enum Op;
|
|||
enum Capability;
|
||||
|
||||
static const int GLSLextKHRVersion = 100;
|
||||
static const int GLSLextKHRRevision = 1;
|
||||
static const int GLSLextKHRRevision = 2;
|
||||
|
||||
static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot";
|
||||
static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote";
|
||||
static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group";
|
||||
static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview";
|
||||
static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters";
|
||||
static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot";
|
||||
static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote";
|
||||
static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group";
|
||||
static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview";
|
||||
static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters";
|
||||
static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage";
|
||||
static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class";
|
||||
static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage";
|
||||
static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export";
|
||||
static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer";
|
||||
|
||||
#endif // #ifndef GLSLextKHR_H
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,6 +32,8 @@
|
|||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
|
@ -45,9 +47,20 @@
|
|||
|
||||
namespace glslang {
|
||||
|
||||
struct SpvOptions {
|
||||
SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
|
||||
optimizeSize(false) { }
|
||||
bool generateDebugInfo;
|
||||
bool disableOptimizer;
|
||||
bool optimizeSize;
|
||||
};
|
||||
|
||||
void GetSpirvVersion(std::string&);
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger);
|
||||
int GetSpirvGeneratorVersion();
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
||||
SpvOptions* options = nullptr);
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
||||
spv::SpvBuildLogger* logger, SpvOptions* options = nullptr);
|
||||
void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
|
||||
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#include "spvIR.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
using spv::Block;
|
||||
using spv::Id;
|
||||
|
@ -69,33 +69,33 @@ public:
|
|||
void visit(Block* block)
|
||||
{
|
||||
assert(block);
|
||||
if (visited_[block] || delayed_[block])
|
||||
if (visited_.count(block) || delayed_.count(block))
|
||||
return;
|
||||
callback_(block);
|
||||
visited_[block] = true;
|
||||
visited_.insert(block);
|
||||
Block* mergeBlock = nullptr;
|
||||
Block* continueBlock = nullptr;
|
||||
auto mergeInst = block->getMergeInstruction();
|
||||
if (mergeInst) {
|
||||
Id mergeId = mergeInst->getIdOperand(0);
|
||||
mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock();
|
||||
delayed_[mergeBlock] = true;
|
||||
delayed_.insert(mergeBlock);
|
||||
if (mergeInst->getOpCode() == spv::OpLoopMerge) {
|
||||
Id continueId = mergeInst->getIdOperand(1);
|
||||
continueBlock =
|
||||
block->getParent().getParent().getInstruction(continueId)->getBlock();
|
||||
delayed_[continueBlock] = true;
|
||||
delayed_.insert(continueBlock);
|
||||
}
|
||||
}
|
||||
const auto successors = block->getSuccessors();
|
||||
for (auto it = successors.cbegin(); it != successors.cend(); ++it)
|
||||
visit(*it);
|
||||
if (continueBlock) {
|
||||
delayed_[continueBlock] = false;
|
||||
delayed_.erase(continueBlock);
|
||||
visit(continueBlock);
|
||||
}
|
||||
if (mergeBlock) {
|
||||
delayed_[mergeBlock] = false;
|
||||
delayed_.erase(mergeBlock);
|
||||
visit(mergeBlock);
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ public:
|
|||
private:
|
||||
std::function<void(Block*)> callback_;
|
||||
// Whether a block has already been visited or is being delayed.
|
||||
std::unordered_map<Block *, bool> visited_, delayed_;
|
||||
std::unordered_set<Block *> visited_, delayed_;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,9 @@ namespace spv {
|
|||
const unsigned typeStart = idPos(id);
|
||||
const spv::Op opCode = asOpCode(typeStart);
|
||||
|
||||
if (errorLatch)
|
||||
return 0;
|
||||
|
||||
switch (opCode) {
|
||||
case spv::OpTypeInt: // fall through...
|
||||
case spv::OpTypeFloat: return (spv[typeStart+2]+31)/32;
|
||||
|
@ -148,8 +151,10 @@ namespace spv {
|
|||
unsigned spirvbin_t::idTypeSizeInWords(spv::Id id) const
|
||||
{
|
||||
const auto tid_it = idTypeSizeMap.find(id);
|
||||
if (tid_it == idTypeSizeMap.end())
|
||||
if (tid_it == idTypeSizeMap.end()) {
|
||||
error("type size for ID not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tid_it->second;
|
||||
}
|
||||
|
@ -215,14 +220,19 @@ namespace spv {
|
|||
bool spirvbin_t::isConstOp(spv::Op opCode) const
|
||||
{
|
||||
switch (opCode) {
|
||||
case spv::OpConstantNull: error("unimplemented constant type");
|
||||
case spv::OpConstantSampler: error("unimplemented constant type");
|
||||
case spv::OpConstantNull:
|
||||
case spv::OpConstantSampler:
|
||||
error("unimplemented constant type");
|
||||
return true;
|
||||
|
||||
case spv::OpConstantTrue:
|
||||
case spv::OpConstantFalse:
|
||||
case spv::OpConstantComposite:
|
||||
case spv::OpConstant: return true;
|
||||
default: return false;
|
||||
case spv::OpConstant:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,19 +258,31 @@ namespace spv {
|
|||
{
|
||||
assert(id != spv::NoResult && newId != spv::NoResult);
|
||||
|
||||
if (id > bound()) {
|
||||
error(std::string("ID out of range: ") + std::to_string(id));
|
||||
return spirvbin_t::unused;
|
||||
}
|
||||
|
||||
if (id >= idMapL.size())
|
||||
idMapL.resize(id+1, unused);
|
||||
|
||||
if (newId != unmapped && newId != unused) {
|
||||
if (isOldIdUnused(id))
|
||||
if (isOldIdUnused(id)) {
|
||||
error(std::string("ID unused in module: ") + std::to_string(id));
|
||||
return spirvbin_t::unused;
|
||||
}
|
||||
|
||||
if (!isOldIdUnmapped(id))
|
||||
if (!isOldIdUnmapped(id)) {
|
||||
error(std::string("ID already mapped: ") + std::to_string(id) + " -> "
|
||||
+ std::to_string(localId(id)));
|
||||
+ std::to_string(localId(id)));
|
||||
|
||||
if (isNewIdMapped(newId))
|
||||
return spirvbin_t::unused;
|
||||
}
|
||||
|
||||
if (isNewIdMapped(newId)) {
|
||||
error(std::string("ID already used in module: ") + std::to_string(newId));
|
||||
return spirvbin_t::unused;
|
||||
}
|
||||
|
||||
msg(4, 4, std::string("map: ") + std::to_string(id) + " -> " + std::to_string(newId));
|
||||
setMapped(newId);
|
||||
|
@ -294,6 +316,10 @@ namespace spv {
|
|||
process(inst_fn_nop, // ignore instructions
|
||||
[this](spv::Id& id) {
|
||||
id = localId(id);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
assert(id != unused && id != unmapped);
|
||||
}
|
||||
);
|
||||
|
@ -312,14 +338,22 @@ namespace spv {
|
|||
continue;
|
||||
|
||||
// Find a new mapping for any used but unmapped IDs
|
||||
if (isOldIdUnmapped(id))
|
||||
if (isOldIdUnmapped(id)) {
|
||||
localId(id, unusedId = nextUnusedId(unusedId));
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
|
||||
if (isOldIdUnmapped(id))
|
||||
if (isOldIdUnmapped(id)) {
|
||||
error(std::string("old ID not mapped: ") + std::to_string(id));
|
||||
return;
|
||||
}
|
||||
|
||||
// Track max bound
|
||||
maxBound = std::max(maxBound, localId(id) + 1);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
|
||||
bound(maxBound); // reset header ID bound to as big as it now needs to be
|
||||
|
@ -401,6 +435,9 @@ namespace spv {
|
|||
if (typeId != spv::NoResult) {
|
||||
const unsigned idTypeSize = typeSizeInWords(typeId);
|
||||
|
||||
if (errorLatch)
|
||||
return false;
|
||||
|
||||
if (idTypeSize != 0)
|
||||
idTypeSizeMap[resultId] = idTypeSize;
|
||||
}
|
||||
|
@ -416,17 +453,26 @@ namespace spv {
|
|||
} else if (opCode == spv::Op::OpEntryPoint) {
|
||||
entryPoint = asId(start + 2);
|
||||
} else if (opCode == spv::Op::OpFunction) {
|
||||
if (fnStart != 0)
|
||||
if (fnStart != 0) {
|
||||
error("nested function found");
|
||||
return false;
|
||||
}
|
||||
|
||||
fnStart = start;
|
||||
fnRes = asId(start + 2);
|
||||
} else if (opCode == spv::Op::OpFunctionEnd) {
|
||||
assert(fnRes != spv::NoResult);
|
||||
if (fnStart == 0)
|
||||
if (fnStart == 0) {
|
||||
error("function end without function start");
|
||||
return false;
|
||||
}
|
||||
|
||||
fnPos[fnRes] = range_t(fnStart, start + asWordCount(start));
|
||||
fnStart = 0;
|
||||
} else if (isConstOp(opCode)) {
|
||||
if (errorLatch)
|
||||
return false;
|
||||
|
||||
assert(asId(start + 2) != spv::NoResult);
|
||||
typeConstPos.insert(start);
|
||||
} else if (isTypeOp(opCode)) {
|
||||
|
@ -446,29 +492,37 @@ namespace spv {
|
|||
{
|
||||
msg(2, 2, std::string("validating: "));
|
||||
|
||||
if (spv.size() < header_size)
|
||||
if (spv.size() < header_size) {
|
||||
error("file too short: ");
|
||||
return;
|
||||
}
|
||||
|
||||
if (magic() != spv::MagicNumber)
|
||||
if (magic() != spv::MagicNumber) {
|
||||
error("bad magic number");
|
||||
return;
|
||||
}
|
||||
|
||||
// field 1 = version
|
||||
// field 2 = generator magic
|
||||
// field 3 = result <id> bound
|
||||
|
||||
if (schemaNum() != 0)
|
||||
if (schemaNum() != 0) {
|
||||
error("bad schema, must be 0");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int spirvbin_t::processInstruction(unsigned word, instfn_t instFn, idfn_t idFn)
|
||||
{
|
||||
const auto instructionStart = word;
|
||||
const unsigned wordCount = asWordCount(instructionStart);
|
||||
const spv::Op opCode = asOpCode(instructionStart);
|
||||
const int nextInst = word++ + wordCount;
|
||||
spv::Op opCode = asOpCode(instructionStart);
|
||||
|
||||
if (nextInst > int(spv.size()))
|
||||
if (nextInst > int(spv.size())) {
|
||||
error("spir instruction terminated too early");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Base for computing number of operands; will be updated as more is learned
|
||||
unsigned numOperands = wordCount - 1;
|
||||
|
@ -506,6 +560,18 @@ namespace spv {
|
|||
|
||||
// Store IDs from instruction in our map
|
||||
for (int op = 0; numOperands > 0; ++op, --numOperands) {
|
||||
// SpecConstantOp is special: it includes the operands of another opcode which is
|
||||
// given as a literal in the 3rd word. We will switch over to pretending that the
|
||||
// opcode being processed is the literal opcode value of the SpecConstantOp. See the
|
||||
// SPIRV spec for details. This way we will handle IDs and literals as appropriate for
|
||||
// the embedded op.
|
||||
if (opCode == spv::OpSpecConstantOp) {
|
||||
if (op == 0) {
|
||||
opCode = asOpCode(word++); // this is the opcode embedded in the SpecConstantOp.
|
||||
--numOperands;
|
||||
}
|
||||
}
|
||||
|
||||
switch (spv::InstructionDesc[opCode].operands.getClass(op)) {
|
||||
case spv::OperandId:
|
||||
case spv::OperandScope:
|
||||
|
@ -538,6 +604,9 @@ namespace spv {
|
|||
const unsigned literalSize = idTypeSizeInWords(idBuffer[literalSizePos]);
|
||||
const unsigned numLiteralIdPairs = (nextInst-word) / (1+literalSize);
|
||||
|
||||
if (errorLatch)
|
||||
return -1;
|
||||
|
||||
for (unsigned arg=0; arg<numLiteralIdPairs; ++arg) {
|
||||
word += literalSize; // literal
|
||||
idFn(asId(word++)); // label
|
||||
|
@ -614,9 +683,13 @@ namespace spv {
|
|||
// basic parsing and InstructionDesc table borrowed from SpvDisassemble.cpp...
|
||||
unsigned nextInst = unsigned(spv.size());
|
||||
|
||||
for (unsigned word = begin; word < end; word = nextInst)
|
||||
for (unsigned word = begin; word < end; word = nextInst) {
|
||||
nextInst = processInstruction(word, instFn, idFn);
|
||||
|
||||
if (errorLatch)
|
||||
return *this;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -631,8 +704,11 @@ namespace spv {
|
|||
for (const char c : name.first)
|
||||
hashval = hashval * 1009 + c;
|
||||
|
||||
if (isOldIdUnmapped(name.second))
|
||||
if (isOldIdUnmapped(name.second)) {
|
||||
localId(name.second, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -654,6 +730,9 @@ namespace spv {
|
|||
[&](spv::Op, unsigned start) { instPos.push_back(start); return true; },
|
||||
op_fn_nop);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// Window size for context-sensitive canonicalization values
|
||||
// Empirical best size from a single data set. TODO: Would be a good tunable.
|
||||
// We essentially perform a little convolution around each instruction,
|
||||
|
@ -689,8 +768,12 @@ namespace spv {
|
|||
hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime
|
||||
}
|
||||
|
||||
if (isOldIdUnmapped(resId))
|
||||
if (isOldIdUnmapped(resId)) {
|
||||
localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -783,6 +866,9 @@ namespace spv {
|
|||
[&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; }
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// EXPERIMENTAL: Implicit output stores
|
||||
fnLocalVars.clear();
|
||||
idMap.clear();
|
||||
|
@ -803,11 +889,17 @@ namespace spv {
|
|||
},
|
||||
op_fn_nop);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
process(
|
||||
inst_fn_nop,
|
||||
[&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; }
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
}
|
||||
|
||||
|
@ -907,6 +999,9 @@ namespace spv {
|
|||
}
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0)
|
||||
|
@ -915,6 +1010,9 @@ namespace spv {
|
|||
},
|
||||
op_fn_nop);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// Chase replacements to their origins, in case there is a chain such as:
|
||||
// 2 = store 1
|
||||
// 3 = load 2
|
||||
|
@ -948,6 +1046,9 @@ namespace spv {
|
|||
}
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
}
|
||||
|
||||
|
@ -991,6 +1092,9 @@ namespace spv {
|
|||
fn->second.first,
|
||||
fn->second.second);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
fn = fnPos.erase(fn);
|
||||
} else ++fn;
|
||||
}
|
||||
|
@ -1023,6 +1127,9 @@ namespace spv {
|
|||
[&](spv::Id& id) { if (varUseCount[id]) ++varUseCount[id]; }
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// Remove single-use function variables + associated decorations and names
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
|
@ -1064,6 +1171,9 @@ namespace spv {
|
|||
[&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; }
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// Remove single reference types
|
||||
for (const auto typeStart : typeConstPos) {
|
||||
const spv::Id typeId = asTypeConstId(typeStart);
|
||||
|
@ -1073,6 +1183,9 @@ namespace spv {
|
|||
stripInst(typeStart);
|
||||
}
|
||||
}
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1151,8 +1264,10 @@ namespace spv {
|
|||
unsigned spirvbin_t::idPos(spv::Id id) const
|
||||
{
|
||||
const auto tid_it = idPosR.find(id);
|
||||
if (tid_it == idPosR.end())
|
||||
if (tid_it == idPosR.end()) {
|
||||
error("ID not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tid_it->second;
|
||||
}
|
||||
|
@ -1251,8 +1366,14 @@ namespace spv {
|
|||
const spv::Id resId = asTypeConstId(typeStart);
|
||||
const std::uint32_t hashval = hashType(typeStart);
|
||||
|
||||
if (isOldIdUnmapped(resId))
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
if (isOldIdUnmapped(resId)) {
|
||||
localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1271,7 +1392,7 @@ namespace spv {
|
|||
|
||||
int strippedPos = 0;
|
||||
for (unsigned word = 0; word < unsigned(spv.size()); ++word) {
|
||||
if (strip_it != stripRange.end() && word >= strip_it->second)
|
||||
while (strip_it != stripRange.end() && word >= strip_it->second)
|
||||
++strip_it;
|
||||
|
||||
if (strip_it == stripRange.end() || word < strip_it->first || word >= strip_it->second)
|
||||
|
@ -1298,24 +1419,49 @@ namespace spv {
|
|||
msg(3, 4, std::string("ID bound: ") + std::to_string(bound()));
|
||||
|
||||
if (options & STRIP) stripDebug();
|
||||
if (errorLatch) return;
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & OPT_LOADSTORE) optLoadStore();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & OPT_FWD_LS) forwardLoadStores();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & DCE_FUNCS) dceFuncs();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & DCE_VARS) dceVars();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & DCE_TYPES) dceTypes();
|
||||
if (errorLatch) return;
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
if (errorLatch) return;
|
||||
|
||||
stripDeadRefs(); // remove references to things we DCEed
|
||||
if (errorLatch) return;
|
||||
|
||||
// after the last strip, we must clean any debug info referring to now-deleted data
|
||||
|
||||
if (options & MAP_TYPES) mapTypeConst();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & MAP_NAMES) mapNames();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & MAP_FUNCS) mapFnBodies();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & MAP_ALL) {
|
||||
mapRemainder(); // map any unmapped IDs
|
||||
if (errorLatch) return;
|
||||
|
||||
applyMap(); // Now remap each shader to the new IDs we've come up with
|
||||
if (errorLatch) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
|
||||
namespace spv {
|
||||
|
||||
|
@ -111,7 +112,9 @@ namespace spv {
|
|||
class spirvbin_t : public spirvbin_base_t
|
||||
{
|
||||
public:
|
||||
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose) { }
|
||||
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false)
|
||||
{ }
|
||||
|
||||
virtual ~spirvbin_t() { }
|
||||
|
||||
// remap on an existing binary in memory
|
||||
|
@ -165,7 +168,7 @@ private:
|
|||
typedef std::unordered_map<spv::Id, unsigned> typesize_map_t;
|
||||
|
||||
// handle error
|
||||
void error(const std::string& txt) const { errorHandler(txt); }
|
||||
void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); }
|
||||
|
||||
bool isConstOp(spv::Op opCode) const;
|
||||
bool isTypeOp(spv::Op opCode) const;
|
||||
|
@ -286,6 +289,11 @@ private:
|
|||
std::uint32_t options;
|
||||
int verbose; // verbosity level
|
||||
|
||||
// Error latch: this is set if the error handler is ever executed. It would be better to
|
||||
// use a try/catch block and throw, but that's not desired for certain environments, so
|
||||
// this is the alternative.
|
||||
mutable bool errorLatch;
|
||||
|
||||
static errorfn_t errorHandler;
|
||||
static logfn_t logHandler;
|
||||
};
|
||||
|
|
|
@ -56,9 +56,13 @@
|
|||
|
||||
namespace spv {
|
||||
|
||||
Builder::Builder(unsigned int magicNumber, SpvBuildLogger* buildLogger) :
|
||||
Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) :
|
||||
spvVersion(spvVersion),
|
||||
source(SourceLanguageUnknown),
|
||||
sourceVersion(0),
|
||||
sourceFileStringId(NoResult),
|
||||
currentLine(0),
|
||||
emitOpLines(false),
|
||||
addressModel(AddressingModelLogical),
|
||||
memoryModel(MemoryModelGLSL450),
|
||||
builderNumber(magicNumber),
|
||||
|
@ -84,6 +88,26 @@ Id Builder::import(const char* name)
|
|||
return import->getResultId();
|
||||
}
|
||||
|
||||
// Emit an OpLine if we've been asked to emit OpLines and the line number
|
||||
// has changed since the last time, and is a valid line number.
|
||||
void Builder::setLine(int lineNum)
|
||||
{
|
||||
if (lineNum != 0 && lineNum != currentLine) {
|
||||
currentLine = lineNum;
|
||||
if (emitOpLines)
|
||||
addLine(sourceFileStringId, currentLine, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Builder::addLine(Id fileName, int lineNum, int column)
|
||||
{
|
||||
Instruction* line = new Instruction(OpLine);
|
||||
line->addIdOperand(fileName);
|
||||
line->addImmediateOperand(lineNum);
|
||||
line->addImmediateOperand(column);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(line));
|
||||
}
|
||||
|
||||
// For creating new groupedTypes (will return old type if the requested one was already made).
|
||||
Id Builder::makeVoidType()
|
||||
{
|
||||
|
@ -379,6 +403,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
|
|||
|
||||
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
|
||||
{
|
||||
assert(sampled == 1 || sampled == 2);
|
||||
|
||||
// try to find it
|
||||
Instruction* type;
|
||||
for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) {
|
||||
|
@ -410,27 +436,27 @@ Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, boo
|
|||
// deal with capabilities
|
||||
switch (dim) {
|
||||
case DimBuffer:
|
||||
if (sampled)
|
||||
if (sampled == 1)
|
||||
addCapability(CapabilitySampledBuffer);
|
||||
else
|
||||
addCapability(CapabilityImageBuffer);
|
||||
break;
|
||||
case Dim1D:
|
||||
if (sampled)
|
||||
if (sampled == 1)
|
||||
addCapability(CapabilitySampled1D);
|
||||
else
|
||||
addCapability(CapabilityImage1D);
|
||||
break;
|
||||
case DimCube:
|
||||
if (arrayed) {
|
||||
if (sampled)
|
||||
if (sampled == 1)
|
||||
addCapability(CapabilitySampledCubeArray);
|
||||
else
|
||||
addCapability(CapabilityImageCubeArray);
|
||||
}
|
||||
break;
|
||||
case DimRect:
|
||||
if (sampled)
|
||||
if (sampled == 1)
|
||||
addCapability(CapabilitySampledRect);
|
||||
else
|
||||
addCapability(CapabilityImageRect);
|
||||
|
@ -443,10 +469,14 @@ Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, boo
|
|||
}
|
||||
|
||||
if (ms) {
|
||||
if (arrayed)
|
||||
addCapability(CapabilityImageMSArray);
|
||||
if (! sampled)
|
||||
addCapability(CapabilityStorageImageMultisample);
|
||||
if (sampled == 2) {
|
||||
// Images used with subpass data are not storage
|
||||
// images, so don't require the capability for them.
|
||||
if (dim != Dim::DimSubpassData)
|
||||
addCapability(CapabilityStorageImageMultisample);
|
||||
if (arrayed)
|
||||
addCapability(CapabilityImageMSArray);
|
||||
}
|
||||
}
|
||||
|
||||
return type->getResultId();
|
||||
|
@ -928,17 +958,6 @@ void Builder::addMemberName(Id id, int memberNumber, const char* string)
|
|||
names.push_back(std::unique_ptr<Instruction>(name));
|
||||
}
|
||||
|
||||
void Builder::addLine(Id target, Id fileName, int lineNum, int column)
|
||||
{
|
||||
Instruction* line = new Instruction(OpLine);
|
||||
line->addIdOperand(target);
|
||||
line->addIdOperand(fileName);
|
||||
line->addImmediateOperand(lineNum);
|
||||
line->addImmediateOperand(column);
|
||||
|
||||
lines.push_back(std::unique_ptr<Instruction>(line));
|
||||
}
|
||||
|
||||
void Builder::addDecoration(Id id, Decoration decoration, int num)
|
||||
{
|
||||
if (decoration == spv::DecorationMax)
|
||||
|
@ -971,16 +990,16 @@ Function* Builder::makeEntryPoint(const char* entryPoint)
|
|||
|
||||
Block* entry;
|
||||
std::vector<Id> params;
|
||||
std::vector<Decoration> precisions;
|
||||
std::vector<std::vector<Decoration>> decorations;
|
||||
|
||||
entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, precisions, &entry);
|
||||
entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, decorations, &entry);
|
||||
|
||||
return entryPointFunction;
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
|
||||
const std::vector<Id>& paramTypes, const std::vector<Decoration>& precisions, Block **entry)
|
||||
const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
|
||||
{
|
||||
// Make the function and initial instructions in it
|
||||
Id typeId = makeFunctionType(returnType, paramTypes);
|
||||
|
@ -989,8 +1008,10 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
|
|||
|
||||
// Set up the precisions
|
||||
setPrecision(function->getId(), precision);
|
||||
for (unsigned p = 0; p < (unsigned)precisions.size(); ++p)
|
||||
setPrecision(firstParamId + p, precisions[p]);
|
||||
for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
|
||||
for (int d = 0; d < (int)decorations[p].size(); ++d)
|
||||
addDecoration(firstParamId + p, decorations[p][d]);
|
||||
}
|
||||
|
||||
// CFG
|
||||
if (entry) {
|
||||
|
@ -1997,9 +2018,10 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
|
|||
}
|
||||
|
||||
// Comments in header
|
||||
Builder::If::If(Id cond, Builder& gb) :
|
||||
Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) :
|
||||
builder(gb),
|
||||
condition(cond),
|
||||
control(ctrl),
|
||||
elseBlock(0)
|
||||
{
|
||||
function = &builder.getBuildPoint()->getParent();
|
||||
|
@ -2040,7 +2062,7 @@ void Builder::If::makeEndIf()
|
|||
|
||||
// Go back to the headerBlock and make the flow control split
|
||||
builder.setBuildPoint(headerBlock);
|
||||
builder.createSelectionMerge(mergeBlock, SelectionControlMaskNone);
|
||||
builder.createSelectionMerge(mergeBlock, control);
|
||||
if (elseBlock)
|
||||
builder.createConditionalBranch(condition, thenBlock, elseBlock);
|
||||
else
|
||||
|
@ -2052,7 +2074,7 @@ void Builder::If::makeEndIf()
|
|||
}
|
||||
|
||||
// Comments in header
|
||||
void Builder::makeSwitch(Id selector, int numSegments, const std::vector<int>& caseValues,
|
||||
void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector<int>& caseValues,
|
||||
const std::vector<int>& valueIndexToSegment, int defaultSegment,
|
||||
std::vector<Block*>& segmentBlocks)
|
||||
{
|
||||
|
@ -2065,7 +2087,7 @@ void Builder::makeSwitch(Id selector, int numSegments, const std::vector<int>& c
|
|||
Block* mergeBlock = new Block(getUniqueId(), function);
|
||||
|
||||
// make and insert the switch's selection-merge instruction
|
||||
createSelectionMerge(mergeBlock, SelectionControlMaskNone);
|
||||
createSelectionMerge(mergeBlock, control);
|
||||
|
||||
// make the switch instruction
|
||||
Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
|
||||
|
@ -2382,7 +2404,7 @@ void Builder::dump(std::vector<unsigned int>& out) const
|
|||
{
|
||||
// Header, before first instructions:
|
||||
out.push_back(MagicNumber);
|
||||
out.push_back(Version);
|
||||
out.push_back(spvVersion);
|
||||
out.push_back(builderNumber);
|
||||
out.push_back(uniqueId + 1);
|
||||
out.push_back(0);
|
||||
|
@ -2411,12 +2433,9 @@ void Builder::dump(std::vector<unsigned int>& out) const
|
|||
dumpInstructions(out, executionModes);
|
||||
|
||||
// Debug instructions
|
||||
if (source != SourceLanguageUnknown) {
|
||||
Instruction sourceInst(0, 0, OpSource);
|
||||
sourceInst.addImmediateOperand(source);
|
||||
sourceInst.addImmediateOperand(sourceVersion);
|
||||
sourceInst.dump(out);
|
||||
}
|
||||
dumpInstructions(out, strings);
|
||||
dumpModuleProcesses(out);
|
||||
dumpSourceInstructions(out);
|
||||
for (int e = 0; e < (int)sourceExtensions.size(); ++e) {
|
||||
Instruction sourceExtInst(0, 0, OpSourceExtension);
|
||||
sourceExtInst.addStringOperand(sourceExtensions[e]);
|
||||
|
@ -2554,12 +2573,15 @@ void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
|
|||
buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
|
||||
}
|
||||
|
||||
void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control)
|
||||
void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
|
||||
unsigned int dependencyLength)
|
||||
{
|
||||
Instruction* merge = new Instruction(OpLoopMerge);
|
||||
merge->addIdOperand(mergeBlock->getId());
|
||||
merge->addIdOperand(continueBlock->getId());
|
||||
merge->addImmediateOperand(control);
|
||||
if ((control & LoopControlDependencyLengthMask) != 0)
|
||||
merge->addImmediateOperand(dependencyLength);
|
||||
buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
|
||||
}
|
||||
|
||||
|
@ -2574,6 +2596,48 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els
|
|||
elseBlock->addPredecessor(buildPoint);
|
||||
}
|
||||
|
||||
// OpSource
|
||||
// [OpSourceContinued]
|
||||
// ...
|
||||
void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
|
||||
{
|
||||
const int maxWordCount = 0xFFFF;
|
||||
const int opSourceWordCount = 4;
|
||||
const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1;
|
||||
|
||||
if (source != SourceLanguageUnknown) {
|
||||
// OpSource Language Version File Source
|
||||
Instruction sourceInst(NoResult, NoType, OpSource);
|
||||
sourceInst.addImmediateOperand(source);
|
||||
sourceInst.addImmediateOperand(sourceVersion);
|
||||
// File operand
|
||||
if (sourceFileStringId != NoResult) {
|
||||
sourceInst.addIdOperand(sourceFileStringId);
|
||||
// Source operand
|
||||
if (sourceText.size() > 0) {
|
||||
int nextByte = 0;
|
||||
std::string subString;
|
||||
while ((int)sourceText.size() - nextByte > 0) {
|
||||
subString = sourceText.substr(nextByte, nonNullBytesPerInstruction);
|
||||
if (nextByte == 0) {
|
||||
// OpSource
|
||||
sourceInst.addStringOperand(subString.c_str());
|
||||
sourceInst.dump(out);
|
||||
} else {
|
||||
// OpSourcContinued
|
||||
Instruction sourceContinuedInst(OpSourceContinued);
|
||||
sourceContinuedInst.addStringOperand(subString.c_str());
|
||||
sourceContinuedInst.dump(out);
|
||||
}
|
||||
nextByte += nonNullBytesPerInstruction;
|
||||
}
|
||||
} else
|
||||
sourceInst.dump(out);
|
||||
} else
|
||||
sourceInst.dump(out);
|
||||
}
|
||||
}
|
||||
|
||||
void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
|
||||
{
|
||||
for (int i = 0; i < (int)instructions.size(); ++i) {
|
||||
|
@ -2581,4 +2645,13 @@ void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector
|
|||
}
|
||||
}
|
||||
|
||||
void Builder::dumpModuleProcesses(std::vector<unsigned int>& out) const
|
||||
{
|
||||
for (int i = 0; i < (int)moduleProcesses.size(); ++i) {
|
||||
Instruction moduleProcessed(OpModuleProcessed);
|
||||
moduleProcessed.addStringOperand(moduleProcesses[i]);
|
||||
moduleProcessed.dump(out);
|
||||
}
|
||||
}
|
||||
|
||||
}; // end spv namespace
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace spv {
|
|||
|
||||
class Builder {
|
||||
public:
|
||||
Builder(unsigned int userNumber, SpvBuildLogger* logger);
|
||||
Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
|
||||
virtual ~Builder();
|
||||
|
||||
static const int maxMatrixSize = 4;
|
||||
|
@ -70,7 +70,17 @@ public:
|
|||
source = lang;
|
||||
sourceVersion = version;
|
||||
}
|
||||
void setSourceFile(const std::string& file)
|
||||
{
|
||||
Instruction* fileString = new Instruction(getUniqueId(), NoType, OpString);
|
||||
fileString->addStringOperand(file.c_str());
|
||||
sourceFileStringId = fileString->getResultId();
|
||||
strings.push_back(std::unique_ptr<Instruction>(fileString));
|
||||
}
|
||||
void setSourceText(const std::string& text) { sourceText = text; }
|
||||
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
|
||||
void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
|
||||
void setEmitOpLines() { emitOpLines = true; }
|
||||
void addExtension(const char* ext) { extensions.insert(ext); }
|
||||
Id import(const char*);
|
||||
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
|
||||
|
@ -92,6 +102,12 @@ public:
|
|||
return id;
|
||||
}
|
||||
|
||||
// Log the current line, and if different than the last one,
|
||||
// issue a new OpLine, using the current file name.
|
||||
void setLine(int line);
|
||||
// Low-level OpLine. See setLine() for a layered helper.
|
||||
void addLine(Id fileName, int line, int column);
|
||||
|
||||
// For creating new types (will return old type if the requested one was already made).
|
||||
Id makeVoidType();
|
||||
Id makeBoolType();
|
||||
|
@ -199,6 +215,10 @@ public:
|
|||
Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); }
|
||||
Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
|
||||
Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); }
|
||||
#ifdef AMD_EXTENSIONS
|
||||
Id makeInt16Constant(short i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)((unsigned short)i), specConstant); }
|
||||
Id makeUint16Constant(unsigned short u, bool specConstant = false) { return makeIntConstant(makeUintType(16), (unsigned)u, specConstant); }
|
||||
#endif
|
||||
Id makeFloatConstant(float f, bool specConstant = false);
|
||||
Id makeDoubleConstant(double d, bool specConstant = false);
|
||||
#ifdef AMD_EXTENSIONS
|
||||
|
@ -213,7 +233,6 @@ public:
|
|||
void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
|
||||
void addName(Id, const char* name);
|
||||
void addMemberName(Id, int member, const char* name);
|
||||
void addLine(Id target, Id fileName, int line, int column);
|
||||
void addDecoration(Id, Decoration, int num = -1);
|
||||
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
|
||||
|
||||
|
@ -229,7 +248,7 @@ public:
|
|||
// Return the function, pass back the entry.
|
||||
// The returned pointer is only valid for the lifetime of this builder.
|
||||
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
|
||||
const std::vector<Decoration>& precisions, Block **entry = 0);
|
||||
const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
|
||||
|
||||
// Create a return. An 'implicit' return is one not appearing in the source
|
||||
// code. In the case of an implicit return, no post-return block is inserted.
|
||||
|
@ -367,7 +386,7 @@ public:
|
|||
// Helper to use for building nested control flow with if-then-else.
|
||||
class If {
|
||||
public:
|
||||
If(Id condition, Builder& builder);
|
||||
If(Id condition, unsigned int ctrl, Builder& builder);
|
||||
~If() {}
|
||||
|
||||
void makeBeginElse();
|
||||
|
@ -379,6 +398,7 @@ public:
|
|||
|
||||
Builder& builder;
|
||||
Id condition;
|
||||
unsigned int control;
|
||||
Function* function;
|
||||
Block* headerBlock;
|
||||
Block* thenBlock;
|
||||
|
@ -398,7 +418,7 @@ public:
|
|||
// Returns the right set of basic blocks to start each code segment with, so that the caller's
|
||||
// recursion stack can hold the memory for it.
|
||||
//
|
||||
void makeSwitch(Id condition, int numSegments, const std::vector<int>& caseValues,
|
||||
void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
|
||||
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
|
||||
|
||||
// Add a branch to the innermost switch's merge block.
|
||||
|
@ -541,7 +561,7 @@ public:
|
|||
|
||||
void createBranch(Block* block);
|
||||
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
|
||||
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
|
||||
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, unsigned int dependencyLength);
|
||||
|
||||
// Sets to generate opcode for specialization constants.
|
||||
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
|
||||
|
@ -561,12 +581,20 @@ public:
|
|||
void simplifyAccessChainSwizzle();
|
||||
void createAndSetNoPredecessorBlock(const char*);
|
||||
void createSelectionMerge(Block* mergeBlock, unsigned int control);
|
||||
void dumpSourceInstructions(std::vector<unsigned int>&) const;
|
||||
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
|
||||
void dumpModuleProcesses(std::vector<unsigned int>&) const;
|
||||
|
||||
unsigned int spvVersion; // the version of SPIR-V to emit in the header
|
||||
SourceLanguage source;
|
||||
int sourceVersion;
|
||||
spv::Id sourceFileStringId;
|
||||
std::string sourceText;
|
||||
int currentLine;
|
||||
bool emitOpLines;
|
||||
std::set<std::string> extensions;
|
||||
std::vector<const char*> sourceExtensions;
|
||||
std::vector<const char*> moduleProcesses;
|
||||
AddressingModel addressModel;
|
||||
MemoryModel memoryModel;
|
||||
std::set<spv::Capability> capabilities;
|
||||
|
@ -579,6 +607,7 @@ public:
|
|||
AccessChain accessChain;
|
||||
|
||||
// special blocks of instructions for output
|
||||
std::vector<std::unique_ptr<Instruction> > strings;
|
||||
std::vector<std::unique_ptr<Instruction> > imports;
|
||||
std::vector<std::unique_ptr<Instruction> > entryPoints;
|
||||
std::vector<std::unique_ptr<Instruction> > executionModes;
|
||||
|
@ -599,7 +628,7 @@ public:
|
|||
// Our loop stack.
|
||||
std::stack<LoopBlocks> loops;
|
||||
|
||||
// The stream for outputing warnings and errors.
|
||||
// The stream for outputting warnings and errors.
|
||||
SpvBuildLogger* logger;
|
||||
}; // end Builder class
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace spv {
|
|||
extern "C" {
|
||||
// Include C-based headers that don't have a namespace
|
||||
#include "GLSL.ext.KHR.h"
|
||||
#include "GLSL.ext.EXT.h"
|
||||
#ifdef AMD_EXTENSIONS
|
||||
#include "GLSL.ext.AMD.h"
|
||||
#endif
|
||||
|
@ -175,12 +176,13 @@ const char* ExecutionModeString(int mode)
|
|||
case 31: return "ContractionOff";
|
||||
case 32: return "Bad";
|
||||
|
||||
case 4446: return "PostDepthCoverage";
|
||||
case ExecutionModeCeiling:
|
||||
default: return "Bad";
|
||||
}
|
||||
}
|
||||
|
||||
const int StorageClassCeiling = 12;
|
||||
const int StorageClassCeiling = 13;
|
||||
|
||||
const char* StorageClassString(int StorageClass)
|
||||
{
|
||||
|
@ -197,6 +199,7 @@ const char* StorageClassString(int StorageClass)
|
|||
case 9: return "PushConstant";
|
||||
case 10: return "AtomicCounter";
|
||||
case 11: return "Image";
|
||||
case 12: return "StorageBuffer";
|
||||
|
||||
case StorageClassCeiling:
|
||||
default: return "Bad";
|
||||
|
@ -329,6 +332,7 @@ const char* BuiltInString(int builtIn)
|
|||
case 4424: return "BaseVertex";
|
||||
case 4425: return "BaseInstance";
|
||||
case 4426: return "DrawIndex";
|
||||
case 5014: return "FragStencilRefEXT";
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case 4992: return "BaryCoordNoPerspAMD";
|
||||
|
@ -348,6 +352,8 @@ const char* BuiltInString(int builtIn)
|
|||
case 5262: return "ViewportMaskPerViewNV";
|
||||
#endif
|
||||
|
||||
case 5264: return "FullyCoveredEXT";
|
||||
|
||||
case BuiltInCeiling:
|
||||
default: return "Bad";
|
||||
}
|
||||
|
@ -635,13 +641,15 @@ const char* SelectControlString(int cont)
|
|||
}
|
||||
}
|
||||
|
||||
const int LoopControlCeiling = 2;
|
||||
const int LoopControlCeiling = 4;
|
||||
|
||||
const char* LoopControlString(int cont)
|
||||
{
|
||||
switch (cont) {
|
||||
case 0: return "Unroll";
|
||||
case 1: return "DontUnroll";
|
||||
case 2: return "DependencyInfinite";
|
||||
case 3: return "DependencyLength";
|
||||
|
||||
case LoopControlCeiling:
|
||||
default: return "Bad";
|
||||
|
@ -830,9 +838,25 @@ const char* CapabilityString(int info)
|
|||
case 4427: return "DrawParameters";
|
||||
case 4431: return "SubgroupVoteKHR";
|
||||
|
||||
case 4433: return "StorageUniformBufferBlock16";
|
||||
case 4434: return "StorageUniform16";
|
||||
case 4435: return "StoragePushConstant16";
|
||||
case 4436: return "StorageInputOutput16";
|
||||
|
||||
case 4437: return "DeviceGroup";
|
||||
case 4439: return "MultiView";
|
||||
|
||||
case 5013: return "StencilExportEXT";
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case 5009: return "ImageGatherBiasLodAMD";
|
||||
case 5010: return "FragmentMaskAMD";
|
||||
case 5015: return "ImageReadWriteLodAMD";
|
||||
#endif
|
||||
|
||||
case 4445: return "AtomicStorageOps";
|
||||
|
||||
case 4447: return "SampleMaskPostDepthCoverage";
|
||||
#ifdef NV_EXTENSIONS
|
||||
case 5251: return "GeometryShaderPassthroughNV";
|
||||
case 5254: return "ShaderViewportIndexLayerNV";
|
||||
|
@ -841,6 +865,8 @@ const char* CapabilityString(int info)
|
|||
case 5260: return "PerViewAttributesNV";
|
||||
#endif
|
||||
|
||||
case 5265: return "FragmentFullyCoveredEXT";
|
||||
|
||||
case CapabilityCeiling:
|
||||
default: return "Bad";
|
||||
}
|
||||
|
@ -1187,6 +1213,9 @@ const char* OpcodeString(int op)
|
|||
case 5005: return "OpGroupFMaxNonUniformAMD";
|
||||
case 5006: return "OpGroupUMaxNonUniformAMD";
|
||||
case 5007: return "OpGroupSMaxNonUniformAMD";
|
||||
|
||||
case 5011: return "OpFragmentMaskFetchAMD";
|
||||
case 5012: return "OpFragmentFetchAMD";
|
||||
#endif
|
||||
|
||||
case OpcodeCeiling:
|
||||
|
@ -2529,6 +2558,7 @@ void Parameterize()
|
|||
InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Merge Block'");
|
||||
InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Continue Target'");
|
||||
InstructionDesc[OpLoopMerge].operands.push(OperandLoop, "");
|
||||
InstructionDesc[OpLoopMerge].operands.push(OperandOptionalLiteral, "");
|
||||
|
||||
InstructionDesc[OpSelectionMerge].operands.push(OperandId, "'Merge Block'");
|
||||
InstructionDesc[OpSelectionMerge].operands.push(OperandSelect, "");
|
||||
|
@ -2849,6 +2879,15 @@ void Parameterize()
|
|||
InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
|
||||
InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
|
||||
InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandId, "X");
|
||||
|
||||
InstructionDesc[OpFragmentMaskFetchAMD].capabilities.push_back(CapabilityFragmentMaskAMD);
|
||||
InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Image'");
|
||||
InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Coordinate'");
|
||||
|
||||
InstructionDesc[OpFragmentFetchAMD].capabilities.push_back(CapabilityFragmentMaskAMD);
|
||||
InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Image'");
|
||||
InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Coordinate'");
|
||||
InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Fragment Index'");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
// Parameterize the SPIR-V enumerants.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "spirv.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
namespace std {
|
||||
bool isnan(double f)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2017 The Khronos Group Inc.
|
||||
// Copyright (c) 2014-2018 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and/or associated documentation files (the "Materials"),
|
||||
|
@ -46,12 +46,12 @@ namespace spv {
|
|||
|
||||
typedef unsigned int Id;
|
||||
|
||||
#define SPV_VERSION 0x10000
|
||||
#define SPV_REVISION 10
|
||||
#define SPV_VERSION 0x10200
|
||||
#define SPV_REVISION 3
|
||||
|
||||
static const unsigned int MagicNumber = 0x07230203;
|
||||
static const unsigned int Version = 0x00010000;
|
||||
static const unsigned int Revision = 10;
|
||||
static const unsigned int Version = 0x00010200;
|
||||
static const unsigned int Revision = 3;
|
||||
static const unsigned int OpCodeMask = 0xffff;
|
||||
static const unsigned int WordCountShift = 16;
|
||||
|
||||
|
@ -122,6 +122,15 @@ enum ExecutionMode {
|
|||
ExecutionModeOutputTriangleStrip = 29,
|
||||
ExecutionModeVecTypeHint = 30,
|
||||
ExecutionModeContractionOff = 31,
|
||||
ExecutionModeInitializer = 33,
|
||||
ExecutionModeFinalizer = 34,
|
||||
ExecutionModeSubgroupSize = 35,
|
||||
ExecutionModeSubgroupsPerWorkgroup = 36,
|
||||
ExecutionModeSubgroupsPerWorkgroupId = 37,
|
||||
ExecutionModeLocalSizeId = 38,
|
||||
ExecutionModeLocalSizeHintId = 39,
|
||||
ExecutionModePostDepthCoverage = 4446,
|
||||
ExecutionModeStencilRefReplacingEXT = 5027,
|
||||
ExecutionModeMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
|
@ -376,6 +385,10 @@ enum Decoration {
|
|||
DecorationNoContraction = 42,
|
||||
DecorationInputAttachmentIndex = 43,
|
||||
DecorationAlignment = 44,
|
||||
DecorationMaxByteOffset = 45,
|
||||
DecorationAlignmentId = 46,
|
||||
DecorationMaxByteOffsetId = 47,
|
||||
DecorationExplicitInterpAMD = 4999,
|
||||
DecorationOverrideCoverageNV = 5248,
|
||||
DecorationPassthroughNV = 5250,
|
||||
DecorationViewportRelativeNV = 5252,
|
||||
|
@ -435,11 +448,20 @@ enum BuiltIn {
|
|||
BuiltInDrawIndex = 4426,
|
||||
BuiltInDeviceIndex = 4438,
|
||||
BuiltInViewIndex = 4440,
|
||||
BuiltInBaryCoordNoPerspAMD = 4992,
|
||||
BuiltInBaryCoordNoPerspCentroidAMD = 4993,
|
||||
BuiltInBaryCoordNoPerspSampleAMD = 4994,
|
||||
BuiltInBaryCoordSmoothAMD = 4995,
|
||||
BuiltInBaryCoordSmoothCentroidAMD = 4996,
|
||||
BuiltInBaryCoordSmoothSampleAMD = 4997,
|
||||
BuiltInBaryCoordPullModelAMD = 4998,
|
||||
BuiltInFragStencilRefEXT = 5014,
|
||||
BuiltInViewportMaskNV = 5253,
|
||||
BuiltInSecondaryPositionNV = 5257,
|
||||
BuiltInSecondaryViewportMaskNV = 5258,
|
||||
BuiltInPositionPerViewNV = 5261,
|
||||
BuiltInViewportMaskPerViewNV = 5262,
|
||||
BuiltInFullyCoveredEXT = 5264,
|
||||
BuiltInMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
|
@ -458,6 +480,8 @@ enum SelectionControlMask {
|
|||
enum LoopControlShift {
|
||||
LoopControlUnrollShift = 0,
|
||||
LoopControlDontUnrollShift = 1,
|
||||
LoopControlDependencyInfiniteShift = 2,
|
||||
LoopControlDependencyLengthShift = 3,
|
||||
LoopControlMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
|
@ -465,6 +489,8 @@ enum LoopControlMask {
|
|||
LoopControlMaskNone = 0,
|
||||
LoopControlUnrollMask = 0x00000001,
|
||||
LoopControlDontUnrollMask = 0x00000002,
|
||||
LoopControlDependencyInfiniteMask = 0x00000004,
|
||||
LoopControlDependencyLengthMask = 0x00000008,
|
||||
};
|
||||
|
||||
enum FunctionControlShift {
|
||||
|
@ -615,6 +641,9 @@ enum Capability {
|
|||
CapabilityStorageImageReadWithoutFormat = 55,
|
||||
CapabilityStorageImageWriteWithoutFormat = 56,
|
||||
CapabilityMultiViewport = 57,
|
||||
CapabilitySubgroupDispatch = 58,
|
||||
CapabilityNamedBarrier = 59,
|
||||
CapabilityPipeStorage = 60,
|
||||
CapabilitySubgroupBallotKHR = 4423,
|
||||
CapabilityDrawParameters = 4427,
|
||||
CapabilitySubgroupVoteKHR = 4431,
|
||||
|
@ -628,12 +657,23 @@ enum Capability {
|
|||
CapabilityMultiView = 4439,
|
||||
CapabilityVariablePointersStorageBuffer = 4441,
|
||||
CapabilityVariablePointers = 4442,
|
||||
CapabilityAtomicStorageOps = 4445,
|
||||
CapabilitySampleMaskPostDepthCoverage = 4447,
|
||||
CapabilityImageGatherBiasLodAMD = 5009,
|
||||
CapabilityFragmentMaskAMD = 5010,
|
||||
CapabilityStencilExportEXT = 5013,
|
||||
CapabilityImageReadWriteLodAMD = 5015,
|
||||
CapabilitySampleMaskOverrideCoverageNV = 5249,
|
||||
CapabilityGeometryShaderPassthroughNV = 5251,
|
||||
CapabilityShaderViewportIndexLayerEXT = 5254,
|
||||
CapabilityShaderViewportIndexLayerNV = 5254,
|
||||
CapabilityShaderViewportMaskNV = 5255,
|
||||
CapabilityShaderStereoViewNV = 5259,
|
||||
CapabilityPerViewAttributesNV = 5260,
|
||||
CapabilityFragmentFullyCoveredEXT = 5265,
|
||||
CapabilitySubgroupShuffleINTEL = 5568,
|
||||
CapabilitySubgroupBufferBlockIOINTEL = 5569,
|
||||
CapabilitySubgroupImageBlockIOINTEL = 5570,
|
||||
CapabilityMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
|
@ -932,12 +972,42 @@ enum Op {
|
|||
OpAtomicFlagTestAndSet = 318,
|
||||
OpAtomicFlagClear = 319,
|
||||
OpImageSparseRead = 320,
|
||||
OpSizeOf = 321,
|
||||
OpTypePipeStorage = 322,
|
||||
OpConstantPipeStorage = 323,
|
||||
OpCreatePipeFromPipeStorage = 324,
|
||||
OpGetKernelLocalSizeForSubgroupCount = 325,
|
||||
OpGetKernelMaxNumSubgroups = 326,
|
||||
OpTypeNamedBarrier = 327,
|
||||
OpNamedBarrierInitialize = 328,
|
||||
OpMemoryNamedBarrier = 329,
|
||||
OpModuleProcessed = 330,
|
||||
OpExecutionModeId = 331,
|
||||
OpDecorateId = 332,
|
||||
OpSubgroupBallotKHR = 4421,
|
||||
OpSubgroupFirstInvocationKHR = 4422,
|
||||
OpSubgroupAllKHR = 4428,
|
||||
OpSubgroupAnyKHR = 4429,
|
||||
OpSubgroupAllEqualKHR = 4430,
|
||||
OpSubgroupReadInvocationKHR = 4432,
|
||||
OpGroupIAddNonUniformAMD = 5000,
|
||||
OpGroupFAddNonUniformAMD = 5001,
|
||||
OpGroupFMinNonUniformAMD = 5002,
|
||||
OpGroupUMinNonUniformAMD = 5003,
|
||||
OpGroupSMinNonUniformAMD = 5004,
|
||||
OpGroupFMaxNonUniformAMD = 5005,
|
||||
OpGroupUMaxNonUniformAMD = 5006,
|
||||
OpGroupSMaxNonUniformAMD = 5007,
|
||||
OpFragmentMaskFetchAMD = 5011,
|
||||
OpFragmentFetchAMD = 5012,
|
||||
OpSubgroupShuffleINTEL = 5571,
|
||||
OpSubgroupShuffleDownINTEL = 5572,
|
||||
OpSubgroupShuffleUpINTEL = 5573,
|
||||
OpSubgroupShuffleXorINTEL = 5574,
|
||||
OpSubgroupBlockReadINTEL = 5575,
|
||||
OpSubgroupBlockWriteINTEL = 5576,
|
||||
OpSubgroupImageBlockReadINTEL = 5577,
|
||||
OpSubgroupImageBlockWriteINTEL = 5578,
|
||||
OpMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
|
|
|
@ -65,12 +65,17 @@ const Id NoResult = 0;
|
|||
const Id NoType = 0;
|
||||
|
||||
const Decoration NoPrecision = DecorationMax;
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define POTENTIALLY_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define POTENTIALLY_UNUSED
|
||||
#endif
|
||||
|
||||
POTENTIALLY_UNUSED
|
||||
const MemorySemanticsMask MemorySemanticsAllMemory =
|
||||
(MemorySemanticsMask)(MemorySemanticsSequentiallyConsistentMask |
|
||||
MemorySemanticsUniformMemoryMask |
|
||||
MemorySemanticsSubgroupMemoryMask |
|
||||
(MemorySemanticsMask)(MemorySemanticsUniformMemoryMask |
|
||||
MemorySemanticsWorkgroupMemoryMask |
|
||||
MemorySemanticsCrossWorkgroupMemoryMask |
|
||||
MemorySemanticsAtomicCounterMemoryMask |
|
||||
MemorySemanticsImageMemoryMask);
|
||||
|
||||
|
@ -87,7 +92,6 @@ public:
|
|||
void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); }
|
||||
void addStringOperand(const char* str)
|
||||
{
|
||||
originalString = str;
|
||||
unsigned int word;
|
||||
char* wordString = (char*)&word;
|
||||
char* wordPtr = wordString;
|
||||
|
@ -120,7 +124,6 @@ public:
|
|||
Id getTypeId() const { return typeId; }
|
||||
Id getIdOperand(int op) const { return operands[op]; }
|
||||
unsigned int getImmediateOperand(int op) const { return operands[op]; }
|
||||
const char* getStringOperand() const { return originalString.c_str(); }
|
||||
|
||||
// Write out the binary form.
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
|
@ -151,7 +154,6 @@ protected:
|
|||
Id typeId;
|
||||
Op opCode;
|
||||
std::vector<Id> operands;
|
||||
std::string originalString; // could be optimized away; convenience for getting string operand
|
||||
Block* block;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
add_library(glslang-default-resource-limits
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp)
|
||||
set_property(TARGET glslang-default-resource-limits PROPERTY FOLDER glslang)
|
||||
set_property(TARGET glslang-default-resource-limits PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
target_include_directories(glslang-default-resource-limits
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PUBLIC ${PROJECT_SOURCE_DIR}
|
||||
)
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PUBLIC ${PROJECT_SOURCE_DIR})
|
||||
|
||||
set(SOURCES StandAlone.cpp)
|
||||
set(SOURCES StandAlone.cpp DirStackFileIncluder.h)
|
||||
set(REMAPPER_SOURCES spirv-remap.cpp)
|
||||
|
||||
add_executable(glslangValidator ${SOURCES})
|
||||
|
@ -24,7 +23,6 @@ set(LIBRARIES
|
|||
SPVRemapper
|
||||
glslang-default-resource-limits)
|
||||
|
||||
|
||||
if(WIN32)
|
||||
set(LIBRARIES ${LIBRARIES} psapi)
|
||||
elseif(UNIX)
|
||||
|
@ -40,8 +38,10 @@ if(WIN32)
|
|||
source_group("Source" FILES ${SOURCES})
|
||||
endif(WIN32)
|
||||
|
||||
install(TARGETS glslangValidator
|
||||
RUNTIME DESTINATION bin)
|
||||
if(ENABLE_GLSLANG_INSTALL)
|
||||
install(TARGETS glslangValidator
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
install(TARGETS spirv-remap
|
||||
RUNTIME DESTINATION bin)
|
||||
install(TARGETS spirv-remap
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif(ENABLE_GLSLANG_INSTALL)
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
//
|
||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
// Copyright (C) 2017 Google, Inc.
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "./../glslang/Public/ShaderLang.h"
|
||||
|
||||
// Default include class for normal include convention of search backward
|
||||
// through the stack of active include paths (for nested includes).
|
||||
// Can be overridden to customize.
|
||||
class DirStackFileIncluder : public glslang::TShader::Includer {
|
||||
public:
|
||||
DirStackFileIncluder() : externalLocalDirectoryCount(0) { }
|
||||
|
||||
virtual IncludeResult* includeLocal(const char* headerName,
|
||||
const char* includerName,
|
||||
size_t inclusionDepth) override
|
||||
{
|
||||
return readLocalPath(headerName, includerName, (int)inclusionDepth);
|
||||
}
|
||||
|
||||
virtual IncludeResult* includeSystem(const char* headerName,
|
||||
const char* /*includerName*/,
|
||||
size_t /*inclusionDepth*/) override
|
||||
{
|
||||
return readSystemPath(headerName);
|
||||
}
|
||||
|
||||
// Externally set directories. E.g., from a command-line -I<dir>.
|
||||
// - Most-recently pushed are checked first.
|
||||
// - All these are checked after the parse-time stack of local directories
|
||||
// is checked.
|
||||
// - This only applies to the "local" form of #include.
|
||||
// - Makes its own copy of the path.
|
||||
virtual void pushExternalLocalDirectory(const std::string& dir)
|
||||
{
|
||||
directoryStack.push_back(dir);
|
||||
externalLocalDirectoryCount = (int)directoryStack.size();
|
||||
}
|
||||
|
||||
virtual void releaseInclude(IncludeResult* result) override
|
||||
{
|
||||
if (result != nullptr) {
|
||||
delete [] static_cast<tUserDataElement*>(result->userData);
|
||||
delete result;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~DirStackFileIncluder() override { }
|
||||
|
||||
protected:
|
||||
typedef char tUserDataElement;
|
||||
std::vector<std::string> directoryStack;
|
||||
int externalLocalDirectoryCount;
|
||||
|
||||
// Search for a valid "local" path based on combining the stack of include
|
||||
// directories and the nominal name of the header.
|
||||
virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth)
|
||||
{
|
||||
// Discard popped include directories, and
|
||||
// initialize when at parse-time first level.
|
||||
directoryStack.resize(depth + externalLocalDirectoryCount);
|
||||
if (depth == 1)
|
||||
directoryStack.back() = getDirectory(includerName);
|
||||
|
||||
// Find a directory that works, using a reverse search of the include stack.
|
||||
for (auto it = directoryStack.rbegin(); it != directoryStack.rend(); ++it) {
|
||||
std::string path = *it + '/' + headerName;
|
||||
std::replace(path.begin(), path.end(), '\\', '/');
|
||||
std::ifstream file(path, std::ios_base::binary | std::ios_base::ate);
|
||||
if (file) {
|
||||
directoryStack.push_back(getDirectory(path));
|
||||
return newIncludeResult(path, file, (int)file.tellg());
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Search for a valid <system> path.
|
||||
// Not implemented yet; returning nullptr signals failure to find.
|
||||
virtual IncludeResult* readSystemPath(const char* /*headerName*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Do actual reading of the file, filling in a new include result.
|
||||
virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const
|
||||
{
|
||||
char* content = new tUserDataElement [length];
|
||||
file.seekg(0, file.beg);
|
||||
file.read(content, length);
|
||||
return new IncludeResult(path, content, length, content);
|
||||
}
|
||||
|
||||
// If no path markers, return current working directory.
|
||||
// Otherwise, strip file name and return path leading up to it.
|
||||
virtual std::string getDirectory(const std::string path) const
|
||||
{
|
||||
size_t last = path.find_last_of("/\\");
|
||||
return last == std::string::npos ? "." : path.substr(0, last);
|
||||
}
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -184,4 +184,21 @@ void fooDeeparray()
|
|||
yp = y;
|
||||
xp = y; // ERROR, wrong size
|
||||
yp = x; // ERROR, wrong size
|
||||
}
|
||||
|
||||
layout(num_views = 2) in; // ERROR, no extension
|
||||
|
||||
void mwErr()
|
||||
{
|
||||
gl_ViewID_OVR; // ERROR, no extension
|
||||
}
|
||||
|
||||
#extension GL_OVR_multiview : enable
|
||||
|
||||
layout(num_views = 2) uniform float mwUniform; // ERROR, must be global
|
||||
layout(num_views = 2) in; // OK
|
||||
|
||||
void mwOk()
|
||||
{
|
||||
gl_ViewID_OVR;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ layout(local_size_x = 2) in;
|
|||
layout(local_size_x = 16) in; // ERROR, changing
|
||||
layout(local_size_z = 4096) in; // ERROR, too large
|
||||
layout(local_size_x = 2) in;
|
||||
|
||||
layout(local_size_y = 0) in; // ERROR, 0 not allowed
|
||||
const int total = gl_MaxComputeWorkGroupCount.y
|
||||
+ gl_MaxComputeUniformComponents
|
||||
+ gl_MaxComputeTextureImageUnits
|
||||
|
|
|
@ -113,3 +113,9 @@ out float outArray[2][3]; // ERROR
|
|||
uniform ubaa {
|
||||
int a;
|
||||
} ubaaname[2][3]; // ERROR
|
||||
|
||||
vec3 func(in mat3[2] x[3])
|
||||
{
|
||||
mat3 a0 = x[2][1];
|
||||
return a0[2];
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#version 310 es
|
||||
layout (location=0) uniform Block {
|
||||
layout (binding=0) uniform Block {
|
||||
highp int a[];
|
||||
} uni;
|
||||
layout (location=0) out highp int o;
|
||||
|
|
|
@ -184,10 +184,8 @@ void qlod()
|
|||
lod = textureQueryLod(sampRect, pf2); // ERROR
|
||||
}
|
||||
|
||||
struct SKeyMem { int precise; } KeyMem; // ERROR, keyword can't be a member
|
||||
|
||||
uniform uint uu;
|
||||
out int iout;
|
||||
out uint iout;
|
||||
|
||||
void bitwiseConv()
|
||||
{
|
||||
|
@ -195,3 +193,9 @@ void bitwiseConv()
|
|||
iout += uu ^ i;
|
||||
iout += i | uu;
|
||||
}
|
||||
|
||||
subroutine(subT1, subT2);
|
||||
subroutine float subT1() { return 1.0; }
|
||||
subroutine float subT2() { return 1.0; }
|
||||
|
||||
struct SKeyMem { int precise; } KeyMem; // ERROR, keyword can't be a member
|
||||
|
|
|
@ -174,6 +174,12 @@ out layout(xfb_buffer=7, xfb_offset=0) bblck10 { // link ERROR, implicit stride
|
|||
float f;
|
||||
} bbinst10;
|
||||
|
||||
layout(xfb_buffer = 3) out;
|
||||
layout(xfb_offset = 32) out gl_PerVertex {
|
||||
layout(xfb_buffer = 2) float gl_PointSize; // ERROR, change in xfb_buffer
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
int drawParamsBad()
|
||||
{
|
||||
return gl_BaseVertexARB + gl_BaseInstanceARB + gl_DrawIDARB; // ERROR, extension not requested
|
||||
|
|
|
@ -1 +1,6 @@
|
|||
#version 450 core
|
||||
layout(local_size_x = 0) in; // ERROR, 0 not allowed
|
||||
void main()
|
||||
{
|
||||
shared float f; // ERROR shared must be global
|
||||
}
|
||||
|
|
|
@ -54,3 +54,15 @@ float cull(int i)
|
|||
{
|
||||
return (i >= 6) ? gl_CullDistance[5] : gl_CullDistance[i];
|
||||
}
|
||||
|
||||
layout(location = 6) in bName1 {
|
||||
float f;
|
||||
layout(location = 7) float g;
|
||||
mat4 m;
|
||||
} bInst1;
|
||||
layout(location = 12) in bName2 {
|
||||
float f;
|
||||
layout(location = 13) float g; // ERROR, location on array
|
||||
} bInst2[3];
|
||||
|
||||
layout(early_fragment_tests) in float f; // ERROR, must be standalone
|
||||
|
|
|
@ -15,3 +15,5 @@ void main()
|
|||
gl_in[3].gl_Position; // ERROR, out of range
|
||||
gl_CullDistance[2] = gl_in[1].gl_CullDistance[2];
|
||||
}
|
||||
|
||||
layout(points) in float f[3]; // ERROR, must be standalone
|
||||
|
|
|
@ -12,3 +12,12 @@ void main()
|
|||
{
|
||||
gl_out[gl_InvocationID].gl_CullDistance[2] = gl_in[1].gl_CullDistance[2];
|
||||
}
|
||||
|
||||
layout(location = 4) out bName1 {
|
||||
float f;
|
||||
layout(location = 5) float g;
|
||||
} bInst1[2];
|
||||
layout(location = 6) out bName2 {
|
||||
float f;
|
||||
layout(location = 7) float g; // ERROR, location on array
|
||||
} bInst2[2][3];
|
||||
|
|
|
@ -12,3 +12,10 @@ void main()
|
|||
{
|
||||
gl_CullDistance[2] = gl_in[1].gl_CullDistance[2];
|
||||
}
|
||||
|
||||
layout(equal_spacing) in float f1[]; // ERROR, must be standalone
|
||||
layout(fractional_even_spacing) in float f2[]; // ERROR, must be standalone
|
||||
layout(fractional_odd_spacing) in float f3[]; // ERROR, must be standalone
|
||||
layout(cw) in float f4[]; // ERROR, must be standalone
|
||||
layout(ccw) in float f5[]; // ERROR, must be standalone
|
||||
layout(point_mode) in float f6[]; // ERROR, must be standalone
|
||||
|
|
|
@ -22,7 +22,35 @@ out SA outSA;
|
|||
struct SS { float f; S s; };
|
||||
out SS outSS;
|
||||
|
||||
layout(binding = 0) uniform atomic_uint aui;
|
||||
uint ui;
|
||||
|
||||
void foo()
|
||||
{
|
||||
SS::f;
|
||||
atomicCounterAdd(aui, ui); // ERROR, need 4.6
|
||||
atomicCounterSubtract(aui, ui); // ERROR, need 4.6
|
||||
atomicCounterMin(aui, ui); // ERROR, need 4.6
|
||||
atomicCounterMax(aui, ui); // ERROR, need 4.6
|
||||
atomicCounterAnd(aui, ui); // ERROR, need 4.6
|
||||
atomicCounterOr(aui, ui); // ERROR, need 4.6
|
||||
atomicCounterXor(aui, ui); // ERROR, need 4.6
|
||||
atomicCounterExchange(aui, ui); // ERROR, need 4.6
|
||||
atomicCounterCompSwap(aui, ui, ui); // ERROR, need 4.6
|
||||
|
||||
int a = gl_BaseVertex + gl_BaseInstance + gl_DrawID; // ERROR, need 4.6
|
||||
|
||||
bool b1;
|
||||
anyInvocation(b1); // ERROR, need 4.6
|
||||
allInvocations(b1); // ERROR, need 4.6
|
||||
allInvocationsEqual(b1); // ERROR, need 4.6
|
||||
}
|
||||
; // ERROR: no extraneous semicolons
|
||||
|
||||
layout(location = 0) uniform locBlock { // ERROR, no location uniform block
|
||||
int a;
|
||||
};
|
||||
|
||||
layout(location = 0) buffer locBuffBlock { // ERROR, no location on buffer block
|
||||
int b;
|
||||
};
|
||||
|
|
|
@ -84,7 +84,7 @@ ERROR: 0:194: '.' : cannot apply to an array: method
|
|||
ERROR: 0:194: 'a' : can't use function syntax on variable
|
||||
ERROR: 0:214: 'non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:3000: '#error' : line of this error should be 3000
|
||||
ERROR: 0:3002: '' : syntax error
|
||||
ERROR: 0:3002: '' : syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
|
||||
ERROR: 77 compilation errors. No code generated.
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ ERROR: 0:82: 'xr' : vector swizzle selectors not from the same set
|
|||
ERROR: 0:83: 'xyxyx' : vector swizzle too long
|
||||
ERROR: 0:84: 'z' : vector swizzle selection out of range
|
||||
ERROR: 0:85: 'assign' : l-value required
|
||||
ERROR: 0:91: 'int' : overloaded functions must have the same return type
|
||||
ERROR: 0:91: 'main' : overloaded functions must have the same return type
|
||||
ERROR: 0:91: 'main' : function already has a body
|
||||
ERROR: 0:91: 'int' : entry point cannot return a value
|
||||
ERROR: 0:92: 'main' : function cannot take any parameter(s)
|
||||
|
@ -52,8 +52,10 @@ ERROR: 0:209: 'assign' : cannot convert from ' const float' to ' temp 4-compone
|
|||
ERROR: 0:212: 'sampler2DRect' : Reserved word.
|
||||
ERROR: 0:244: ':' : wrong operand types: no operation ':' exists that takes a left-hand operand of type ' global void' and a right operand of type ' const int' (or there is no acceptable conversion)
|
||||
ERROR: 0:245: ':' : wrong operand types: no operation ':' exists that takes a left-hand operand of type ' const int' and a right operand of type ' global void' (or there is no acceptable conversion)
|
||||
ERROR: 0:248: '' : syntax error
|
||||
ERROR: 54 compilation errors. No code generated.
|
||||
ERROR: 0:248: 'shader half float' : required extension not requested: GL_AMD_gpu_shader_half_float
|
||||
ERROR: 0:248: 'half floating-point suffix' : not supported with this profile: none
|
||||
ERROR: 0:248: '' : syntax error, unexpected IDENTIFIER, expecting COMMA or SEMICOLON
|
||||
ERROR: 56 compilation errors. No code generated.
|
||||
|
||||
|
||||
Shader version: 120
|
||||
|
|
|
@ -34,7 +34,7 @@ ERROR: 0:51: 'arrays of arrays' : not supported with this profile: none
|
|||
ERROR: 0:52: 'arrays of arrays' : not supported with this profile: none
|
||||
ERROR: 0:53: 'arrays of arrays' : not supported with this profile: none
|
||||
ERROR: 0:56: 'out' : overloaded functions must have the same parameter storage qualifiers for argument 1
|
||||
ERROR: 0:57: 'float' : overloaded functions must have the same return type
|
||||
ERROR: 0:57: 'overloadA' : overloaded functions must have the same return type
|
||||
ERROR: 0:87: 'overloadC' : no matching overloaded function found
|
||||
ERROR: 0:90: 'overloadC' : no matching overloaded function found
|
||||
ERROR: 0:95: 'overloadD' : ambiguous function signature match: multiple signatures match under implicit type conversion
|
||||
|
|
|
@ -210,7 +210,6 @@ ERROR: node is still EOpNull!
|
|||
0:? 'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position, gl_PointSize float PointSize gl_PointSize, out implicitly-sized array of float ClipDistance gl_ClipDistance})
|
||||
|
||||
400.tesc
|
||||
Warning, version 400 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:6: 'quads' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
|
||||
ERROR: 0:7: 'ccw' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
|
||||
ERROR: 0:8: 'fractional_even_spacing' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
|
||||
|
@ -442,7 +441,6 @@ ERROR: node is still EOpNull!
|
|||
0:? 'badOrder' ( invariant noContraction out 4-element array of 4-component vector of float)
|
||||
|
||||
400.tese
|
||||
Warning, version 400 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:3: 'vertices' : there is no such layout identifier for this stage taking an assigned value
|
||||
ERROR: 0:5: 'triangles' : cannot change previously set input primitive
|
||||
ERROR: 0:6: 'isolines' : cannot change previously set input primitive
|
||||
|
@ -612,7 +610,6 @@ ERROR: node is still EOpNull!
|
|||
0:? 'pinbi' ( patch in block{ in int a})
|
||||
|
||||
410.tesc
|
||||
Warning, version 400 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:4: 'length' : array must first be sized by a redeclaration or layout qualifier
|
||||
ERROR: 1 compilation errors. No code generated.
|
||||
|
||||
|
@ -628,7 +625,6 @@ ERROR: node is still EOpNull!
|
|||
0:? 'patchOut' ( patch out 4-component vector of float)
|
||||
|
||||
420.tesc
|
||||
Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:7: 'vertices' : inconsistent output number of vertices for array size of gl_out
|
||||
ERROR: 0:11: 'vertices' : inconsistent output number of vertices for array size of a
|
||||
ERROR: 0:12: 'vertices' : inconsistent output number of vertices for array size of outb
|
||||
|
@ -747,7 +743,6 @@ ERROR: node is still EOpNull!
|
|||
0:? 'vs_tcs_last' (layout( location=12) in 32-element array of 2X4 matrix of double)
|
||||
|
||||
420.tese
|
||||
Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:7: '=' : cannot convert from ' const 3-element array of float' to ' global 2-element array of float'
|
||||
ERROR: 0:8: 'initializer list' : wrong vector size (or rows in a matrix column): temp 2-component vector of float
|
||||
ERROR: 0:9: 'initializer list' : wrong number of matrix columns: temp 3X3 matrix of float
|
||||
|
@ -759,7 +754,7 @@ ERROR: 0:29: 'constructor' : cannot convert parameter 2 from ' const 2X2 matrix
|
|||
ERROR: 0:29: ' const 2-element array of 4-component vector of float' : cannot construct with these arguments
|
||||
ERROR: 0:29: '=' : cannot convert from ' const float' to ' global 2-element array of 4-component vector of float'
|
||||
ERROR: 0:30: 'initializer list' : wrong number of matrix columns: temp 4X2 matrix of float
|
||||
ERROR: 0:40: 'constructor' : cannot convert parameter 1 from ' temp float' to ' temp structure{ global float s, global float t}'
|
||||
ERROR: 0:40: 'constructor' : cannot convert parameter 1 from ' const structure{ global 4-component vector of float a, global 4-component vector of float b}' to ' temp structure{ global float s, global float t}'
|
||||
ERROR: 0:70: 'initializer list' : wrong number of structure members
|
||||
ERROR: 13 compilation errors. No code generated.
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ ERROR: 0:156: 'invariant' : can only apply to an output
|
|||
ERROR: 0:157: 'invariant' : can only apply to an output
|
||||
ERROR: 0:158: 'invariant' : can only apply to an output
|
||||
ERROR: 0:160: 'imageBuffer' : Reserved word.
|
||||
ERROR: 0:160: '' : syntax error
|
||||
ERROR: 0:160: '' : syntax error, unexpected IMAGEBUFFER, expecting COMMA or SEMICOLON
|
||||
ERROR: 45 compilation errors. No code generated.
|
||||
|
||||
|
||||
|
|
|
@ -43,10 +43,18 @@ ERROR: 0:172: 'std430' : requires the 'buffer' storage qualifier
|
|||
ERROR: 0:175: '' : array size required
|
||||
ERROR: 0:185: 'assign' : cannot convert from ' temp 4-element array of highp float' to ' temp 3-element array of highp float'
|
||||
ERROR: 0:186: 'assign' : cannot convert from ' temp 3-element array of highp float' to ' temp 4-element array of highp float'
|
||||
ERROR: 44 compilation errors. No code generated.
|
||||
ERROR: 0:189: 'num_views' : required extension not requested: Possible extensions include:
|
||||
GL_OVR_multiview
|
||||
GL_OVR_multiview2
|
||||
ERROR: 0:193: 'gl_ViewID_OVR' : required extension not requested: Possible extensions include:
|
||||
GL_OVR_multiview
|
||||
GL_OVR_multiview2
|
||||
ERROR: 0:198: 'num_views' : can only apply to a standalone qualifier
|
||||
ERROR: 47 compilation errors. No code generated.
|
||||
|
||||
|
||||
Shader version: 300
|
||||
Requested GL_OVR_multiview
|
||||
ERROR: node is still EOpNull!
|
||||
0:27 Function Definition: main( ( global void)
|
||||
0:27 Function Parameters:
|
||||
|
@ -289,6 +297,14 @@ ERROR: node is still EOpNull!
|
|||
0:184 'y' ( temp 4-element array of highp float)
|
||||
0:185 'xp' ( temp 3-element array of highp float)
|
||||
0:186 'yp' ( temp 4-element array of highp float)
|
||||
0:191 Function Definition: mwErr( ( global void)
|
||||
0:191 Function Parameters:
|
||||
0:193 Sequence
|
||||
0:193 'gl_ViewID_OVR' ( in highp uint ViewIndex)
|
||||
0:201 Function Definition: mwOk( ( global void)
|
||||
0:201 Function Parameters:
|
||||
0:203 Sequence
|
||||
0:203 'gl_ViewID_OVR' ( in highp uint ViewIndex)
|
||||
0:? Linker Objects
|
||||
0:? 'm43' ( uniform highp 4X3 matrix of float)
|
||||
0:? 'm33' ( uniform highp 3X3 matrix of float)
|
||||
|
@ -323,6 +339,7 @@ ERROR: node is still EOpNull!
|
|||
0:? 'Binst' (layout( column_major shared) uniform block{layout( column_major shared) uniform highp int a})
|
||||
0:? 'Bfoo' ( global highp int)
|
||||
0:? 'B430i' (layout( column_major std430) uniform block{layout( column_major std430 offset=0) uniform highp int a})
|
||||
0:? 'mwUniform' ( uniform highp float)
|
||||
0:? 'gl_VertexID' ( gl_VertexId highp int VertexId)
|
||||
0:? 'gl_InstanceID' ( gl_InstanceId highp int InstanceId)
|
||||
|
||||
|
@ -331,6 +348,7 @@ Linked vertex stage:
|
|||
|
||||
|
||||
Shader version: 300
|
||||
Requested GL_OVR_multiview
|
||||
ERROR: node is still EOpNull!
|
||||
0:27 Function Definition: main( ( global void)
|
||||
0:27 Function Parameters:
|
||||
|
@ -481,6 +499,7 @@ ERROR: node is still EOpNull!
|
|||
0:? 'Binst' (layout( column_major shared) uniform block{layout( column_major shared) uniform highp int a})
|
||||
0:? 'Bfoo' ( global highp int)
|
||||
0:? 'B430i' (layout( column_major std430) uniform block{layout( column_major std430 offset=0) uniform highp int a})
|
||||
0:? 'mwUniform' ( uniform highp float)
|
||||
0:? 'gl_VertexID' ( gl_VertexId highp int VertexId)
|
||||
0:? 'gl_InstanceID' ( gl_InstanceId highp int InstanceId)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
310.comp
|
||||
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:4: 'local_size' : cannot change previously set size
|
||||
ERROR: 0:5: 'local_size' : too large; see gl_MaxComputeWorkGroupSize
|
||||
ERROR: 0:7: 'local_size_y' : must be at least 1
|
||||
ERROR: 0:23: '' : array size required
|
||||
ERROR: 0:39: 'in' : global storage input qualifier cannot be used in a compute shader
|
||||
ERROR: 0:39: 'location qualifier on input' : not supported in this stage: compute
|
||||
|
@ -16,7 +16,7 @@ ERROR: 0:47: 'local_size' : can only apply to 'in'
|
|||
ERROR: 0:61: 'assign' : l-value required "ro" (can't modify a readonly buffer)
|
||||
ERROR: 0:66: 'buffer' : buffers can be declared only as blocks
|
||||
ERROR: 0:68: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:76: 'image variables declared 'writeonly' without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:76: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:81: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:82: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:87: 'imageAtomicCompSwap' : required extension not requested: GL_OES_shader_image_atomic
|
||||
|
@ -54,12 +54,12 @@ ERROR: 0:171: 'samplerCubeArray' : Reserved word.
|
|||
ERROR: 0:171: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:172: 'iimage2DRect' : Reserved word.
|
||||
ERROR: 0:172: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:172: 'image variables declared 'writeonly' without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:172: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:173: 'image2DMS' : Reserved word.
|
||||
ERROR: 0:173: 'image variables declared 'writeonly' without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:173: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:174: 'uimage2DMSArray' : Reserved word.
|
||||
ERROR: 0:174: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:174: 'image variables declared 'writeonly' without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:174: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:181: 'rgba32f' : format requires readonly or writeonly memory qualifier
|
||||
ERROR: 0:182: 'rgba8i' : format requires readonly or writeonly memory qualifier
|
||||
ERROR: 0:183: 'rgba16ui' : format requires readonly or writeonly memory qualifier
|
||||
|
@ -84,7 +84,7 @@ WARNING: 0:238: '#define' : names containing consecutive underscores are reserve
|
|||
ERROR: 0:244: 'gl_DeviceIndex' : required extension not requested: GL_EXT_device_group
|
||||
ERROR: 0:245: 'gl_ViewIndex' : undeclared identifier
|
||||
ERROR: 0:255: 'gl_ViewIndex' : undeclared identifier
|
||||
ERROR: 82 compilation errors. No code generated.
|
||||
ERROR: 83 compilation errors. No code generated.
|
||||
|
||||
|
||||
Shader version: 310
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
310.frag
|
||||
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:2: 'float' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:8: 'origin_upper_left' : not supported with this profile: es
|
||||
ERROR: 0:8: 'pixel_center_integer' : not supported with this profile: es
|
||||
|
@ -19,13 +18,13 @@ ERROR: 0:44: 'texel offset' : value is out of range: [gl_MinProgramTexelOffset,
|
|||
ERROR: 0:45: 'texel offset' : value is out of range: [gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]
|
||||
ERROR: 0:45: 'texel offset' : value is out of range: [gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]
|
||||
ERROR: 0:66: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:66: 'image variables declared 'writeonly' without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:66: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:67: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:67: 'image variables declared 'writeonly' without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:67: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:68: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:68: 'image variables declared 'writeonly' without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:68: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:69: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:69: 'image variables declared 'writeonly' without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:69: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:73: 'binding' : requires block, or sampler/image, or atomic-counter type
|
||||
ERROR: 0:77: 'location' : location is too large
|
||||
ERROR: 0:81: 'location' : too large for fragment output
|
||||
|
@ -36,7 +35,7 @@ ERROR: 0:83: 'layout-id value' : cannot be negative
|
|||
ERROR: 0:96: 'sampler/image' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:110: 'out' : cannot be bool
|
||||
ERROR: 0:111: 'image2D' : sampler/image types can only be used in uniform variables or function parameters: imageOut
|
||||
ERROR: 0:111: 'image variables declared 'writeonly' without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:111: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported with this profile: es
|
||||
ERROR: 0:112: 'out' : cannot be a matrix
|
||||
ERROR: 0:114: 'in' : cannot be bool
|
||||
ERROR: 0:115: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: ino
|
||||
|
@ -124,7 +123,7 @@ ERROR: 0:391: 'interpolateAtOffset' : first argument must be an interpolant, or
|
|||
ERROR: 0:392: 'interpolateAtOffset' : first argument must be an interpolant, or interpolant-array element
|
||||
ERROR: 0:396: 'interpolateAtCentroid' : first argument must be an interpolant, or interpolant-array element
|
||||
ERROR: 0:397: 'interpolateAtSample' : first argument must be an interpolant, or interpolant-array element
|
||||
ERROR: 0:400: 'blend equation' : required extension not requested: GL_KHR_blend_equation_advanced
|
||||
ERROR: 0:400: 'blend equation' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:423: 'blend equation' : can only apply to 'out'
|
||||
ERROR: 0:424: 'blend equation' : can only apply to a standalone qualifier
|
||||
ERROR: 0:425: 'blend equation' : can only apply to a standalone qualifier
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
310.geom
|
||||
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:29: 'fromVertex' : block instance name redefinition
|
||||
ERROR: 0:33: 'fromVertex' : redefinition
|
||||
ERROR: 0:35: 'fooC' : block instance name redefinition
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
310.tesc
|
||||
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:8: 'quads' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
|
||||
ERROR: 0:9: 'ccw' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
|
||||
ERROR: 0:10: 'fractional_even_spacing' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
310.tese
|
||||
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:7: 'vertices' : there is no such layout identifier for this stage taking an assigned value
|
||||
ERROR: 0:9: 'triangles' : cannot change previously set input primitive
|
||||
ERROR: 0:10: 'isolines' : cannot change previously set input primitive
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
310.vert
|
||||
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:3: 'shared' : not supported in this stage: vertex
|
||||
ERROR: 0:4: 'local_size_x' : there is no such layout identifier for this stage taking an assigned value
|
||||
ERROR: 0:5: 'buffer' : buffers can be declared only as blocks
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
310AofA.vert
|
||||
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:17: '' : array size required
|
||||
ERROR: 0:23: '' : array size required
|
||||
ERROR: 0:28: '[]' : only outermost dimension of an array of arrays can be implicitly sized
|
||||
|
@ -318,10 +317,29 @@ ERROR: node is still EOpNull!
|
|||
0:99 0 (const int)
|
||||
0:99 Constant:
|
||||
0:99 1 (const int)
|
||||
0:117 Function Definition: func(mf33[3][2]; ( global highp 3-component vector of float)
|
||||
0:117 Function Parameters:
|
||||
0:117 'x' ( in 3-element array of 2-element array of highp 3X3 matrix of float)
|
||||
0:119 Sequence
|
||||
0:119 Sequence
|
||||
0:119 move second child to first child ( temp highp 3X3 matrix of float)
|
||||
0:119 'a0' ( temp highp 3X3 matrix of float)
|
||||
0:119 direct index ( temp highp 3X3 matrix of float)
|
||||
0:119 direct index ( temp 2-element array of highp 3X3 matrix of float)
|
||||
0:119 'x' ( in 3-element array of 2-element array of highp 3X3 matrix of float)
|
||||
0:119 Constant:
|
||||
0:119 2 (const int)
|
||||
0:119 Constant:
|
||||
0:119 1 (const int)
|
||||
0:120 Branch: Return with expression
|
||||
0:120 direct index ( temp highp 3-component vector of float)
|
||||
0:120 'a0' ( temp highp 3X3 matrix of float)
|
||||
0:120 Constant:
|
||||
0:120 2 (const int)
|
||||
0:? Linker Objects
|
||||
0:? 'name' (layout( column_major shared) buffer 3-element array of block{layout( column_major shared) buffer implicitly-sized array of highp float u, layout( column_major shared) buffer implicitly-sized array of highp 4-component vector of float v})
|
||||
0:? 'uname' (layout( column_major shared) uniform 3-element array of block{layout( column_major shared) uniform highp float u, layout( column_major shared) uniform implicitly-sized array of highp 4-component vector of float v})
|
||||
0:? 'name2' (layout( column_major shared) buffer 3-element array of block{layout( column_major shared) buffer highp float u, layout( column_major shared) buffer implicitly-sized array of implicitly-sized array of highp 4-component vector of float v})
|
||||
0:? 'name2' (layout( column_major shared) buffer 3-element array of block{layout( column_major shared) buffer highp float u, layout( column_major shared) buffer implicitly-sized array of 1-element array of highp 4-component vector of float v})
|
||||
0:? 'name3' (layout( column_major shared) buffer 3-element array of block{layout( column_major shared) buffer highp float u, layout( column_major shared) buffer implicitly-sized array of 7-element array of highp 4-component vector of float v})
|
||||
0:? 'many' ( global 1-element array of 2-element array of 3-element array of 4-element array of 5-element array of 6-element array of highp float)
|
||||
0:? 'gu' ( global implicitly-sized array of 7-element array of highp float)
|
||||
|
@ -362,7 +380,7 @@ ERROR: node is still EOpNull!
|
|||
0:? Linker Objects
|
||||
0:? 'name' (layout( column_major shared) buffer 3-element array of block{layout( column_major shared) buffer implicitly-sized array of highp float u, layout( column_major shared) buffer implicitly-sized array of highp 4-component vector of float v})
|
||||
0:? 'uname' (layout( column_major shared) uniform 3-element array of block{layout( column_major shared) uniform highp float u, layout( column_major shared) uniform 1-element array of highp 4-component vector of float v})
|
||||
0:? 'name2' (layout( column_major shared) buffer 3-element array of block{layout( column_major shared) buffer highp float u, layout( column_major shared) buffer implicitly-sized array of implicitly-sized array of highp 4-component vector of float v})
|
||||
0:? 'name2' (layout( column_major shared) buffer 3-element array of block{layout( column_major shared) buffer highp float u, layout( column_major shared) buffer implicitly-sized array of 1-element array of highp 4-component vector of float v})
|
||||
0:? 'name3' (layout( column_major shared) buffer 3-element array of block{layout( column_major shared) buffer highp float u, layout( column_major shared) buffer implicitly-sized array of 7-element array of highp 4-component vector of float v})
|
||||
0:? 'many' ( global 1-element array of 2-element array of 3-element array of 4-element array of 5-element array of 6-element array of highp float)
|
||||
0:? 'gu' ( global 1-element array of 7-element array of highp float)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
310implicitSizeArrayError.vert
|
||||
Warning, version 310 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:3: '' : array size required
|
||||
ERROR: 1 compilation errors. No code generated.
|
||||
|
||||
|
@ -13,13 +12,13 @@ ERROR: node is still EOpNull!
|
|||
0:7 'o' (layout( location=0) smooth out highp int)
|
||||
0:7 direct index (layout( column_major shared) temp highp int)
|
||||
0:7 a: direct index for structure (layout( column_major shared) uniform implicitly-sized array of highp int)
|
||||
0:7 'uni' (layout( location=0 column_major shared) uniform block{layout( column_major shared) uniform implicitly-sized array of highp int a})
|
||||
0:7 'uni' (layout( binding=0 column_major shared) uniform block{layout( column_major shared) uniform implicitly-sized array of highp int a})
|
||||
0:7 Constant:
|
||||
0:7 0 (const int)
|
||||
0:7 Constant:
|
||||
0:7 2 (const int)
|
||||
0:? Linker Objects
|
||||
0:? 'uni' (layout( location=0 column_major shared) uniform block{layout( column_major shared) uniform implicitly-sized array of highp int a})
|
||||
0:? 'uni' (layout( binding=0 column_major shared) uniform block{layout( column_major shared) uniform implicitly-sized array of highp int a})
|
||||
0:? 'o' (layout( location=0) smooth out highp int)
|
||||
0:? 'gl_VertexID' ( gl_VertexId highp int VertexId)
|
||||
0:? 'gl_InstanceID' ( gl_InstanceId highp int InstanceId)
|
||||
|
@ -37,13 +36,13 @@ ERROR: node is still EOpNull!
|
|||
0:7 'o' (layout( location=0) smooth out highp int)
|
||||
0:7 direct index (layout( column_major shared) temp highp int)
|
||||
0:7 a: direct index for structure (layout( column_major shared) uniform 1-element array of highp int)
|
||||
0:7 'uni' (layout( location=0 column_major shared) uniform block{layout( column_major shared) uniform 1-element array of highp int a})
|
||||
0:7 'uni' (layout( binding=0 column_major shared) uniform block{layout( column_major shared) uniform 1-element array of highp int a})
|
||||
0:7 Constant:
|
||||
0:7 0 (const int)
|
||||
0:7 Constant:
|
||||
0:7 2 (const int)
|
||||
0:? Linker Objects
|
||||
0:? 'uni' (layout( location=0 column_major shared) uniform block{layout( column_major shared) uniform 1-element array of highp int a})
|
||||
0:? 'uni' (layout( binding=0 column_major shared) uniform block{layout( column_major shared) uniform 1-element array of highp int a})
|
||||
0:? 'o' (layout( location=0) smooth out highp int)
|
||||
0:? 'gl_VertexID' ( gl_VertexId highp int VertexId)
|
||||
0:? 'gl_InstanceID' ( gl_InstanceId highp int InstanceId)
|
||||
|
|
|
@ -16,6 +16,7 @@ ERROR: 0:57: 'location on block member' : not supported for this version or the
|
|||
ERROR: 0:62: 'location on block member' : can only use in an in/out block
|
||||
ERROR: 0:62: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:60: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:60: 'location' : cannot apply to uniform or buffer block
|
||||
ERROR: 0:68: 'layout-id value' : cannot be negative
|
||||
ERROR: 0:69: 'layout-id value' : cannot be negative
|
||||
ERROR: 0:76: 'f2' : cannot use layout qualifiers on structure members
|
||||
|
@ -23,6 +24,7 @@ ERROR: 0:91: 'location on block member' : can only use in an in/out block
|
|||
ERROR: 0:91: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:91: 'location' : overlapping use of location 3
|
||||
ERROR: 0:89: 'location qualifier on uniform or buffer' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:89: 'location' : cannot apply to uniform or buffer block
|
||||
ERROR: 0:94: 'location' : either the block needs a location, or all members need a location, or no members have a location
|
||||
ERROR: 0:108: 'A' : cannot use layout qualifiers on structure members
|
||||
ERROR: 0:119: 'location' : overlapping use of location 44
|
||||
|
@ -38,7 +40,7 @@ ERROR: 0:140: 'assign' : cannot convert from ' const float' to ' temp 2-compone
|
|||
ERROR: 0:141: 'textureQueryLod' : no matching overloaded function found
|
||||
ERROR: 0:141: 'assign' : cannot convert from ' const float' to ' temp 2-component vector of float'
|
||||
ERROR: 0:152: 'index' : value must be 0 or 1
|
||||
ERROR: 39 compilation errors. No code generated.
|
||||
ERROR: 41 compilation errors. No code generated.
|
||||
|
||||
|
||||
Shader version: 330
|
||||
|
@ -100,7 +102,7 @@ ERROR: node is still EOpNull!
|
|||
0:? 'v20' ( smooth in 4-component vector of float)
|
||||
0:? 'v21' (layout( location=60) smooth in float)
|
||||
0:? 'v22' (layout( location=2) smooth in float)
|
||||
0:? 'anon@1' ( in block{layout( location=1 component=0) in float f1, layout( location=3) in float f2})
|
||||
0:? 'anon@1' ( in block{layout( location=1) in float f1, layout( location=3) in float f2})
|
||||
0:? 'uinst' (layout( location=1 column_major shared) uniform block{layout( column_major shared) uniform float f1, layout( location=3 column_major shared) uniform float f2})
|
||||
0:? 'v3' (layout( location=6) smooth in 4-component vector of float)
|
||||
0:? 'v4' ( smooth in 4-component vector of float)
|
||||
|
@ -108,12 +110,12 @@ ERROR: node is still EOpNull!
|
|||
0:? 'v6' (layout( location=30) smooth in 4-component vector of float)
|
||||
0:? 'v23' (layout( location=61) smooth in float)
|
||||
0:? 'v24' (layout( location=62) smooth in float)
|
||||
0:? 'ininst2' ( in block{layout( location=28 component=0) in bool b1, layout( location=29 component=0) in float f1, layout( location=25) in float f2, layout( location=26 component=0) in 4-component vector of float f3, layout( location=21) in structure{ global float f1, temp float f2} s2, layout( location=23 component=0) in 4-component vector of float f4, layout( location=24 component=0) in 4-component vector of float f5})
|
||||
0:? 'ininst2' ( in block{layout( location=28) in bool b1, layout( location=29) in float f1, layout( location=25) in float f2, layout( location=26) in 4-component vector of float f3, layout( location=21) in structure{ global float f1, temp float f2} s2, layout( location=23) in 4-component vector of float f4, layout( location=24) in 4-component vector of float f5})
|
||||
0:? 'uinst2' (layout( location=13 column_major shared) uniform block{layout( column_major shared) uniform float f1, layout( location=3 column_major shared) uniform float f2})
|
||||
0:? 'in3' ( in block{ in float f1, layout( location=40) in float f2})
|
||||
0:? 'in4' ( in block{layout( location=50) in float f1, layout( location=51) in float f2})
|
||||
0:? 's' (layout( location=33) smooth in structure{ global 3-component vector of float a, global 2X2 matrix of float b, global 2-element array of 4-component vector of float c, temp 2-component vector of float A})
|
||||
0:? 'anon@2' ( in block{layout( location=44 component=0) in 4-component vector of float d, layout( location=45 component=0) in 4-component vector of float e, layout( location=47) in 4-component vector of float f, layout( location=48 component=0) in 4-component vector of float g, layout( location=41) in 4-component vector of float h, layout( location=42 component=0) in 4-component vector of float i, layout( location=43 component=0) in 4-component vector of float j, layout( location=44 component=0) in 4-component vector of float k})
|
||||
0:? 'anon@2' ( in block{layout( location=44) in 4-component vector of float d, layout( location=45) in 4-component vector of float e, layout( location=47) in 4-component vector of float f, layout( location=48) in 4-component vector of float g, layout( location=41) in 4-component vector of float h, layout( location=42) in 4-component vector of float i, layout( location=43) in 4-component vector of float j, layout( location=44) in 4-component vector of float k})
|
||||
0:? 'outVar2' (layout( location=4095 index=0) out 4-component vector of float)
|
||||
0:? 'outVar3' (layout( location=0 index=1) out 4-component vector of float)
|
||||
0:? 'outVar4' (layout( location=0 index=1) out 4-component vector of float)
|
||||
|
@ -165,7 +167,7 @@ ERROR: node is still EOpNull!
|
|||
0:? 'v20' ( smooth in 4-component vector of float)
|
||||
0:? 'v21' (layout( location=60) smooth in float)
|
||||
0:? 'v22' (layout( location=2) smooth in float)
|
||||
0:? 'anon@1' ( in block{layout( location=1 component=0) in float f1, layout( location=3) in float f2})
|
||||
0:? 'anon@1' ( in block{layout( location=1) in float f1, layout( location=3) in float f2})
|
||||
0:? 'uinst' (layout( location=1 column_major shared) uniform block{layout( column_major shared) uniform float f1, layout( location=3 column_major shared) uniform float f2})
|
||||
0:? 'v3' (layout( location=6) smooth in 4-component vector of float)
|
||||
0:? 'v4' ( smooth in 4-component vector of float)
|
||||
|
@ -173,12 +175,12 @@ ERROR: node is still EOpNull!
|
|||
0:? 'v6' (layout( location=30) smooth in 4-component vector of float)
|
||||
0:? 'v23' (layout( location=61) smooth in float)
|
||||
0:? 'v24' (layout( location=62) smooth in float)
|
||||
0:? 'ininst2' ( in block{layout( location=28 component=0) in bool b1, layout( location=29 component=0) in float f1, layout( location=25) in float f2, layout( location=26 component=0) in 4-component vector of float f3, layout( location=21) in structure{ global float f1, temp float f2} s2, layout( location=23 component=0) in 4-component vector of float f4, layout( location=24 component=0) in 4-component vector of float f5})
|
||||
0:? 'ininst2' ( in block{layout( location=28) in bool b1, layout( location=29) in float f1, layout( location=25) in float f2, layout( location=26) in 4-component vector of float f3, layout( location=21) in structure{ global float f1, temp float f2} s2, layout( location=23) in 4-component vector of float f4, layout( location=24) in 4-component vector of float f5})
|
||||
0:? 'uinst2' (layout( location=13 column_major shared) uniform block{layout( column_major shared) uniform float f1, layout( location=3 column_major shared) uniform float f2})
|
||||
0:? 'in3' ( in block{ in float f1, layout( location=40) in float f2})
|
||||
0:? 'in4' ( in block{layout( location=50) in float f1, layout( location=51) in float f2})
|
||||
0:? 's' (layout( location=33) smooth in structure{ global 3-component vector of float a, global 2X2 matrix of float b, global 2-element array of 4-component vector of float c, temp 2-component vector of float A})
|
||||
0:? 'anon@2' ( in block{layout( location=44 component=0) in 4-component vector of float d, layout( location=45 component=0) in 4-component vector of float e, layout( location=47) in 4-component vector of float f, layout( location=48 component=0) in 4-component vector of float g, layout( location=41) in 4-component vector of float h, layout( location=42 component=0) in 4-component vector of float i, layout( location=43 component=0) in 4-component vector of float j, layout( location=44 component=0) in 4-component vector of float k})
|
||||
0:? 'anon@2' ( in block{layout( location=44) in 4-component vector of float d, layout( location=45) in 4-component vector of float e, layout( location=47) in 4-component vector of float f, layout( location=48) in 4-component vector of float g, layout( location=41) in 4-component vector of float h, layout( location=42) in 4-component vector of float i, layout( location=43) in 4-component vector of float j, layout( location=44) in 4-component vector of float k})
|
||||
0:? 'outVar2' (layout( location=4095 index=0) out 4-component vector of float)
|
||||
0:? 'outVar3' (layout( location=0 index=1) out 4-component vector of float)
|
||||
0:? 'outVar4' (layout( location=0 index=1) out 4-component vector of float)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
400.frag
|
||||
Warning, version 400 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:18: 'textureGatherOffsets(...)' : must be a compile-time constant: offsets argument
|
||||
ERROR: 0:22: 'textureGatherOffset(...)' : must be a compile-time constant: component argument
|
||||
ERROR: 0:23: 'textureGatherOffset(...)' : must be 0, 1, 2, or 3: component argument
|
||||
|
@ -34,8 +33,12 @@ ERROR: 0:183: 'textureQueryLod' : no matching overloaded function found
|
|||
ERROR: 0:183: 'assign' : cannot convert from ' const float' to ' temp 2-component vector of float'
|
||||
ERROR: 0:184: 'textureQueryLod' : no matching overloaded function found
|
||||
ERROR: 0:184: 'assign' : cannot convert from ' const float' to ' temp 2-component vector of float'
|
||||
ERROR: 0:187: '' : syntax error
|
||||
ERROR: 35 compilation errors. No code generated.
|
||||
ERROR: 0:197: 'subroutine' : feature not yet implemented
|
||||
ERROR: 0:197: '' : default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification
|
||||
ERROR: 0:198: 'subroutine' : feature not yet implemented
|
||||
ERROR: 0:199: 'subroutine' : feature not yet implemented
|
||||
ERROR: 0:201: '' : syntax error, unexpected PRECISE, expecting IDENTIFIER
|
||||
ERROR: 39 compilation errors. No code generated.
|
||||
|
||||
|
||||
Shader version: 400
|
||||
|
@ -469,6 +472,39 @@ ERROR: node is still EOpNull!
|
|||
0:181 'pf3' ( temp 3-component vector of float)
|
||||
0:183 'lod' ( temp 2-component vector of float)
|
||||
0:184 'lod' ( temp 2-component vector of float)
|
||||
0:190 Function Definition: bitwiseConv( ( global void)
|
||||
0:190 Function Parameters:
|
||||
0:192 Sequence
|
||||
0:192 move second child to first child ( temp uint)
|
||||
0:192 'iout' ( out uint)
|
||||
0:192 bitwise and ( temp uint)
|
||||
0:192 'uu' ( uniform uint)
|
||||
0:192 Convert int to uint ( temp uint)
|
||||
0:192 'i' ( flat in int)
|
||||
0:193 add second child into first child ( temp uint)
|
||||
0:193 'iout' ( out uint)
|
||||
0:193 exclusive-or ( temp uint)
|
||||
0:193 'uu' ( uniform uint)
|
||||
0:193 Convert int to uint ( temp uint)
|
||||
0:193 'i' ( flat in int)
|
||||
0:194 add second child into first child ( temp uint)
|
||||
0:194 'iout' ( out uint)
|
||||
0:194 inclusive-or ( temp uint)
|
||||
0:194 Convert int to uint ( temp uint)
|
||||
0:194 'i' ( flat in int)
|
||||
0:194 'uu' ( uniform uint)
|
||||
0:198 Function Definition: subT1( ( temp float)
|
||||
0:198 Function Parameters:
|
||||
0:198 Sequence
|
||||
0:198 Branch: Return with expression
|
||||
0:198 Constant:
|
||||
0:198 1.000000
|
||||
0:199 Function Definition: subT2( ( temp float)
|
||||
0:199 Function Parameters:
|
||||
0:199 Sequence
|
||||
0:199 Branch: Return with expression
|
||||
0:199 Constant:
|
||||
0:199 1.000000
|
||||
0:? Linker Objects
|
||||
0:? 'c2D' ( smooth in 2-component vector of float)
|
||||
0:? 'i' ( flat in int)
|
||||
|
@ -512,6 +548,8 @@ ERROR: node is still EOpNull!
|
|||
0:? 'sampCubeAs' ( uniform samplerCubeArrayShadow)
|
||||
0:? 'sampBuf' ( uniform samplerBuffer)
|
||||
0:? 'sampRect' ( uniform sampler2DRect)
|
||||
0:? 'uu' ( uniform uint)
|
||||
0:? 'iout' ( out uint)
|
||||
|
||||
|
||||
Linked fragment stage:
|
||||
|
@ -685,4 +723,6 @@ ERROR: node is still EOpNull!
|
|||
0:? 'sampCubeAs' ( uniform samplerCubeArrayShadow)
|
||||
0:? 'sampBuf' ( uniform samplerBuffer)
|
||||
0:? 'sampRect' ( uniform sampler2DRect)
|
||||
0:? 'uu' ( uniform uint)
|
||||
0:? 'iout' ( out uint)
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
400.geom
|
||||
Warning, version 400 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:12: 'invocations' : can only apply to a standalone qualifier
|
||||
ERROR: 0:20: 'patch' : not supported in this stage: geometry
|
||||
ERROR: 0:20: 'gl_PointSize' : cannot add layout to redeclared block member
|
||||
ERROR: 0:20: 'gl_PointSize' : cannot add non-XFB layout to redeclared block member
|
||||
ERROR: 0:20: 'gl_PointSize' : cannot add patch to redeclared block member
|
||||
ERROR: 0:25: 'length' : array must first be sized by a redeclaration or layout qualifier
|
||||
ERROR: 0:36: 'length' : array must first be sized by a redeclaration or layout qualifier
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
400.tesc
|
||||
Warning, version 400 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:6: 'quads' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
|
||||
ERROR: 0:7: 'ccw' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
|
||||
ERROR: 0:8: 'fractional_even_spacing' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
400.tese
|
||||
Warning, version 400 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:3: 'vertices' : there is no such layout identifier for this stage taking an assigned value
|
||||
ERROR: 0:5: 'triangles' : cannot change previously set input primitive
|
||||
ERROR: 0:6: 'isolines' : cannot change previously set input primitive
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
400.vert
|
||||
Warning, version 400 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:3: 'vertex-shader `double` type input' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:4: 'vertex-shader `double` type input' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:5: 'vertex-shader `double` type input' : not supported for this version or the enabled extensions
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
410.geom
|
||||
Warning, version 410 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:8: 'myIn' : cannot redeclare a built-in block with a user name
|
||||
ERROR: 0:12: 'gl_myIn' : no declaration found for redeclaration
|
||||
ERROR: 0:20: 'gl_PerVertex' : can only redeclare a built-in block once, and before any use
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
410.tesc
|
||||
Warning, version 400 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:4: 'length' : array must first be sized by a redeclaration or layout qualifier
|
||||
ERROR: 1 compilation errors. No code generated.
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
410.vert
|
||||
Warning, version 410 is not yet complete; most version-specific features are present, but some are missing.
|
||||
|
||||
Shader version: 410
|
||||
0:? Sequence
|
||||
0:7 Function Definition: main( ( global void)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
420.comp
|
||||
Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:3: 'gl_WorkGroupSize' : not supported for this version or the enabled extensions
|
||||
ERROR: 1 compilation errors. No code generated.
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
420.frag
|
||||
Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:4: 'redeclaration' : all redeclarations must use the same depth layout on gl_FragDepth
|
||||
ERROR: 0:11: 'layout qualifier' : can only apply depth layout to gl_FragDepth
|
||||
ERROR: 0:12: 'gl_FragDepth' : cannot redeclare after use
|
||||
WARNING: 0:14: 'atomic_uint' : implicitly sized atomic_uint array treated as having one element for tracking the default offset
|
||||
ERROR: 3 compilation errors. No code generated.
|
||||
ERROR: 0:14: 'atomic_uint' : array must be explicitly sized
|
||||
ERROR: 4 compilation errors. No code generated.
|
||||
|
||||
|
||||
Shader version: 420
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
420.geom
|
||||
Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:9: 'length' : array must first be sized by a redeclaration or layout qualifier
|
||||
ERROR: 0:11: '[' : array must be sized by a redeclaration or layout qualifier before being indexed with a variable
|
||||
ERROR: 0:42: 'assign' : l-value required (can't modify a const)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
420.tesc
|
||||
Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:7: 'vertices' : inconsistent output number of vertices for array size of gl_out
|
||||
ERROR: 0:11: 'vertices' : inconsistent output number of vertices for array size of a
|
||||
ERROR: 0:12: 'vertices' : inconsistent output number of vertices for array size of outb
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
420.tese
|
||||
Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:7: '=' : cannot convert from ' const 3-element array of float' to ' global 2-element array of float'
|
||||
ERROR: 0:8: 'initializer list' : wrong vector size (or rows in a matrix column): temp 2-component vector of float
|
||||
ERROR: 0:9: 'initializer list' : wrong number of matrix columns: temp 3X3 matrix of float
|
||||
|
@ -11,7 +10,7 @@ ERROR: 0:29: 'constructor' : cannot convert parameter 2 from ' const 2X2 matrix
|
|||
ERROR: 0:29: ' const 2-element array of 4-component vector of float' : cannot construct with these arguments
|
||||
ERROR: 0:29: '=' : cannot convert from ' const float' to ' global 2-element array of 4-component vector of float'
|
||||
ERROR: 0:30: 'initializer list' : wrong number of matrix columns: temp 4X2 matrix of float
|
||||
ERROR: 0:40: 'constructor' : cannot convert parameter 1 from ' temp float' to ' temp structure{ global float s, global float t}'
|
||||
ERROR: 0:40: 'constructor' : cannot convert parameter 1 from ' const structure{ global 4-component vector of float a, global 4-component vector of float b}' to ' temp structure{ global float s, global float t}'
|
||||
ERROR: 0:70: 'initializer list' : wrong number of structure members
|
||||
ERROR: 13 compilation errors. No code generated.
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
420.vert
|
||||
Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:2: '#version' : must occur first in shader
|
||||
WARNING: 0:3: varying deprecated in version 130; may be removed in future release
|
||||
ERROR: 0:3: 'varying' : no longer supported in core profile; removed in version 420
|
||||
|
@ -33,7 +32,7 @@ ERROR: 0:85: '' : vertex input cannot be further qualified
|
|||
ERROR: 0:86: 'patch' : not supported in this stage: vertex
|
||||
ERROR: 0:100: '=' : global const initializers must be constant ' const int'
|
||||
ERROR: 0:101: '' : array size must be a constant integer expression
|
||||
ERROR: 0:107: 'image variables declared 'writeonly' without a format layout qualifier' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:107: 'image variables not declared 'writeonly' and without a format layout qualifier' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:114: 'imageAtomicMin' : only supported on image with format r32i or r32ui
|
||||
ERROR: 0:115: 'imageAtomicMax' : no matching overloaded function found
|
||||
ERROR: 0:119: 'writeonly' : argument cannot drop memory qualifier when passed to formal parameter
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
420_size_gl_in.geom
|
||||
Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:19: 'gl_PerVertex' : can only redeclare a built-in block once, and before any use
|
||||
ERROR: 1 compilation errors. No code generated.
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
430.comp
|
||||
Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:4: 'local_size' : cannot change previously set size
|
||||
ERROR: 0:5: 'local_size' : too large; see gl_MaxComputeWorkGroupSize
|
||||
ERROR: 0:43: 'in' : global storage input qualifier cannot be used in a compute shader
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
430.vert
|
||||
Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:3: 'location' : can only apply to uniform, buffer, in, or out storage qualifiers
|
||||
ERROR: 0:7: 'input block' : not supported in this stage: vertex
|
||||
ERROR: 0:7: 'location qualifier on in/out block' : not supported for this version or the enabled extensions
|
||||
|
@ -233,7 +232,7 @@ ERROR: node is still EOpNull!
|
|||
0:? 'start2' ( const int)
|
||||
0:? 5 (const int)
|
||||
0:? 'v6' (layout( location=19) in 4-component vector of float)
|
||||
0:? 'ininst2' ( in block{layout( location=28 component=0) in bool b1, layout( location=29 component=0) in float f1, layout( location=25) in float f2})
|
||||
0:? 'ininst2' ( in block{layout( location=28) in bool b1, layout( location=29) in float f1, layout( location=25) in float f2})
|
||||
0:? 'in4' ( in block{layout( location=50) in float f1, layout( location=51) in float f2})
|
||||
0:? 'bbinst2g' ( out block{layout( xfb_buffer=3 xfb_offset=64) out 4-component vector of float bbv})
|
||||
0:? 'bg' (layout( xfb_buffer=1 xfb_offset=48 xfb_stride=80) smooth out 4-component vector of float)
|
||||
|
@ -308,7 +307,7 @@ ERROR: node is still EOpNull!
|
|||
0:? 'start2' ( const int)
|
||||
0:? 5 (const int)
|
||||
0:? 'v6' (layout( location=19) in 4-component vector of float)
|
||||
0:? 'ininst2' ( in block{layout( location=28 component=0) in bool b1, layout( location=29 component=0) in float f1, layout( location=25) in float f2})
|
||||
0:? 'ininst2' ( in block{layout( location=28) in bool b1, layout( location=29) in float f1, layout( location=25) in float f2})
|
||||
0:? 'in4' ( in block{layout( location=50) in float f1, layout( location=51) in float f2})
|
||||
0:? 'bbinst2g' ( out block{layout( xfb_buffer=3 xfb_offset=64) out 4-component vector of float bbv})
|
||||
0:? 'bg' (layout( xfb_buffer=1 xfb_offset=48 xfb_stride=80) smooth out 4-component vector of float)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
430AofA.frag
|
||||
Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:6: '[]' : only outermost dimension of an array of arrays can be implicitly sized
|
||||
ERROR: 0:14: 'constructor' : constructing non-array constituent from array argument
|
||||
ERROR: 0:15: 'constructor' : array constructor argument not correct type to construct array element
|
||||
|
@ -406,7 +405,7 @@ ERROR: node is still EOpNull!
|
|||
0:? Linker Objects
|
||||
0:? 'many' ( global 1-element array of 2-element array of 3-element array of 4-element array of 5-element array of 6-element array of float)
|
||||
0:? 'gu' ( global implicitly-sized array of 7-element array of float)
|
||||
0:? 'gimp' ( global implicitly-sized array of implicitly-sized array of float)
|
||||
0:? 'gimp' ( global implicitly-sized array of 1-element array of float)
|
||||
0:? 'g4' ( global 4-element array of 7-element array of float)
|
||||
0:? 'g5' ( global 5-element array of 7-element array of float)
|
||||
|
||||
|
@ -769,7 +768,7 @@ ERROR: node is still EOpNull!
|
|||
0:? Linker Objects
|
||||
0:? 'many' ( global 1-element array of 2-element array of 3-element array of 4-element array of 5-element array of 6-element array of float)
|
||||
0:? 'gu' ( global 1-element array of 7-element array of float)
|
||||
0:? 'gimp' ( global 1-element array of implicitly-sized array of float)
|
||||
0:? 'gimp' ( global 1-element array of 1-element array of float)
|
||||
0:? 'g4' ( global 4-element array of 7-element array of float)
|
||||
0:? 'g5' ( global 5-element array of 7-element array of float)
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
430scope.vert
|
||||
Warning, version 430 is not yet complete; most version-specific features are present, but some are missing.
|
||||
ERROR: 0:5: 'a' : redefinition
|
||||
ERROR: 0:17: 'b' : function name is redeclaration of existing name
|
||||
ERROR: 0:20: 'c' : redefinition
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue