From a3b0dde24b3b841ca6924788a9052bb52e8b4e22 Mon Sep 17 00:00:00 2001 From: bkaradzic Date: Sun, 25 Nov 2012 18:24:50 -0800 Subject: [PATCH] Fixes. Added vsh output/fsh input hash matching. --- 3rdparty/fcpp/cpp.h | 2 +- 3rdparty/openctm/lib/compressMG2.c | 2 +- 3rdparty/openctm/lib/openctm.c | 6 +- 3rdparty/openctm/lib/stream.c | 6 +- 3rdparty/openctm/tools/3ds.cpp | 44 +- 3rdparty/openctm/tools/common.h | 2 + 3rdparty/openctm/tools/convoptions.cpp | 10 +- 3rdparty/openctm/tools/ctm.cpp | 6 +- 3rdparty/openctm/tools/ctmconv.cpp | 155 +++-- 3rdparty/openctm/tools/dae.cpp | 14 +- 3rdparty/openctm/tools/lwo.cpp | 34 +- 3rdparty/openctm/tools/mesh.cpp | 8 +- 3rdparty/openctm/tools/meshio.cpp | 6 +- 3rdparty/openctm/tools/obj.cpp | 14 +- 3rdparty/openctm/tools/off.cpp | 12 +- 3rdparty/openctm/tools/ply.cpp | 12 +- 3rdparty/openctm/tools/stl.cpp | 12 +- 3rdparty/openctm/tools/wrl.cpp | 16 +- README.md | 111 +++- examples/01-cubes/makefile | 1 + examples/02-metaballs/makefile | 1 + examples/03-raymarch/makefile | 1 + examples/04-mesh/makefile | 1 + examples/05-instancing/makefile | 1 + examples/06-bump/bump.cpp | 2 +- examples/06-bump/makefile | 1 + examples/common/dbg.cpp | 13 +- examples/runtime/shaders/dx11/fs_bump.bin | Bin 4264 -> 4272 bytes examples/runtime/shaders/dx11/fs_cubes.bin | Bin 486 -> 494 bytes .../runtime/shaders/dx11/fs_instancing.bin | Bin 486 -> 494 bytes examples/runtime/shaders/dx11/fs_mesh.bin | Bin 2267 -> 2275 bytes .../runtime/shaders/dx11/fs_metaballs.bin | Bin 890 -> 898 bytes .../runtime/shaders/dx11/fs_raymarching.bin | Bin 10695 -> 10703 bytes examples/runtime/shaders/dx11/vs_bump.bin | Bin 2664 -> 2672 bytes examples/runtime/shaders/dx11/vs_cubes.bin | Bin 1068 -> 1076 bytes .../runtime/shaders/dx11/vs_instancing.bin | Bin 1395 -> 1403 bytes examples/runtime/shaders/dx11/vs_mesh.bin | Bin 2039 -> 2047 bytes .../runtime/shaders/dx11/vs_metaballs.bin | Bin 1282 -> 1290 bytes .../runtime/shaders/dx11/vs_raymarching.bin | Bin 1176 -> 1184 bytes examples/runtime/shaders/dx9/fs_bump.bin | Bin 2199 -> 2207 bytes examples/runtime/shaders/dx9/fs_cubes.bin | Bin 129 -> 137 bytes .../runtime/shaders/dx9/fs_instancing.bin | Bin 129 -> 137 bytes examples/runtime/shaders/dx9/fs_mesh.bin | Bin 1270 -> 1278 bytes examples/runtime/shaders/dx9/fs_metaballs.bin | Bin 473 -> 481 bytes .../runtime/shaders/dx9/fs_raymarching.bin | Bin 47422 -> 47430 bytes examples/runtime/shaders/dx9/vs_bump.bin | Bin 1051 -> 1059 bytes examples/runtime/shaders/dx9/vs_cubes.bin | Bin 311 -> 319 bytes .../runtime/shaders/dx9/vs_instancing.bin | Bin 466 -> 474 bytes examples/runtime/shaders/dx9/vs_mesh.bin | Bin 974 -> 982 bytes examples/runtime/shaders/dx9/vs_metaballs.bin | Bin 433 -> 441 bytes .../runtime/shaders/dx9/vs_raymarching.bin | Bin 347 -> 355 bytes examples/runtime/shaders/gles/fs_bump.bin | Bin 4125 -> 4133 bytes examples/runtime/shaders/gles/fs_cubes.bin | Bin 122 -> 130 bytes .../runtime/shaders/gles/fs_instancing.bin | Bin 122 -> 130 bytes examples/runtime/shaders/gles/fs_mesh.bin | Bin 1248 -> 1256 bytes .../runtime/shaders/gles/fs_metaballs.bin | Bin 358 -> 366 bytes .../runtime/shaders/gles/fs_raymarching.bin | Bin 9562 -> 9570 bytes examples/runtime/shaders/gles/vs_bump.bin | Bin 1605 -> 1613 bytes examples/runtime/shaders/gles/vs_cubes.bin | Bin 312 -> 320 bytes .../runtime/shaders/gles/vs_instancing.bin | Bin 558 -> 566 bytes examples/runtime/shaders/gles/vs_mesh.bin | Bin 1344 -> 1352 bytes .../runtime/shaders/gles/vs_metaballs.bin | Bin 485 -> 493 bytes .../runtime/shaders/gles/vs_raymarching.bin | Bin 395 -> 403 bytes examples/runtime/shaders/glsl/fs_bump.bin | Bin 4086 -> 4094 bytes examples/runtime/shaders/glsl/fs_cubes.bin | Bin 83 -> 91 bytes .../runtime/shaders/glsl/fs_instancing.bin | Bin 83 -> 91 bytes examples/runtime/shaders/glsl/fs_mesh.bin | Bin 1209 -> 1217 bytes .../runtime/shaders/glsl/fs_metaballs.bin | Bin 319 -> 327 bytes .../runtime/shaders/glsl/fs_raymarching.bin | Bin 9523 -> 9531 bytes examples/runtime/shaders/glsl/vs_bump.bin | Bin 1566 -> 1574 bytes examples/runtime/shaders/glsl/vs_cubes.bin | Bin 273 -> 281 bytes .../runtime/shaders/glsl/vs_instancing.bin | Bin 519 -> 527 bytes examples/runtime/shaders/glsl/vs_mesh.bin | Bin 1305 -> 1313 bytes .../runtime/shaders/glsl/vs_metaballs.bin | Bin 446 -> 454 bytes .../runtime/shaders/glsl/vs_raymarching.bin | Bin 356 -> 364 bytes include/bgfx.h | 13 +- premake/premake4.lua | 3 +- premake/shader.mk | 6 +- premake/shaderc.lua | 3 +- premake/{ddsdump.lua => texturec.lua} | 5 +- src/bgfx.cpp | 127 +++- src/bgfx_p.h | 211 +++--- src/config.h | 7 + src/dds.cpp | 78 +-- src/fs_clear_dx11.bin.h | 63 +- src/fs_debugfont_dx11.bin.h | 109 ++-- src/fs_debugfont_dx9.bin.h | 47 +- src/fs_debugfont_glsl.bin.h | 47 +- src/glimports.h | 6 + src/renderer_d3d11.cpp | 337 ++++++---- src/renderer_d3d11.h | 36 +- src/renderer_d3d9.cpp | 185 +++--- src/renderer_d3d9.h | 33 +- src/renderer_gl.cpp | 186 ++++-- src/renderer_gl.h | 28 +- src/renderer_null.cpp | 8 +- src/vs_clear_dx11.bin.h | 75 +-- src/vs_debugfont_dx11.bin.h | 166 ++--- src/vs_debugfont_dx9.bin.h | 45 +- src/vs_debugfont_glsl.bin.h | 62 +- tools/bin/shaderc.exe | Bin 1079296 -> 1084416 bytes tools/{ => shaderc}/shaderc.cpp | 604 +++++++----------- tools/{ddsdump.cpp => texturec/texturec.cpp} | 7 +- 103 files changed, 1610 insertions(+), 1380 deletions(-) rename premake/{ddsdump.lua => texturec.lua} (66%) rename tools/{ => shaderc}/shaderc.cpp (78%) rename tools/{ddsdump.cpp => texturec/texturec.cpp} (91%) diff --git a/3rdparty/fcpp/cpp.h b/3rdparty/fcpp/cpp.h index b60c7399a..c8084af7e 100644 --- a/3rdparty/fcpp/cpp.h +++ b/3rdparty/fcpp/cpp.h @@ -202,7 +202,7 @@ typedef struct sizes { */ #ifdef nomacarg -#define cput output /* cput concatenates tokens */ +#define cput generate /* cput concatenates tokens */ #else #if COMMENT_INVISIBLE #define cput(c) { if (c != TOK_SEP && c != COM_SEP) putchar(c); } diff --git a/3rdparty/openctm/lib/compressMG2.c b/3rdparty/openctm/lib/compressMG2.c index 787928349..064379a95 100644 --- a/3rdparty/openctm/lib/compressMG2.c +++ b/3rdparty/openctm/lib/compressMG2.c @@ -506,7 +506,7 @@ static void _ctmMakeNormalCoordSys(CTMfloat * aNormal, CTMfloat * aBasisAxes) x[2] = aNormal[1]; // Normalize the new X axis (note: |x[2]| = |x[0]|) - len = sqrtf(2.0 * x[0] * x[0] + x[1] * x[1]); + len = sqrtf(2.0f * x[0] * x[0] + x[1] * x[1]); if(len > 1.0e-20f) { len = 1.0f / len; diff --git a/3rdparty/openctm/lib/openctm.c b/3rdparty/openctm/lib/openctm.c index f1b9303ae..03461201c 100644 --- a/3rdparty/openctm/lib/openctm.c +++ b/3rdparty/openctm/lib/openctm.c @@ -913,7 +913,7 @@ CTMEXPORT void CTMCALL ctmFileComment(CTMcontext aContext, // Get length of string (if empty, do nothing) if(!aFileComment) return; - len = strlen(aFileComment); + len = (int)strlen(aFileComment); if(!len) return; @@ -1005,7 +1005,7 @@ static _CTMfloatmap * _ctmAddFloatMap(_CTMcontext * self, if(aName) { // Get length of string (if empty, do nothing) - len = strlen(aName); + len = (CTMuint)strlen(aName); if(len) { // Copy the string @@ -1024,7 +1024,7 @@ static _CTMfloatmap * _ctmAddFloatMap(_CTMcontext * self, if(aFileName) { // Get length of string (if empty, do nothing) - len = strlen(aFileName); + len = (CTMuint)strlen(aFileName); if(len) { // Copy the string diff --git a/3rdparty/openctm/lib/stream.c b/3rdparty/openctm/lib/stream.c index 5ed85b7a9..5cd67cd03 100644 --- a/3rdparty/openctm/lib/stream.c +++ b/3rdparty/openctm/lib/stream.c @@ -155,7 +155,7 @@ void _ctmStreamWriteSTRING(_CTMcontext * self, const char * aValue) // Get string length if(aValue) - len = strlen(aValue); + len = (CTMuint)strlen(aValue); else len = 0; @@ -194,7 +194,7 @@ int _ctmStreamReadPackedInts(_CTMcontext * self, CTMint * aData, self->mError = CTM_OUT_OF_MEMORY; return CTM_FALSE; } - _ctmStreamRead(self, (void *) packed, packedSize); + _ctmStreamRead(self, (void *) packed, (CTMuint)packedSize); // Allocate memory for interleaved array tmp = (unsigned char *) malloc(aCount * aSize * 4); @@ -374,7 +374,7 @@ int _ctmStreamReadPackedFloats(_CTMcontext * self, CTMfloat * aData, self->mError = CTM_OUT_OF_MEMORY; return CTM_FALSE; } - _ctmStreamRead(self, (void *) packed, packedSize); + _ctmStreamRead(self, (void *) packed, (CTMuint)packedSize); // Allocate memory for interleaved array tmp = (unsigned char *) malloc(aCount * aSize * 4); diff --git a/3rdparty/openctm/tools/3ds.cpp b/3rdparty/openctm/tools/3ds.cpp index 62f0beae8..10761894b 100644 --- a/3rdparty/openctm/tools/3ds.cpp +++ b/3rdparty/openctm/tools/3ds.cpp @@ -25,7 +25,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include @@ -174,16 +174,16 @@ void Import_3DS(const char * aFileName, Mesh * aMesh) // Open the input file ifstream f(aFileName, ios::in | ios::binary); if(f.fail()) - throw runtime_error("Could not open input file."); + throw_runtime_error("Could not open input file."); // Get file size f.seekg(0, ios::end); - uint32 fileSize = f.tellg(); + uint32 fileSize = (uint32)f.tellg(); f.seekg(0, ios::beg); // Check file size (rough initial check) if(fileSize < 6) - throw runtime_error("Invalid 3DS file format."); + throw_runtime_error("Invalid 3DS file format."); uint16 chunk, count; uint32 chunkLen; @@ -192,7 +192,7 @@ void Import_3DS(const char * aFileName, Mesh * aMesh) chunk = ReadInt16(f); chunkLen = ReadInt32(f); if((chunk != CHUNK_MAIN) || (chunkLen != fileSize)) - throw runtime_error("Invalid 3DS file format."); + throw_runtime_error("Invalid 3DS file format."); // Parse chunks, and store the data in a temporary list, objList... Obj3DS * obj = 0; @@ -287,8 +287,8 @@ void Import_3DS(const char * aFileName, Mesh * aMesh) for(list::iterator o = objList.begin(); o != objList.end(); ++ o) { // Append... - uint32 idxOffset = aMesh->mIndices.size(); - uint32 vertOffset = aMesh->mVertices.size(); + uint32 idxOffset = (uint32)aMesh->mIndices.size(); + uint32 vertOffset = (uint32)aMesh->mVertices.size(); aMesh->mIndices.resize(idxOffset + (*o).mIndices.size()); aMesh->mVertices.resize(vertOffset + (*o).mVertices.size()); if(hasUVCoords) @@ -317,7 +317,7 @@ void Export_3DS(const char * aFileName, Mesh * aMesh, Options &aOptions) // First, check that the mesh fits in a 3DS file (at most 65535 triangles // and 65535 vertices are supported). if((aMesh->mIndices.size() > (3*65535)) || (aMesh->mVertices.size() > 65535)) - throw runtime_error("The mesh is too large to fit in a 3DS file."); + throw_runtime_error("The mesh is too large to fit in a 3DS file."); // What should we export? bool exportTexCoords = aMesh->HasTexCoords() && !aOptions.mNoTexCoords; @@ -327,16 +327,16 @@ void Export_3DS(const char * aFileName, Mesh * aMesh, Options &aOptions) string matName("Material0"); // Get mesh properties - uint32 triCount = aMesh->mIndices.size() / 3; - uint32 vertCount = aMesh->mVertices.size(); + uint32 triCount = (uint32)(aMesh->mIndices.size() / 3); + uint32 vertCount = (uint32)aMesh->mVertices.size(); // Calculate the material chunk size uint32 materialSize = 0; uint32 matGroupSize = 0; if(exportTexCoords && aMesh->mTexFileName.size() > 0) { - materialSize += 24 + matName.size() + 1 + aMesh->mTexFileName.size() + 1; - matGroupSize += 8 + matName.size() + 1 + 2 * triCount; + materialSize += 24 + (uint32)matName.size() + 1 + (uint32)aMesh->mTexFileName.size() + 1; + matGroupSize += 8 + (uint32)matName.size() + 1 + 2 * triCount; } // Calculate the mesh chunk size @@ -345,12 +345,12 @@ void Export_3DS(const char * aFileName, Mesh * aMesh, Options &aOptions) triMeshSize += 8 + 8 * vertCount; // Calculate the total file size - uint32 fileSize = 38 + objName.size() + 1 + materialSize + triMeshSize; + uint32 fileSize = 38 + (uint32)objName.size() + 1 + materialSize + triMeshSize; // Open the output file ofstream f(aFileName, ios::out | ios::binary); if(f.fail()) - throw runtime_error("Could not open output file."); + throw_runtime_error("Could not open output file."); // Write file header WriteInt16(f, CHUNK_MAIN); @@ -361,7 +361,7 @@ void Export_3DS(const char * aFileName, Mesh * aMesh, Options &aOptions) // 3D Edit chunk WriteInt16(f, CHUNK_3DEDIT); - WriteInt32(f, 16 + materialSize + objName.size() + 1 + triMeshSize); + WriteInt32(f, 16 + materialSize + (uint32)objName.size() + 1 + triMeshSize); WriteInt16(f, CHUNK_MESH_VERSION); WriteInt32(f, 6 + 4); WriteInt32(f, 0x00000003); @@ -372,19 +372,19 @@ void Export_3DS(const char * aFileName, Mesh * aMesh, Options &aOptions) WriteInt16(f, CHUNK_MAT_ENTRY); WriteInt32(f, materialSize); WriteInt16(f, CHUNK_MAT_NAME); - WriteInt32(f, 6 + matName.size() + 1); - f.write(matName.c_str(), matName.size() + 1); + WriteInt32(f, 6 + (uint32)matName.size() + 1); + f.write(matName.c_str(), (uint32)matName.size() + 1); WriteInt16(f, CHUNK_MAT_TEXMAP); - WriteInt32(f, 12 + aMesh->mTexFileName.size() + 1); + WriteInt32(f, 12 + (uint32)aMesh->mTexFileName.size() + 1); WriteInt16(f, CHUNK_MAT_MAPNAME); - WriteInt32(f, 6 + aMesh->mTexFileName.size() + 1); - f.write(aMesh->mTexFileName.c_str(), aMesh->mTexFileName.size() + 1); + WriteInt32(f, 6 + (uint32)aMesh->mTexFileName.size() + 1); + f.write(aMesh->mTexFileName.c_str(), (uint32)aMesh->mTexFileName.size() + 1); } // Object chunk WriteInt16(f, CHUNK_OBJECT); - WriteInt32(f, 6 + objName.size() + 1 + triMeshSize); - f.write(objName.c_str(), objName.size() + 1); + WriteInt32(f, 6 + (uint32)objName.size() + 1 + triMeshSize); + f.write(objName.c_str(), (uint32)objName.size() + 1); // Triangle Mesh chunk WriteInt16(f, CHUNK_TRIMESH); diff --git a/3rdparty/openctm/tools/common.h b/3rdparty/openctm/tools/common.h index 11c545b22..9a8b4eb45 100644 --- a/3rdparty/openctm/tools/common.h +++ b/3rdparty/openctm/tools/common.h @@ -30,6 +30,8 @@ #include +void throw_runtime_error(std::string str); + // Convert a string to upper case. std::string UpperCase(const std::string &aString); diff --git a/3rdparty/openctm/tools/convoptions.cpp b/3rdparty/openctm/tools/convoptions.cpp index bab301b5c..95ac7f35a 100644 --- a/3rdparty/openctm/tools/convoptions.cpp +++ b/3rdparty/openctm/tools/convoptions.cpp @@ -25,7 +25,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include "convoptions.h" @@ -106,7 +106,7 @@ void Options::GetFromArgs(int argc, char **argv, int aStartIdx) else if(upaxis == string("-Z")) mUpAxis = uaNZ; else - throw runtime_error("Invalid up axis (use X, Y, Z, -X, -Y or -Z)."); + throw_runtime_error("Invalid up axis (use X, Y, Z, -X, -Y or -Z)."); } else if(cmd == string("--flip")) { @@ -139,13 +139,13 @@ void Options::GetFromArgs(int argc, char **argv, int aStartIdx) else if(method == string("MG2")) mMethod = CTM_METHOD_MG2; else - throw runtime_error("Invalid method (use RAW, MG1 or MG2)."); + throw_runtime_error("Invalid method (use RAW, MG1 or MG2)."); } else if((cmd == string("--level")) && (i < (argc - 1))) { CTMint val = GetIntArg(argv[i + 1]); if( (val < 0) || (val > 9) ) - throw runtime_error("Invalid compression level (it must be in the range 0 - 9)."); + throw_runtime_error("Invalid compression level (it must be in the range 0 - 9)."); mLevel = CTMuint(val); ++ i; } @@ -185,6 +185,6 @@ void Options::GetFromArgs(int argc, char **argv, int aStartIdx) ++ i; } else - throw runtime_error(string("Invalid argument: ") + cmd); + throw_runtime_error(string("Invalid argument: ") + cmd); } } diff --git a/3rdparty/openctm/tools/ctm.cpp b/3rdparty/openctm/tools/ctm.cpp index 7ed749d5a..7f1d1b5db 100644 --- a/3rdparty/openctm/tools/ctm.cpp +++ b/3rdparty/openctm/tools/ctm.cpp @@ -25,7 +25,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include "ctm.h" @@ -123,8 +123,8 @@ void Export_CTM(const char * aFileName, Mesh * aMesh, Options &aOptions) CTMfloat * normals = 0; if(aMesh->HasNormals() && !aOptions.mNoNormals) normals = &aMesh->mNormals[0].x; - ctm.DefineMesh((CTMfloat *) &aMesh->mVertices[0].x, aMesh->mVertices.size(), - (const CTMuint*) &aMesh->mIndices[0], aMesh->mIndices.size() / 3, + ctm.DefineMesh((CTMfloat *) &aMesh->mVertices[0].x, (CTMuint)aMesh->mVertices.size(), + (const CTMuint*) &aMesh->mIndices[0], (CTMuint)aMesh->mIndices.size() / 3, normals); // Define texture coordinates diff --git a/3rdparty/openctm/tools/ctmconv.cpp b/3rdparty/openctm/tools/ctmconv.cpp index 62993aab2..07e6811e6 100644 --- a/3rdparty/openctm/tools/ctmconv.cpp +++ b/3rdparty/openctm/tools/ctmconv.cpp @@ -27,7 +27,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include @@ -113,7 +113,7 @@ static void PreProcessMesh(Mesh &aMesh, Options &aOptions) // Flip trianlges? if(aOptions.mFlipTriangles) { - CTMuint triCount = aMesh.mIndices.size() / 3; + CTMuint triCount = (CTMuint)(aMesh.mIndices.size() / 3); for(CTMuint i = 0; i < triCount; ++ i) { CTMuint tmp = aMesh.mIndices[i * 3]; @@ -131,6 +131,11 @@ static void PreProcessMesh(Mesh &aMesh, Options &aOptions) cout << 1000.0 * dt << " ms" << endl; } +void throw_runtime_error(std::string str) +{ + cout << "Error: " << str << endl; + abort(); +} //----------------------------------------------------------------------------- // main() @@ -141,94 +146,84 @@ int main(int argc, char ** argv) Options opt; string inFile; string outFile; - try - { - if(argc < 3) - throw runtime_error("Too few arguments."); - inFile = string(argv[1]); - outFile = string(argv[2]); - opt.GetFromArgs(argc, argv, 3); - } - catch(exception &e) - { - cout << "Error: " << e.what() << endl << endl; - cout << "Usage: " << argv[0] << " infile outfile [options]" << endl << endl; - cout << "Options:" << endl; - cout << endl << " Data manipulation (all formats)" << endl; - cout << " --scale arg Scale the mesh by a scalar factor." << endl; - cout << " --upaxis arg Set up axis (X, Y, Z, -X, -Y, -Z). If != Z, the mesh will" << endl; - cout << " be flipped." << endl; - cout << " --flip Flip triangle orientation." << endl; - cout << " --calc-normals If the source file does not contain any normals, calculate" << endl; - cout << " them." << endl; - cout << " --no-normals Do not export normals." << endl; - cout << " --no-texcoords Do not export texture coordinates." << endl; - cout << " --no-colors Do not export vertex colors." << endl; - cout << endl << " OpenCTM output" << endl; - cout << " --method arg Select compression method (RAW, MG1, MG2)" << endl; - cout << " --level arg Set the compression level (0 - 9)" << endl; - cout << endl << " OpenCTM MG2 method" << endl; - cout << " --vprec arg Set vertex precision" << endl; - cout << " --vprecrel arg Set vertex precision, relative method" << endl; - cout << " --nprec arg Set normal precision" << endl; - cout << " --tprec arg Set texture map precision" << endl; - cout << " --cprec arg Set color precision" << endl; - cout << endl << " Miscellaneous" << endl; - cout << " --comment arg Set the file comment (default is to use the comment" << endl; - cout << " from the input file, if any)." << endl; - cout << " --texfile arg Set the texture file name reference for the texture" << endl; - cout << " (default is to use the texture file name reference" << endl; - cout << " from the input file, if any)." << endl; - // Show supported formats - cout << endl << "Supported file formats:" << endl << endl; - list formatList; - SupportedFormats(formatList); - for(list::iterator i = formatList.begin(); i != formatList.end(); ++ i) - cout << " " << (*i) << endl; - cout << endl; + if(argc < 3) + { + cout << "Error: Too few arguments." << endl << endl; + cout << "Usage: " << argv[0] << " infile outfile [options]" << endl << endl; + cout << "Options:" << endl; + cout << endl << " Data manipulation (all formats)" << endl; + cout << " --scale arg Scale the mesh by a scalar factor." << endl; + cout << " --upaxis arg Set up axis (X, Y, Z, -X, -Y, -Z). If != Z, the mesh will" << endl; + cout << " be flipped." << endl; + cout << " --flip Flip triangle orientation." << endl; + cout << " --calc-normals If the source file does not contain any normals, calculate" << endl; + cout << " them." << endl; + cout << " --no-normals Do not export normals." << endl; + cout << " --no-texcoords Do not export texture coordinates." << endl; + cout << " --no-colors Do not export vertex colors." << endl; + cout << endl << " OpenCTM output" << endl; + cout << " --method arg Select compression method (RAW, MG1, MG2)" << endl; + cout << " --level arg Set the compression level (0 - 9)" << endl; + cout << endl << " OpenCTM MG2 method" << endl; + cout << " --vprec arg Set vertex precision" << endl; + cout << " --vprecrel arg Set vertex precision, relative method" << endl; + cout << " --nprec arg Set normal precision" << endl; + cout << " --tprec arg Set texture map precision" << endl; + cout << " --cprec arg Set color precision" << endl; + cout << endl << " Miscellaneous" << endl; + cout << " --comment arg Set the file comment (default is to use the comment" << endl; + cout << " from the input file, if any)." << endl; + cout << " --texfile arg Set the texture file name reference for the texture" << endl; + cout << " (default is to use the texture file name reference" << endl; + cout << " from the input file, if any)." << endl; - return 0; + // Show supported formats + cout << endl << "Supported file formats:" << endl << endl; + list formatList; + SupportedFormats(formatList); + for(list::iterator i = formatList.begin(); i != formatList.end(); ++ i) + cout << " " << (*i) << endl; + cout << endl; + + return 0; } - try - { - // Define mesh - Mesh mesh; + inFile = string(argv[1]); + outFile = string(argv[2]); + opt.GetFromArgs(argc, argv, 3); - // Create a timer instance - SysTimer timer; - double dt; + // Define mesh + Mesh mesh; - // Load input file - cout << "Loading " << inFile << "... " << flush; - timer.Push(); - ImportMesh(inFile.c_str(), &mesh); - dt = timer.PopDelta(); - cout << 1000.0 * dt << " ms" << endl; + // Create a timer instance + SysTimer timer; + double dt; - // Manipulate the mesh - PreProcessMesh(mesh, opt); + // Load input file + cout << "Loading " << inFile << "... " << flush; + timer.Push(); + ImportMesh(inFile.c_str(), &mesh); + dt = timer.PopDelta(); + cout << 1000.0 * dt << " ms" << endl; - // Override comment? - if(opt.mComment.size() > 0) - mesh.mComment = opt.mComment; + // Manipulate the mesh + PreProcessMesh(mesh, opt); - // Override texture file name? - if(opt.mTexFileName.size() > 0) - mesh.mTexFileName = opt.mTexFileName; + // Override comment? + if(opt.mComment.size() > 0) + mesh.mComment = opt.mComment; - // Save output file - cout << "Saving " << outFile << "... " << flush; - timer.Push(); - ExportMesh(outFile.c_str(), &mesh, opt); - dt = timer.PopDelta(); - cout << 1000.0 * dt << " ms" << endl; - } - catch(exception &e) - { - cout << "Error: " << e.what() << endl; - } + // Override texture file name? + if(opt.mTexFileName.size() > 0) + mesh.mTexFileName = opt.mTexFileName; + + // Save output file + cout << "Saving " << outFile << "... " << flush; + timer.Push(); + ExportMesh(outFile.c_str(), &mesh, opt); + dt = timer.PopDelta(); + cout << 1000.0 * dt << " ms" << endl; return 0; } diff --git a/3rdparty/openctm/tools/dae.cpp b/3rdparty/openctm/tools/dae.cpp index d4c4521d1..5d18c4732 100644 --- a/3rdparty/openctm/tools/dae.cpp +++ b/3rdparty/openctm/tools/dae.cpp @@ -26,7 +26,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include @@ -454,7 +454,7 @@ void Import_DAE(const char * aFileName, Mesh * aMesh) aMesh->mTexCoords.resize(texcoordOffset ); for(size_t i = 0; i < indexVector.size(); ++i) - aMesh->mIndices[indicesOff + i] = indexVector[i]; + aMesh->mIndices[indicesOff + i] = (unsigned int)indexVector[i]; for(size_t i = 0; i < vertVector.size(); ++i) aMesh->mVertices[vertexOff + i] = vertVector[i]; @@ -469,7 +469,7 @@ void Import_DAE(const char * aFileName, Mesh * aMesh) } } else - throw runtime_error("Could not open input file."); + throw_runtime_error("Could not open input file."); } /// Dump a float array to an XML text node. @@ -563,7 +563,7 @@ void Export_DAE(const char * aFileName, Mesh * aMesh, Options &aOptions) source_position->LinkEndChild(positions_array); positions_array->SetAttribute("id", "Mesh-1-positions-array"); positions_array->SetAttribute("count", int(aMesh->mVertices.size() * 3)); - FloatArrayToXML(positions_array, &aMesh->mVertices[0].x, aMesh->mVertices.size() * 3); + FloatArrayToXML(positions_array, &aMesh->mVertices[0].x, (unsigned int)aMesh->mVertices.size() * 3); TiXmlElement * positions_technique = new TiXmlElement("technique_common"); source_position->LinkEndChild(positions_technique); TiXmlElement * positions_technique_accessor = new TiXmlElement("accessor"); @@ -596,7 +596,7 @@ void Export_DAE(const char * aFileName, Mesh * aMesh, Options &aOptions) source_normal->LinkEndChild(normals_array); normals_array->SetAttribute("id", "Mesh-1-normals-array"); normals_array->SetAttribute("count", int(aMesh->mVertices.size() * 3)); - FloatArrayToXML(normals_array, &aMesh->mNormals[0].x, aMesh->mNormals.size() * 3); + FloatArrayToXML(normals_array, &aMesh->mNormals[0].x, (unsigned int)aMesh->mNormals.size() * 3); TiXmlElement * normals_technique = new TiXmlElement("technique_common"); source_normal->LinkEndChild(normals_technique); TiXmlElement * normals_technique_accessor = new TiXmlElement("accessor"); @@ -630,7 +630,7 @@ void Export_DAE(const char * aFileName, Mesh * aMesh, Options &aOptions) source_map1->LinkEndChild(map1_array); map1_array->SetAttribute("id", "Mesh-1-map1-array"); map1_array->SetAttribute("count", int(aMesh->mVertices.size() * 3)); - FloatArrayToXML(map1_array, &aMesh->mTexCoords[0].u, aMesh->mTexCoords.size() * 2); + FloatArrayToXML(map1_array, &aMesh->mTexCoords[0].u, (unsigned int)aMesh->mTexCoords.size() * 2); TiXmlElement * map1_technique = new TiXmlElement("technique_common"); source_map1->LinkEndChild(map1_technique); TiXmlElement * map1_technique_accessor = new TiXmlElement("accessor"); @@ -721,5 +721,5 @@ void Export_DAE(const char * aFileName, Mesh * aMesh, Options &aOptions) // Save the XML document to a file xmlDoc.SaveFile(aFileName); if(xmlDoc.Error()) - throw runtime_error(string(xmlDoc.ErrorDesc())); + throw_runtime_error(string(xmlDoc.ErrorDesc())); } diff --git a/3rdparty/openctm/tools/lwo.cpp b/3rdparty/openctm/tools/lwo.cpp index b61d06bc5..9b1544ee8 100644 --- a/3rdparty/openctm/tools/lwo.cpp +++ b/3rdparty/openctm/tools/lwo.cpp @@ -25,7 +25,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include @@ -216,14 +216,14 @@ static void WriteVEC12(ostream &aStream, Vector3 aValue) /// Write a string to a stream (no zero termination). static void WriteString(ostream &aStream, const char * aString) { - int len = strlen(aString); + int len = (int)strlen(aString); aStream.write(aString, len); } /// Write a zero terminated string to a stream. static void WriteStringZ(ostream &aStream, const char * aString) { - int len = strlen(aString) + 1; + int len = (int)strlen(aString) + 1; aStream.write(aString, len); if(len & 1) { @@ -262,8 +262,8 @@ static uint32 CalcPOLSSize(Mesh * aMesh) /// account, but exclude the name string (at least two bytes)... static uint32 CalcVMAPSize(Mesh * aMesh, uint32 aDimension) { - uint32 size = 6 + aMesh->mVertices.size() * (2 + 4 * aDimension); - uint32 maxIdx = aMesh->mVertices.size() - 1; + uint32 size = (uint32)(6 + aMesh->mVertices.size() * (2 + 4 * aDimension)); + uint32 maxIdx = (uint32)(aMesh->mVertices.size() - 1); if(maxIdx >= 0x0000ff00) size += (maxIdx - 0x0000feff) * 2; return size; @@ -280,14 +280,14 @@ void Import_LWO(const char * aFileName, Mesh * aMesh) // Open the input file ifstream f(aFileName, ios::in | ios::binary); if(f.fail()) - throw runtime_error("Could not open input file."); + throw_runtime_error("Could not open input file."); // File header if(ReadString(f, 4) != string("FORM")) - throw runtime_error("Not a valid LWO file (missing FORM chunk)."); + throw_runtime_error("Not a valid LWO file (missing FORM chunk)."); uint32 fileSize = ReadU4(f); if(ReadString(f, 4) != string("LWO2")) - throw runtime_error("Not a valid LWO file (not LWO2 format)."); + throw_runtime_error("Not a valid LWO file (not LWO2 format)."); // Start with an empty mesh aMesh->Clear(); @@ -333,7 +333,7 @@ void Import_LWO(const char * aFileName, Mesh * aMesh) // Check point count uint32 newPoints = chunkSize / 12; if((newPoints * 12) != chunkSize) - throw runtime_error("Not a valid LWO file (invalid PNTS chunk)."); + throw_runtime_error("Not a valid LWO file (invalid PNTS chunk)."); // Read points (relative to current pivot point) aMesh->mVertices.resize(pointCount + newPoints); @@ -347,7 +347,7 @@ void Import_LWO(const char * aFileName, Mesh * aMesh) { // POLS before PNTS? if(!havePoints) - throw runtime_error("Not a valid LWO file (POLS chunk before PNTS chunk)."); + throw_runtime_error("Not a valid LWO file (POLS chunk before PNTS chunk)."); // Check that we have a FACE or PTCH descriptor. string type = ReadString(f, 4); @@ -424,7 +424,7 @@ void Import_LWO(const char * aFileName, Mesh * aMesh) if((type == string("RGB ")) || (type == string("RGBA"))) { // Resize the mesh colors array - uint32 oldSize = aMesh->mColors.size(); + uint32 oldSize = (uint32)aMesh->mColors.size(); aMesh->mColors.resize(pointCount); for(uint32 i = oldSize; i < pointCount; ++ i) aMesh->mColors[i] = Vector4(1.0f, 1.0f, 1.0f, 1.0f); @@ -456,7 +456,7 @@ void Import_LWO(const char * aFileName, Mesh * aMesh) else if((type == string("TXUV"))) { // Resize the mesh UV array - uint32 oldSize = aMesh->mTexCoords.size(); + uint32 oldSize = (uint32)aMesh->mTexCoords.size(); aMesh->mTexCoords.resize(pointCount); for(uint32 i = oldSize; i < pointCount; ++ i) aMesh->mTexCoords[i] = Vector2(0.0f, 0.0f); @@ -491,7 +491,7 @@ void Import_LWO(const char * aFileName, Mesh * aMesh) // Post-adjustment: color array (if any) if((aMesh->mColors.size() > 0) && (aMesh->mColors.size() < pointCount)) { - uint32 oldSize = aMesh->mColors.size(); + uint32 oldSize = (uint32)aMesh->mColors.size(); aMesh->mColors.resize(pointCount); for(uint32 i = oldSize; i < pointCount; ++ i) aMesh->mColors[i] = Vector4(1.0f, 1.0f, 1.0f, 1.0f); @@ -500,7 +500,7 @@ void Import_LWO(const char * aFileName, Mesh * aMesh) // Post-adjustment: texture coordinate array (if any) if((aMesh->mTexCoords.size() > 0) && (aMesh->mTexCoords.size() < pointCount)) { - uint32 oldSize = aMesh->mTexCoords.size(); + uint32 oldSize = (uint32)aMesh->mTexCoords.size(); aMesh->mTexCoords.resize(pointCount); for(uint32 i = oldSize; i < pointCount; ++ i) aMesh->mTexCoords[i] = Vector2(0.0f, 0.0f); @@ -515,7 +515,7 @@ void Export_LWO(const char * aFileName, Mesh * aMesh, Options &aOptions) { // Check if we can support this mesh (too many vertices?) if(aMesh->mVertices.size() > 0x00ffffff) - throw runtime_error("Too large mesh (not supported by the LWO file format)."); + throw_runtime_error("Too large mesh (not supported by the LWO file format)."); // What should we export? bool exportComment = (aMesh->mComment.size() > 0); @@ -523,7 +523,7 @@ void Export_LWO(const char * aFileName, Mesh * aMesh, Options &aOptions) bool exportColors = aMesh->HasColors() && !aOptions.mNoColors; // Calculate the sizes of the individual chunks - uint32 textSize = aMesh->mComment.size() + 1; + uint32 textSize = (uint32)aMesh->mComment.size() + 1; if(textSize & 1) ++ textSize; uint32 tagsSize = 8; uint32 layrSize = 24; @@ -548,7 +548,7 @@ void Export_LWO(const char * aFileName, Mesh * aMesh, Options &aOptions) // Open the output file ofstream f(aFileName, ios::out | ios::binary); if(f.fail()) - throw runtime_error("Could not open output file."); + throw_runtime_error("Could not open output file."); // File header WriteString(f, "FORM"); diff --git a/3rdparty/openctm/tools/mesh.cpp b/3rdparty/openctm/tools/mesh.cpp index 623b99125..c6a8947fb 100644 --- a/3rdparty/openctm/tools/mesh.cpp +++ b/3rdparty/openctm/tools/mesh.cpp @@ -25,7 +25,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include "mesh.h" @@ -73,8 +73,8 @@ void Mesh::Clear() /// Automatic detection of the optimal normal calculation method Mesh::NormalCalcAlgo Mesh::DetectNormalCalculationMethod() { - unsigned int triCount = mIndices.size() / 3; - unsigned int vertexCount = mVertices.size(); + unsigned int triCount = (unsigned int)(mIndices.size() / 3); + unsigned int vertexCount = (unsigned int)(mVertices.size() ); // Calculate the mean edge length double meanEdgeLen = 0; @@ -169,7 +169,7 @@ void Mesh::CalculateNormals(NormalCalcAlgo aAlgo) mNormals[i] = Vector3(0.0f, 0.0f, 0.0f); // Calculate sum of the flat normals of the neighbouring triangles - unsigned int triCount = mIndices.size() / 3; + unsigned int triCount = (unsigned int)(mIndices.size() / 3); for(unsigned int i = 0; i < triCount; ++ i) { // Calculate the weighted flat normal for this triangle diff --git a/3rdparty/openctm/tools/meshio.cpp b/3rdparty/openctm/tools/meshio.cpp index 52e84412f..270641be4 100644 --- a/3rdparty/openctm/tools/meshio.cpp +++ b/3rdparty/openctm/tools/meshio.cpp @@ -25,7 +25,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include "mesh.h" @@ -68,7 +68,7 @@ void ImportMesh(const char * aFileName, Mesh * aMesh) else if(fileExt == string(".WRL")) Import_WRL(aFileName, aMesh); else - throw runtime_error("Unknown input file extension."); + throw_runtime_error("Unknown input file extension."); } /// Export a mesh to a file. @@ -94,7 +94,7 @@ void ExportMesh(const char * aFileName, Mesh * aMesh, Options &aOptions) else if(fileExt == string(".WRL")) Export_WRL(aFileName, aMesh, aOptions); else - throw runtime_error("Unknown output file extension."); + throw_runtime_error("Unknown output file extension."); } /// Return a list of supported formats. diff --git a/3rdparty/openctm/tools/obj.cpp b/3rdparty/openctm/tools/obj.cpp index 5ed49aa53..75e7012eb 100644 --- a/3rdparty/openctm/tools/obj.cpp +++ b/3rdparty/openctm/tools/obj.cpp @@ -25,7 +25,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include @@ -108,9 +108,9 @@ class OBJFace { if(value > 0) value --; else if(value < 0) - throw runtime_error("Negative vertex references in OBJ files are not supported."); + throw_runtime_error("Negative vertex references in OBJ files are not supported."); else - throw runtime_error("Invalid index (zero) in OBJ file."); + throw_runtime_error("Invalid index (zero) in OBJ file."); } n.Set(j, value); } @@ -150,7 +150,7 @@ void Import_OBJ(const char * aFileName, Mesh * aMesh) // Open the input file ifstream inFile(aFileName, ios::in); if(inFile.fail()) - throw runtime_error("Could not open input file."); + throw_runtime_error("Could not open input file."); // Mesh description - parsed from the OBJ file list vertices; @@ -201,7 +201,7 @@ void Import_OBJ(const char * aFileName, Mesh * aMesh) int triCount = 0; for(list::iterator i = faces.begin(); i != faces.end(); ++ i) { - int nodeCount = (*i).mNodes.size(); + int nodeCount = (int)((*i).mNodes.size()); if(nodeCount >= 3) triCount += (nodeCount - 2); } @@ -269,7 +269,7 @@ void Export_OBJ(const char * aFileName, Mesh * aMesh, Options &aOptions) // Open the output file ofstream f(aFileName, ios::out); if(f.fail()) - throw runtime_error("Could not open output file."); + throw_runtime_error("Could not open output file."); // What should we export? bool exportTexCoords = aMesh->HasTexCoords() && !aOptions.mNoTexCoords; @@ -312,7 +312,7 @@ void Export_OBJ(const char * aFileName, Mesh * aMesh, Options &aOptions) } // Write faces - unsigned int triCount = aMesh->mIndices.size() / 3; + unsigned int triCount = (unsigned int)(aMesh->mIndices.size() / 3); f << "s 1" << endl; // Put all faces in the same smoothing group for(unsigned int i = 0; i < triCount; ++ i) { diff --git a/3rdparty/openctm/tools/off.cpp b/3rdparty/openctm/tools/off.cpp index 6a40934da..ac427a725 100644 --- a/3rdparty/openctm/tools/off.cpp +++ b/3rdparty/openctm/tools/off.cpp @@ -32,7 +32,7 @@ // http://people.sc.fsu.edu/~burkardt/data/off/off.html //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include @@ -99,7 +99,7 @@ void Import_OFF(const char * aFileName, Mesh * aMesh) // Open the input file ifstream f(aFileName, ios::in); if(f.fail()) - throw runtime_error("Could not open input file."); + throw_runtime_error("Could not open input file."); // Some state variables that we need... unsigned int numVertices; @@ -110,16 +110,16 @@ void Import_OFF(const char * aFileName, Mesh * aMesh) // Read header ReadNextLine(f, line, comment); if(line != string("OFF")) - throw runtime_error("Not a valid OFF format file (missing OFF signature)."); + throw_runtime_error("Not a valid OFF format file (missing OFF signature)."); ReadNextLine(f, line, comment); sstr.clear(); sstr.str(line); sstr >> numVertices; sstr >> numFaces; if(numVertices < 1) - throw runtime_error("Not a valid OFF format file (bad vertex count)."); + throw_runtime_error("Not a valid OFF format file (bad vertex count)."); if(numFaces < 1) - throw runtime_error("Not a valid OFF format file (bad face count)."); + throw_runtime_error("Not a valid OFF format file (bad face count)."); // Read vertices aMesh->mVertices.resize(numVertices); @@ -199,7 +199,7 @@ void Export_OFF(const char * aFileName, Mesh * aMesh, Options &aOptions) // Open the output file ofstream f(aFileName, ios::out); if(f.fail()) - throw runtime_error("Could not open output file."); + throw_runtime_error("Could not open output file."); // Mesh information unsigned int numVertices = (unsigned int) aMesh->mVertices.size(); diff --git a/3rdparty/openctm/tools/ply.cpp b/3rdparty/openctm/tools/ply.cpp index 2bacaae4e..fcbe18d2b 100644 --- a/3rdparty/openctm/tools/ply.cpp +++ b/3rdparty/openctm/tools/ply.cpp @@ -26,7 +26,7 @@ //----------------------------------------------------------------------------- #include -#include +#include "common.h" #include #include #include @@ -169,9 +169,9 @@ void Import_PLY(const char * aFileName, Mesh * aMesh) // Open the PLY file p_ply ply = ply_open(aFileName, NULL); if(!ply) - throw runtime_error("Unable to open PLY file."); + throw_runtime_error("Unable to open PLY file."); if(!ply_read_header(ply)) - throw runtime_error("Invalid PLY file."); + throw_runtime_error("Invalid PLY file."); // Get the file comment (if any) bool firstComment = true; @@ -212,7 +212,7 @@ void Import_PLY(const char * aFileName, Mesh * aMesh) // Sanity check if((faceCount < 1) || (vertexCount < 1)) - throw runtime_error("Empty PLY mesh - invalid file format?"); + throw_runtime_error("Empty PLY mesh - invalid file format?"); // Prepare the mesh aMesh->mIndices.resize(faceCount * 3); @@ -223,7 +223,7 @@ void Import_PLY(const char * aFileName, Mesh * aMesh) // Read the PLY file if(!ply_read(ply)) - throw runtime_error("Unable to load PLY file."); + throw_runtime_error("Unable to load PLY file."); // Close the PLY file ply_close(ply); @@ -243,7 +243,7 @@ void Export_PLY(const char * aFileName, Mesh * aMesh, Options &aOptions) // Open the output file ofstream f(aFileName, ios::out | ios::binary); if(f.fail()) - throw runtime_error("Could not open output file."); + throw_runtime_error("Could not open output file."); // Set floating point precision f << setprecision(8); diff --git a/3rdparty/openctm/tools/stl.cpp b/3rdparty/openctm/tools/stl.cpp index 70a6a720a..cf07a6074 100644 --- a/3rdparty/openctm/tools/stl.cpp +++ b/3rdparty/openctm/tools/stl.cpp @@ -25,7 +25,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include @@ -115,14 +115,14 @@ void Import_STL(const char * aFileName, Mesh * aMesh) // Open the input file ifstream f(aFileName, ios::in | ios::binary); if(f.fail()) - throw runtime_error("Could not open input file."); + throw_runtime_error("Could not open input file."); // Get the file size f.seekg(0, ios::end); uint32 fileSize = (uint32) f.tellg(); f.seekg(0, ios::beg); if(fileSize < 84) - throw runtime_error("Invalid format - not a valid STL file."); + throw_runtime_error("Invalid format - not a valid STL file."); // Read header (80 character comment + triangle count) char comment[81]; @@ -131,7 +131,7 @@ void Import_STL(const char * aFileName, Mesh * aMesh) aMesh->mComment = string(comment); uint32 triangleCount = ReadInt32(f); if(fileSize != (84 + triangleCount * 50)) - throw runtime_error("Invalid format - not a valid STL file."); + throw_runtime_error("Invalid format - not a valid STL file."); if(triangleCount > 0) { @@ -192,7 +192,7 @@ void Export_STL(const char * aFileName, Mesh * aMesh, Options &aOptions) // Open the output file ofstream f(aFileName, ios::out | ios::binary); if(f.fail()) - throw runtime_error("Could not open output file."); + throw_runtime_error("Could not open output file."); // Write header (80-character comment + triangle count) char comment[80]; @@ -204,7 +204,7 @@ void Export_STL(const char * aFileName, Mesh * aMesh, Options &aOptions) comment[i] = 0; } f.write(comment, 80); - uint32 triangleCount = aMesh->mIndices.size() / 3; + uint32 triangleCount = (CTMuint)(aMesh->mIndices.size() / 3); WriteInt32(f, triangleCount); // Write the triangle data diff --git a/3rdparty/openctm/tools/wrl.cpp b/3rdparty/openctm/tools/wrl.cpp index e39286f3c..00bdcb54c 100644 --- a/3rdparty/openctm/tools/wrl.cpp +++ b/3rdparty/openctm/tools/wrl.cpp @@ -25,7 +25,7 @@ // distribution. //----------------------------------------------------------------------------- -#include +#include "common.h" #include #include #include @@ -55,14 +55,14 @@ class VRMLReader { char GetNextChar() { if(!mStream) - throw runtime_error("VRML input stream undefined."); + throw_runtime_error("VRML input stream undefined."); if(mBufPos >= mBufActual) { mBufPos = 0; if(!mStream->eof()) { mStream->read(mBuffer, mBufSize); - mBufActual = mStream->gcount(); + mBufActual = (int)(mStream->gcount()); } else mBufActual = 0; @@ -172,7 +172,7 @@ class VRMLReader { // Read the header string header = GetNextLine(); if(header.substr(0, 10) != string("#VRML V2.0")) - throw runtime_error("Not a valid VRML 2.0 file."); + throw_runtime_error("Not a valid VRML 2.0 file."); // Read the rest of the file while(!mEndOfFile) @@ -201,7 +201,7 @@ class VRMLReader { void Import_WRL(const char * aFileName, Mesh * aMesh) { // FIXME: The import functionality has not yet been fully implemented - throw runtime_error("VRML import is not yet supported."); + throw_runtime_error("VRML import is not yet supported."); // Clear the mesh aMesh->Clear(); @@ -209,7 +209,7 @@ void Import_WRL(const char * aFileName, Mesh * aMesh) // Open the input file ifstream f(aFileName, ios::in); if(f.fail()) - throw runtime_error("Could not open input file."); + throw_runtime_error("Could not open input file."); // Initialize the reader object VRMLReader reader; @@ -228,7 +228,7 @@ void Export_WRL(const char * aFileName, Mesh * aMesh, Options &aOptions) // Open the output file ofstream f(aFileName, ios::out); if(f.fail()) - throw runtime_error("Could not open output file."); + throw_runtime_error("Could not open output file."); // Set floating point precision f << setprecision(8); @@ -284,7 +284,7 @@ void Export_WRL(const char * aFileName, Mesh * aMesh, Options &aOptions) // Write faces f << "\t\t\t\tcoordIndex [" << endl; - unsigned int triCount = aMesh->mIndices.size() / 3; + unsigned int triCount = (unsigned int)(aMesh->mIndices.size() / 3); for(unsigned int i = 0; i < triCount; ++ i) { f << "\t\t\t\t\t" << diff --git a/README.md b/README.md index 7197d81a1..7047658b3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ bgfx ==== +What is it? +----------- + Cross-platform rendering library. Supported rendering backends: @@ -65,7 +68,7 @@ directory link to directory without spaces in the path. ### Building for Native Client (Pepper 22) on Windows -Download Native Client SDK from +Download Native Client SDK from: [https://developers.google.com/native-client/sdk/download](https://developers.google.com/native-client/sdk/download) setx NACL \toolchain\win_x86_newlib @@ -84,7 +87,7 @@ Other platforms: make -R -Configuration is -<32/64>. For example: +Configuration is `-<32/64>`. For example: linux-release32, nacl-debug64, android-release32, etc. @@ -112,6 +115,69 @@ Geometry instancing. ### 06-bump Loading textures. +Internals +--------- + +bgfx is using sort-based draw call bucketing. This means that submition order +doesn't necessarily matches the rendering order. On the high level this allows +submitting draw calls for all passes at one place, but on the low-level they +will be sorted and ordered correctly. This sometimes creates undesired results +usually for GUI rendering, where draw order should usually match submit order. +bgfx provides way to enable sequential rendering for these cases (see +`bgfx::setViewSeq`). + +Internally All low-level rendering draw calls are issued inside single function +`Context::rendererSubmit`. This function exist inside each renderer backend +implementation. + +More detailed description of sort-based draw call bucketing can be found at: +[Order your graphics draw calls around!](http://realtimecollisiondetection.net/blog/?p=86) + +Customization +------------- + +By default each platform has sane default values. For example on Windows default +renderer is DirectX9, and on Linux it is OpenGL 2.1. On Windows platform all +rendering backends are available. For OpenGL ES on desktop you can find more +information at: +[OpenGL ES 2.0 and EGL on desktop](http://www.g-truc.net/post-0457.html) + +All configuration settings are located inside [src/config.h](src/config.h). + +Every `BGFX_CONFIG_*` setting can be changed by passing defines thru compiler +switches. For example setting preprocessor define `BGFX_CONFIG_RENDERER_OPENGL=1` +on Windows will change backend renderer to OpenGL 2.1. on Windows. Since +rendering APIs are platform specific, this obviously won't work nor make sense +in all cases. Certain platforms have only single choice, for example the Native +Client works only with OpenGL ES 2.0 renderer, using anything other than that +will result in build errors. + +Tools +----- + +### Shader Compiler (shaderc) + +bgfx cross-platform shader language is based on GLSL syntax. It's uses ANSI C +preprocessor to transform GLSL like language syntax into HLSL. This technique +has certain drawbacks, but overall it's simple and allows quick authoring of +cross-platform shaders. + +### Texture Compiler (texturec) + +### Geometry Compiler (geometryc) + +Todo +---- + + - Multiple render targets. + - BlendFuncSeparate and BlendEquationSeparate. + - Copy from texture to texture. + - Occlusion queries. + - OSX and iOS platforms. + - DX11: MSAA. + - GL: MSAA. + - GL: ARB_vertex_array_object + OES_vertex_array_object. + Notice ------ @@ -127,8 +193,45 @@ http://www.stuckingeometry.com Project page https://github.com/bkaradzic/bgfx -License -------- +3rd Party Libraries +------------------- + +All required 3rd party libraries are included in bgfx repository in [3rdparty/](3rdparty/) +directory. + +### edtaa3 (MIT) + +Contour Rendering by Distance Fields + +https://github.com/OpenGLInsights/OpenGLInsightsCode/tree/master/Chapter%2012%202D%20Shape%20Rendering%20by%20Distance%20Fields + +### fcpp (BSD) + +Frexx C preprocessor + +https://github.com/bagder/fcpp + +### glsl-optimizer (MIT) + +GLSL optimizer based on Mesa's GLSL compiler. Used in Unity for mobile shader +optimization. + +https://github.com/aras-p/glsl-optimizer + +### OpenCTM (Zlib) + +OpenCTM — the Open Compressed Triangle Mesh file format — is a +file format, a software library and a tool set for compression of 3D triangle +meshes. + +http://openctm.sourceforge.net/ + +### stb_image (Public Domain) + +http://nothings.org/stb_image.c + +License (BSD 2-clause) +---------------------- Copyright 2010-2012 Branimir Karadzic. All rights reserved. diff --git a/examples/01-cubes/makefile b/examples/01-cubes/makefile index 3d8f5374e..3bb2f87f9 100644 --- a/examples/01-cubes/makefile +++ b/examples/01-cubes/makefile @@ -5,6 +5,7 @@ BGFX_DIR=../.. RUNTIME_DIR=$(BGFX_DIR)/examples/runtime +BUILD_DIR=../../.build include $(BGFX_DIR)/premake/shader.mk diff --git a/examples/02-metaballs/makefile b/examples/02-metaballs/makefile index 3d8f5374e..3bb2f87f9 100644 --- a/examples/02-metaballs/makefile +++ b/examples/02-metaballs/makefile @@ -5,6 +5,7 @@ BGFX_DIR=../.. RUNTIME_DIR=$(BGFX_DIR)/examples/runtime +BUILD_DIR=../../.build include $(BGFX_DIR)/premake/shader.mk diff --git a/examples/03-raymarch/makefile b/examples/03-raymarch/makefile index 3d8f5374e..3bb2f87f9 100644 --- a/examples/03-raymarch/makefile +++ b/examples/03-raymarch/makefile @@ -5,6 +5,7 @@ BGFX_DIR=../.. RUNTIME_DIR=$(BGFX_DIR)/examples/runtime +BUILD_DIR=../../.build include $(BGFX_DIR)/premake/shader.mk diff --git a/examples/04-mesh/makefile b/examples/04-mesh/makefile index 3d8f5374e..3bb2f87f9 100644 --- a/examples/04-mesh/makefile +++ b/examples/04-mesh/makefile @@ -5,6 +5,7 @@ BGFX_DIR=../.. RUNTIME_DIR=$(BGFX_DIR)/examples/runtime +BUILD_DIR=../../.build include $(BGFX_DIR)/premake/shader.mk diff --git a/examples/05-instancing/makefile b/examples/05-instancing/makefile index 3d8f5374e..3bb2f87f9 100644 --- a/examples/05-instancing/makefile +++ b/examples/05-instancing/makefile @@ -5,6 +5,7 @@ BGFX_DIR=../.. RUNTIME_DIR=$(BGFX_DIR)/examples/runtime +BUILD_DIR=../../.build include $(BGFX_DIR)/premake/shader.mk diff --git a/examples/06-bump/bump.cpp b/examples/06-bump/bump.cpp index c7ee52e2c..4464f1e2f 100644 --- a/examples/06-bump/bump.cpp +++ b/examples/06-bump/bump.cpp @@ -429,7 +429,7 @@ int _main_(int _argc, char** _argv) } } - uint16_t numInstances = (data - idb->data)/instanceStride; + uint16_t numInstances = (uint16_t)( (data - idb->data)/instanceStride); // Set vertex and fragment shaders. bgfx::setProgram(program); diff --git a/examples/06-bump/makefile b/examples/06-bump/makefile index 3d8f5374e..3bb2f87f9 100644 --- a/examples/06-bump/makefile +++ b/examples/06-bump/makefile @@ -5,6 +5,7 @@ BGFX_DIR=../.. RUNTIME_DIR=$(BGFX_DIR)/examples/runtime +BUILD_DIR=../../.build include $(BGFX_DIR)/premake/shader.mk diff --git a/examples/common/dbg.cpp b/examples/common/dbg.cpp index dbd7eba45..3d8be1ee1 100644 --- a/examples/common/dbg.cpp +++ b/examples/common/dbg.cpp @@ -11,6 +11,7 @@ #include // isprint #include "dbg.h" +#include #if BX_COMPILER_MSVC # define snprintf _snprintf @@ -36,9 +37,15 @@ void dbgOutput(const char* _out) void dbgPrintfVargs(const char* _format, va_list _argList) { char temp[8192]; - vsnprintf(temp, sizeof(temp), _format, _argList); - temp[sizeof(temp)-1] = '\0'; - dbgOutput(temp); + char* out = temp; + int32_t len = bx::vsnprintf(out, sizeof(temp), _format, _argList); + if (sizeof(temp) < len) + { + out = (char*)alloca(len+1); + len = bx::vsnprintf(out, len, _format, _argList); + } + out[len] = '\0'; + dbgOutput(out); } void dbgPrintf(const char* _format, ...) diff --git a/examples/runtime/shaders/dx11/fs_bump.bin b/examples/runtime/shaders/dx11/fs_bump.bin index 7ffd8b16178a15b74022a5022fe8d2e9e2f81070..453e9aed7ab9b42c83f229e089074b0360bbaf73 100644 GIT binary patch delta 421 zcmZ3XxIvM_E!cx$GLN*_1a|?whAGQ=X2mZmIU68sjRA{;%me|DI4cl?%nuHW5AYB64Ds~$ zlVI@k5At>NVF+>bb9eO%VF+=JaQ62Pa+$2evQQLcXp#T}vylLhfU=7w-(aa`WZfLX zI-LsCup95{V!j%lM#f=GK2FwxI%Fvhr7T>cHSV5cSbwkMoD!{Y>3*qG2Vo^o{<3pn1K|C&CbriumngmL4+AV z;vhCqm|-nc3`Bv%K^UZd3rGM8Kw>OF3^NB=oE6An1}X>+ix2P*_6+g#_mf}5- diff --git a/examples/runtime/shaders/dx11/fs_cubes.bin b/examples/runtime/shaders/dx11/fs_cubes.bin index 96fcba2669f25e91350d7b12616dc8aa08c7f22e..edb799f9263fc5676f7f727516c8ed0cb8da1f95 100644 GIT binary patch delta 16 XcmaFH{EnH!E!cx$N%wot4bK<>Hd+S4 delta 8 PcmaFI{ET@c$1_F%5vc=v diff --git a/examples/runtime/shaders/dx11/fs_instancing.bin b/examples/runtime/shaders/dx11/fs_instancing.bin index 96fcba2669f25e91350d7b12616dc8aa08c7f22e..edb799f9263fc5676f7f727516c8ed0cb8da1f95 100644 GIT binary patch delta 16 XcmaFH{EnH!E!cx$N%wot4bK<>Hd+S4 delta 8 PcmaFI{ET@c$1_F%5vc=v diff --git a/examples/runtime/shaders/dx11/fs_mesh.bin b/examples/runtime/shaders/dx11/fs_mesh.bin index 36d0e7e52a86f181cd9fe2987d3cdbb5eebf5ea2..f4a8c6257e731d0432030a9a85d9c560f037379f 100644 GIT binary patch delta 257 zcmcaD_*js`E!cx$>Ri{~6VwDWpDKK;I2Vs~vNDT;p#8`kBBpw_VAK)MC8RF^h$KdSm;~&J} z=O5(j=)(}=8sY5kALPQYdh$)Cm7E~;ZbAYKER(yL^<_ak0iXd*AQCDAG99FXY4UYu leNhn4h=G9jnW@l$$=mFA95Mc(8 zIEW1rp9&QNQ6O;;28quB2|xizj0K4Kf#Sho@d5t9o*|z8eheY55zhYpK`sn_{z1Nu zJ`B$OKK?-rt0zBXS~>X|v%ut8%o?&Fdjx<+Hi1YWa1#;$+X1F0-)Ghr1(|Ndz`zMp cp(OxRv00hrJ0m0GW@)x=Mn;y+%h_!h0c!arzyJUM diff --git a/examples/runtime/shaders/dx11/fs_metaballs.bin b/examples/runtime/shaders/dx11/fs_metaballs.bin index 3b8209216b4e809a27590a97e35353316afb8bf4..cbd93d7ad0003b5cd9e944f1410bf45e58c92d0c 100644 GIT binary patch delta 155 zcmeyx*2K=?7VN>mtn<}=f~0^^T1rONfE2c>4P>IQ#qf2Qh@WMmYQX2f0iZX7u9yBp?7bB1wRO kxoC10qc$f@s!N8Eh>=NPRtoxmR^0o<&Roc(?LgCed_I`NE!cyBvH8=(4aYSBIV=Yq delta 8 PcmX>fd^~s~$8k*n6QKj< diff --git a/examples/runtime/shaders/dx11/vs_bump.bin b/examples/runtime/shaders/dx11/vs_bump.bin index 0e8bc9a0a538d9bf39fe0b01a7c4641e76fe98c8..942b71635574e3e89a1d8cfad5bcb50630a90088 100644 GIT binary patch delta 593 zcmY*VJxc>Y5S`szk~;}x4HrL16BP>un-m%mgtNF9)Jycjwc3c560FiF{sLkDK(Mhe zjRcESmfHCf?8HJOjUZOeyWC0~n48&oZ{Ez@yE}C4DBLEUD@|Rmsh?TuKHMxtosGd@ z`s>ZVuMLHG(N%ey4;lx1-Yzv8VZBvv1o~5YMM^BiQLtxiqC4G`Zoo<3pd3MnJvXY$ z1VhbYM?}(Q9(>Pl+UAm0R1SI3tRRiiGZ2 zB_Z^)wZPvG>v6I|lm`P7{Q@)lN0}Yrtnyq4i+(qIA{NaP`}$H5B5Gz2U-3TLa%%fL z(S{y2iqfOW{#BV@qpNt{guzW6SSHyL>gfIBX_c9|NQ!0+oCacI@j&FJ*$CtJG0UFk tOCSmyHIA1aM;P$J7@nN?4`10DBgB7dOkk4_3tL|6oW+*e)B4*v`vtXZMZW+5 delta 624 zcmZWmJxc>Y5S{xl1s1n%zN{(gX~xK(p~U3#N5kRY4PXo=IrG7xlwtD2Zr$} zR?M!rx2A+^&2|iu$6^CN?GoLxH6={I;REj}3(!(hM>$F=yK8Y=D^nELwu3E7f@r-GCF0%cHQIT9Sfs@~_z;F)WFKM&+#9eG*K3o{ z9#L~b+HhRv6p1_?OZglVA9leY@om4h=7}8WV(`$EJl1lN53K1Zt@Av;4>kvFU>mb_fal0uv}6bC^U43#)G$D~nR90M5rH)qr67t(u%=(=T(RorQA z*c8{^WC#BO6=hEY$nw!+VKq7q<|>#9QzQT5pbKyihmKx#$g4wanYU0+g5(Gj&oE$L HWe$GU|=qqe22-Jk#VvFvo?@)VO9r{ OIn36K43k$dw*Uahq#pwS delta 117 zcmdnOv4&$JhrYlsx%jEeF8?}kJ7(SI6$}PC8{OY9YO%93FgP+G05g!u2*mvS3=9GO z!JZ+W{(cP3{yzRelVh2xc#8xCz-r?e7??jze!^tU$S_%fSsO_DFslQ}5@u^g#>pF) FTL3?p8|eT5 diff --git a/examples/runtime/shaders/dx11/vs_instancing.bin b/examples/runtime/shaders/dx11/vs_instancing.bin index a4b7c4252c9216bfa5c7c63c28b74177efb5797d..e61505d8c9c96e8a7def0489cbaefc792ce424a5 100644 GIT binary patch delta 128 zcmey&^_z<$EZBo#N%wot30eZP7XMJy`}TM3gdbc9Wwz=a8?D|jO7ZhEFl=K$0A?VQ z5s2B@Cp$1z@j3hZ_y;ir_y>E2c>4QIKEc$)`$<3mtUR89fw^dMICD88ObwRi{~6Z`~n?^aoyuVE=RjnQ4dw&RQM#yABgM*GS2Oyc~0{z1Nu zJ`4f=!JZ+W{(h5}GU?VcKmjw5W&~n>Af5yj15qGxCLm_#U|^UDq(N#x03;5=FmaF? z5CDm>05M2BI4mA!7lX6EkADyY)CD1~5zhYpK`sodCkHb7GJcvopIMo)X!2oZdq&2| z%q)i)873cRsRy#%S>u7^a@O^lAamWA1i)@FV_;xyQV;;Uh0y^h!O&oD!N9;#!~m3^ z{F}|%6yzEs1_rJopehjCtw{k$GBEG~@iHy}Fx!n8Lc?@2OwMMLt_PU`0x%ssKsFmt z4CHT+{U87~8BHC`WMp+fr5qp^fWiZ&7iKOfob7Pbn8KKAOKg#!NAZ1tr5J5YQoR18Fc)Ppccd=5we3P55k zK+F%s!C~=mD??l(oc;ZST%dL{IQ#qf2QjRk9Lemc|o#Z hV}LrCC!c4N7cpaCU~K~OKwf5a01^xh_LJ+_8v$m6K5GB~ diff --git a/examples/runtime/shaders/dx11/vs_metaballs.bin b/examples/runtime/shaders/dx11/vs_metaballs.bin index 31f7a3177424753e2d9df364fe1d2f5afe4d67f0..aa218c8fb5324e3fe43e72a1fea1d3a22b728c43 100644 GIT binary patch delta 273 zcmZqT>f+)E3-(}O*7<5b!B)WF*2A4y%oV%h+3&J*Urbim==+9|m7kx1A#Ac8lelgy z0|GDunM^>;&d$K#?C;|r#Ng*23e5a1u|8RF^hH@S&P-wmc7q?!?kfkrVTLD@ix z0d5Kh14D3FJWMat#1PjAXMg`7m&xCm)EGZamSYyzED{g^Tbs_n!175!0AvQ(;8dVl zAU?Yx0JIT$GC$09$uk);s; D2+uM@ delta 279 zcmeC;YT}y6VJlGHapK^^15fqeZ#55V-}v|c#?Uv6p6u)l43P{7zzk$E0x?KD0U^u) z5@!Npetrgq0RLdm5Kn(U20#BGUq>GXXMZ36pvhfK`febdAOJUogMlFxA_Nx)n*!to zhsDDU3UQ5a_V*8Rfg1InNlmgyKme>I9%vef4Kf*<0U`o494L~;EYHX= uxs6#HNN!?Q2a>m#wI@rm1TZpA&SH@lG-F_3{RGqjvf51!NKbBKX#oJ-S~21P diff --git a/examples/runtime/shaders/dx11/vs_raymarching.bin b/examples/runtime/shaders/dx11/vs_raymarching.bin index 7b7d5ab420901d8a37ba43e3077c05dc59df9712..0e3c8e2a5acb3a43f51c8facb494df5be786f07b 100644 GIT binary patch delta 148 zcmbQixqy=+EZBpAvH8=(3Hk!Ye(uj?4AyN6V_CrTS0n%8M*BC6PW=1~3}Flizzk$E z0x>%~14BGQm;oft1jNihhO@tqe-J}}f3RnWr@!CiT&6|5p9BQJih){~izdr32QxBG WE@0LMl5?2Vf#eZpYet4iEHeN#UL70& delta 120 zcmZ3$IfHW|hrU2bTrcmzVA*Kvf1H19u5L))=>CRLik+Q-A(8gz?o$lv$xEU^zK1Hkn4rkBwBH|AUs=} zPyoVkCVY1?#V*rsf;h{9o2h;402ez!A4mtTiM5iWiC5{$DDo)!DC*YjtQ%aDx}V>4 QF50M0i#_t`2YX_ delta 258 zcmaKmu?@m75Jms_>^L3D1QaPL*nt(Os1OxnV8jBJPJ%K6P%#Bcg%nXRfG41#LKGVX10^s8uFbo8mbfwx%+Nox+^t2&JYr365ii8wufDNotqo;Dk z7q1jscqIqD)JF?gF1}Yks87d{H@cHD6IRL)W`U*Ut9CuOYjT%P>2kSC4)&zkwpy3$ T=MUMt&!225@9Ie`cmMhV?%z1c diff --git a/examples/runtime/shaders/dx9/fs_cubes.bin b/examples/runtime/shaders/dx9/fs_cubes.bin index fb14d875cb3699252b5ed2e7c6364394253918a3..d4f476822dad1ebffe91a0e61b8f34dab16c828d 100644 GIT binary patch delta 15 WcmZo<>}2F{3-(}G(*53ZLL&epvjuJd delta 7 OcmeBVY-F6s(FgztnF1#O diff --git a/examples/runtime/shaders/dx9/fs_instancing.bin b/examples/runtime/shaders/dx9/fs_instancing.bin index fb14d875cb3699252b5ed2e7c6364394253918a3..d4f476822dad1ebffe91a0e61b8f34dab16c828d 100644 GIT binary patch delta 15 WcmZo<>}2F{3-(}G(*53ZLL&epvjuJd delta 7 OcmeBVY-F6s(FgztnF1#O diff --git a/examples/runtime/shaders/dx9/fs_mesh.bin b/examples/runtime/shaders/dx9/fs_mesh.bin index 2600a8d0c59b13495c95f16dea9015b2df060a85..f15a9d3aec774b054ed6f25e2fd722e4b89c7af0 100644 GIT binary patch delta 135 zcmeyy`Hz#sE!cx$>Ri{~8$21+xfmE47#P?m$TKi7F$39*P&O+AV*?YM%`~}yQIe5q za~I=sMoR{UClfdr7=WrdfXbgt0AY5Zb`YO|;eP`wP!4Dem<^I+VPF6vpxVh<%*Pp- JCmXRG0RVLU8}$GH delta 125 zcmeyz`HgcUhbN;WD+6N#0|Wa6c?Je1RtBa9Mkt$^fuVs3%H{&HnSpFZpc)1S7NGd5 z1uQ@YP+tSX=1Gjp83maco=o6iU;ygk07^fZz%<#5S(+Ebf+z%vPA+0T&d4~~isc9Z DA1W4u diff --git a/examples/runtime/shaders/dx9/fs_metaballs.bin b/examples/runtime/shaders/dx9/fs_metaballs.bin index 880484781c364263c3307f2ee71adf7c8d0437e4..f33293a39b2217c612451bce1e038d70711b4915 100644 GIT binary patch delta 99 zcmcb~{E(T$E!cyBS?8<$ga$<}28IR(2L1{13=B-H42%to4D1s)7#Nrt!0aaz7$+{2 nW@MbWS6h{VfnfqaP!$sc6HrGel+6NUuY$5U8W<+?GM)hd~09%tC~DT7%*GIc-%4O;ItaY)1B#E%xUj#xn-veLZW-4d^ delta 196 zcmX|)yAi@b35mN#+5Kspt(1Pf|9)|=3ganjA3l}(|iQ_c(knNM+=b7($ z%-=2Gup17bHrC6jLtN-f96Ho>Wot%TdDA%kJ$Q!|X@2OP=^-DH>8h{2B1M@U=39c) idR?ZYz0Z-3PX<%8r5D$tQ?XS?YpjM2j-|#!t-ue911Q7* diff --git a/examples/runtime/shaders/dx9/vs_cubes.bin b/examples/runtime/shaders/dx9/vs_cubes.bin index 01d66e86cb0ff7c1699de80e5283a23ba724dfc2..8678ce349b8fc6df7ea301291ddc873aa9544eaa 100644 GIT binary patch delta 84 zcmdnaw4aG1EZBo#N%wot37dGi7#JED82Bg1GcYhQOx&-n%E%BpfrWtqi1>jLPZlsT bFiZf_4KOh#kl18?MtM%4=!F0O85kG;^U<|Nnmm1_l63lo9;^ delta 56 zcmcb`e2IA?$4XuX28IR(2L1{13=B+M6Za)EGE7!toG;19@MHoj0|PT71OEdCh9?bd KK>q*#K*a!wZVt8p diff --git a/examples/runtime/shaders/dx9/vs_mesh.bin b/examples/runtime/shaders/dx9/vs_mesh.bin index 22ae1514464344638cc4bb5efae779afb7d8a1c0..aa9460b92a6b52989ac3a33d048798060b911d2a 100644 GIT binary patch delta 162 zcmX@devO?YEZBo#>Ri{~8&VnlnHd-w7#R2`$TKi7F#y?&NNk|^1CTfuL>$Zpsb^wf z2eVlj7#o=3Y^DYl2KLEY7*!b=C*NY6&d4yih{+wu-o+#j5@E7uWSK0*Y|O|s*^fD0 c5~PoT;R(<_1|~)Zjt5)}{}=xM&%nR{0Q@N+_5c6? delta 180 zcmXYqF$w}P6hvo!B3X8et*u1C6YK#jEv@th;vKB^2to?m*xK29hApiZ@g8vkfnPk{ z4D&x>3a{qO1Ar0eZ!5r@n3b!ai(i29p|Xuux%6G-R_xKoH@8Im@=nI9?blv8lyx|! m4$tHPUC_o)4oO|x(c;Dpbn)aa%kl|Ism~tG+#)}6*2W+1ry|n; diff --git a/examples/runtime/shaders/dx9/vs_metaballs.bin b/examples/runtime/shaders/dx9/vs_metaballs.bin index 8c80df245e869c4ea8af3e66f18d2ef209a20555..0f9e0f12737b312ee0a85be4dde8109ad1023104 100644 GIT binary patch delta 138 zcmdnUypx$DEZBpAS?8<$ggcB}6Yq-0GB7YSFfs5?kY`|E0l+DV( z2vo!VfR%xP87L1Ff3kpyA#?%@0|OB81NDIT3=@EK15AtwBsMva(VmfM@%CXm?VNJe`_kST0H9wWmlunIjLPZlsT lFiZf_4KOh#kl18(MtM=7=melF6B7gT1EA=H|Nj{n7yy8k7dHR^ delta 88 zcmaFNbem}+$0l9|28IR(2L1{13=B+M6OTKqGBAWrU}0bYB7UI6lLbHp6M%FBOpFO6 dHd&uhUX+pH$pl8AHYNt<2SCvY|NjHk0svXJ6aD}I diff --git a/examples/runtime/shaders/gles/fs_bump.bin b/examples/runtime/shaders/gles/fs_bump.bin index 16a53b6a8737f1cd072f51906e3d206c3e0da74e..ebd2f0632ac90432822fec3cadd2d4ca9d28ebdd 100644 GIT binary patch delta 35 rcmbQMuvCG=E!cx$GLN*_go7N$3T5%-1^LAj|0+#9XunyD@iQL)&8Q5f delta 21 dcmZ3gFjrwB$H9r8?I&K5pLmjcvk~KGJ^*UZ32*=a diff --git a/examples/runtime/shaders/gles/fs_cubes.bin b/examples/runtime/shaders/gles/fs_cubes.bin index d381232543295e3d1d2a278dbd5deaa926d2b867..55250fc553c08deb3f287627ab1aed2b0f3e2ea7 100644 GIT binary patch delta 14 VcmbRi{~6T&98$WKgG_z3T3IuCJJTo$@w|?MFtxaSs4L9wGMUw delta 26 hcmaFI^o(gDhXc2XLRoxreolUof%QZi$&EQoi~xG22zCGf diff --git a/examples/runtime/shaders/gles/fs_raymarching.bin b/examples/runtime/shaders/gles/fs_raymarching.bin index d7c70816dab2fa70a747b406b335f5ba14f2da73..6add4db1f3a9c92f87a1b5022dcf4f34e703af2c 100644 GIT binary patch delta 16 XcmccR^~j6EE!cyBvH8=(4NV?mY5^OwpaG=> DeiRWD delta 60 zcmX@hbChQyN8ZE*b`u*EIE)p_;>!#2iznV$Ie7sihh$<&Nl|7}X-TR=S!%MeLSj5n PF0&*vKX3Cg#^o#k&Y>4| diff --git a/examples/runtime/shaders/gles/vs_cubes.bin b/examples/runtime/shaders/gles/vs_cubes.bin index 8852fe2555825607a55673ca9d8b00adf301e624..c5309d25f2a0db05af5b219af673043da1c388bb 100644 GIT binary patch delta 45 zcmdnNbbyH?EZBo#N%wot3FQ+f@QEjuloVwqm6oI`l%*z{C?v)w=jY@X8BClr2LOnJ B5r_Z) delta 16 YcmX@Ww1a6PNBP8AJQItgCoY=>05${$vj6}9 diff --git a/examples/runtime/shaders/gles/vs_instancing.bin b/examples/runtime/shaders/gles/vs_instancing.bin index 694886a13b312fc059038cbbfa55931fa2a9d0f1..cfd14213e4908e21a6e2c6a066a9c7692f3091f8 100644 GIT binary patch delta 36 scmZ3-vWm*!=0?gtZfo@l9MHIq}MN0Bw#6eEk delta 39 vcmew-|4p7-xh%D)I5R&_!O&!)aR0#g`Z47jNcZ{Kf|WF&+-l diff --git a/examples/runtime/shaders/glsl/fs_cubes.bin b/examples/runtime/shaders/glsl/fs_cubes.bin index 59695bd22859a918a6c77d24b81db8c2088c15c6..5453e14515f617b5ce8b38530511592bf3a1b9ef 100644 GIT binary patch delta 25 gcmWHJ7Iq8vU|7=q-cz|OwWv5VKTpBXXd<@<0CArPng9R* delta 17 YcmazJ=2k9CEh^5;&r>ionJDZ505Hl0Q~&?~ diff --git a/examples/runtime/shaders/glsl/fs_instancing.bin b/examples/runtime/shaders/glsl/fs_instancing.bin index 59695bd22859a918a6c77d24b81db8c2088c15c6..5453e14515f617b5ce8b38530511592bf3a1b9ef 100644 GIT binary patch delta 25 gcmWHJ7Iq8vU|7=q-cz|OwWv5VKTpBXXd<@<0CArPng9R* delta 17 YcmazJ=2k9CEh^5;&r>ionJDZ505Hl0Q~&?~ diff --git a/examples/runtime/shaders/glsl/fs_mesh.bin b/examples/runtime/shaders/glsl/fs_mesh.bin index eaf53d6b3b8975babb7dc53bd9c23c7c86588fb0..3d29b1cc21385b30e1ddd1726babc8b86fe5787e 100644 GIT binary patch delta 48 zcmdnVd5}}sE!cx$>Ri{~%4MlV#hLke3Wi1#xm6~{%1^XW&PFFzMgU&? B4*UQB diff --git a/examples/runtime/shaders/glsl/fs_raymarching.bin b/examples/runtime/shaders/glsl/fs_raymarching.bin index 3484bdc1470963f14b7a7c565ad6a1e035f2bcf7..907a2b86026b9feb0f7b216c81c9b1520d336739 100644 GIT binary patch delta 28 jcmdn&wcAVBE!cyBvH8`R!1w*5a+#0F?oAU|- delta 20 bcmdn(wb_eXxh%D)I5R&_!O&!*u!brCP&Nk5 diff --git a/examples/runtime/shaders/glsl/vs_bump.bin b/examples/runtime/shaders/glsl/vs_bump.bin index 2de04a441b5bd508e1fd5318ad092803b5d61a26..72324e94a535111b102f89145dcbcb485380b17b 100644 GIT binary patch delta 78 zcmbQovy4YLEZBo#GLN*Fa#?Coab|v=f}znwZW|6`g|hhag8br%%}Nv9?Ix~YJ~^L} iOFXfpq$o3~v?NubEH&9!Au&ELzbH2`XLC8@auxvIXd0;i delta 50 zcmV-20L}lV44w=NBX(tSb7^mGATczN6FiZ5K9N}`R!1w*5W+^!Qd`6fC`PAs1V0OWBDz5oCK delta 29 kcmbQqG?9s0xh%D)I5R&_!O&!)uq(5PLgGXxm5KGU0D~L}DgXcg diff --git a/examples/runtime/shaders/glsl/vs_instancing.bin b/examples/runtime/shaders/glsl/vs_instancing.bin index a425235d6d43bce90cd74ec254bf5a7da7d2a23c..9bdd64066c15cfae3aa965d2dbb218e748ea69e1 100644 GIT binary patch delta 58 zcmZo?>1PoR3-(}G(*533xh%D)I5R&_!O&J@4L delta 36 rcmeBYX=mY9E=w&c&dkqKFf^Gcyo1w3Au&EVKPSIv;%>Q(pJW*U*GCMS diff --git a/examples/runtime/shaders/glsl/vs_mesh.bin b/examples/runtime/shaders/glsl/vs_mesh.bin index d1772ea5c7914760981f8239c53a67205256a1be..2fa0af63d133f33da8d426f812a12247509095a6 100644 GIT binary patch delta 57 zcmV-90LK5B3ZV)UR#Qj-m7PWVBX(tSb7^mGATctL3tW+v9+7h*3N#>gUt@1 diff --git a/examples/runtime/shaders/glsl/vs_metaballs.bin b/examples/runtime/shaders/glsl/vs_metaballs.bin index 4c0cff6f7cee16f7a95764098c03d920afe5daca..6e1bb69332b3a08620766c1c094f97c5f7a61864 100644 GIT binary patch delta 62 zcmdnTe2iH*EZBpAS?8<0a#?Coab|v=f}znwZYNG-g|hg({G!~%iS|+xI|Vrk@{2P| RfYKA&H73^bY~0Jp2mpOD6(#@x delta 62 zcmX@cypNe%xh%D)I5R&_!O&!)u+zjG9=@`~qRPy?bcM3iWMhT0iHnscRtQd9B06ya R3r9hIab^in@y5f`R!1w*5W+|?83^NA;xloVwqm6oI`l%*z{C?v)w N=jY@X8BAQg698!f7196z delta 28 kcmaFE^n{69xh%D)I5R&_!O&!)aP`EMJQEwGCvM#i0GFi;9RL6T diff --git a/include/bgfx.h b/include/bgfx.h index d91ffce5f..9d15cc7aa 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -230,6 +230,7 @@ namespace bgfx enum Enum { MinimumRequiredSpecs = 1, + InvalidShader, D3D9_UnableToCreateInterface, D3D9_UnableToCreateDevice, D3D9_UnableToCreateRenderTarget, @@ -304,7 +305,10 @@ namespace bgfx ARGB8, ABGR16, R5G6B5, - + RGBA4, + RGB5A1, + RGB10A2, + Count }; }; @@ -453,7 +457,7 @@ namespace bgfx /// /// BGFX_DEBUG_IFH - Infinitely fast hardware. When this flag is set /// all rendering calls will be skipped. It's useful when profiling - /// to quickly assess bottleneck between CPU and GPU. + /// to quickly assess bottleneck between CPU and GPU. /// /// BGFX_DEBUG_STATS - Display internal statistics. /// @@ -545,6 +549,11 @@ namespace bgfx void destroyFragmentShader(FragmentShaderHandle _handle); /// Create program with vertex and fragment shaders. + /// + /// @param _vsh vertex shader. + /// @param _fsh fragment shader. + /// @returns Program handle if vertex shader output and fragment shader + /// input are matching, otherwise returns invalid program handle. ProgramHandle createProgram(VertexShaderHandle _vsh, FragmentShaderHandle _fsh); /// Destroy program. diff --git a/premake/premake4.lua b/premake/premake4.lua index da87919dc..d3695679c 100644 --- a/premake/premake4.lua +++ b/premake/premake4.lua @@ -264,9 +264,10 @@ function copyLib() end dofile "bgfx.lua" -dofile "ddsdump.lua" dofile "makedisttex.lua" dofile "shaderc.lua" +dofile "texturec.lua" +dofile "geometryc.lua" dofile "openctm.lua" dofile "example-00-helloworld.lua" dofile "example-01-cubes.lua" diff --git a/premake/shader.mk b/premake/shader.mk index 31c6e7db5..b7988dc58 100644 --- a/premake/shader.mk +++ b/premake/shader.mk @@ -35,8 +35,8 @@ FS_FLAGS=--platform android SHADER_PATH=shaders/gles else ifeq ($(TARGET), 4) -VS_FLAGS=--platform linux -p 140 -FS_FLAGS=--platform linux -p 140 +VS_FLAGS=--platform linux -p 120 +FS_FLAGS=--platform linux -p 120 SHADER_PATH=shaders/glsl endif endif @@ -45,7 +45,7 @@ endif endif BUILD_OUTPUT_DIR=$(addprefix ./, $(RUNTIME_DIR)/$(SHADER_PATH)) -BUILD_INTERMEDIATE_DIR=$(addprefix $(BGFX_DIR)/.build/, $(SHADER_PATH)) +BUILD_INTERMEDIATE_DIR=$(addprefix $(BUILD_DIR)/, $(SHADER_PATH)) VS_SOURCES=$(wildcard vs_*.sc) VS_DEPS=$(addprefix $(BUILD_INTERMEDIATE_DIR)/,$(addsuffix .bin.d, $(basename $(VS_SOURCES)))) diff --git a/premake/shaderc.lua b/premake/shaderc.lua index 98b6242be..3f7453db6 100644 --- a/premake/shaderc.lua +++ b/premake/shaderc.lua @@ -46,7 +46,8 @@ project "shaderc" } files { - BGFX_DIR .. "tools/shaderc.cpp", + BGFX_DIR .. "tools/shaderc/**.cpp", + BGFX_DIR .. "tools/shaderc/**.h", FCPP_DIR .. "**.h", FCPP_DIR .. "cpp1.c", FCPP_DIR .. "cpp2.c", diff --git a/premake/ddsdump.lua b/premake/texturec.lua similarity index 66% rename from premake/ddsdump.lua rename to premake/texturec.lua index 9c9917b4d..d655e6f70 100644 --- a/premake/ddsdump.lua +++ b/premake/texturec.lua @@ -1,4 +1,4 @@ -project "ddsdump" +project "texturec" uuid "838801ee-7bc3-11e1-9f19-eae7d36e7d26" kind "ConsoleApp" @@ -10,7 +10,8 @@ project "ddsdump" files { BGFX_DIR .. "src/dds.*", - BGFX_DIR .. "tools/ddsdump.cpp", + BGFX_DIR .. "tools/texturec/**.cpp", + BGFX_DIR .. "tools/texturec/**.h", } links { diff --git a/src/bgfx.cpp b/src/bgfx.cpp index e205d4b86..4e48dd10b 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -30,11 +30,11 @@ namespace bgfx #define BGFX_MAIN_THREAD_MAGIC 0x78666762 #if BGFX_CONFIG_MULTITHREADED -# define BGFX_MAIN_THREAD() BX_CHECK(BGFX_MAIN_THREAD_MAGIC == s_threadIndex, "Must be called from main thread.") -# define BGFX_RENDER_THREAD() BX_CHECK(BGFX_MAIN_THREAD_MAGIC != s_threadIndex, "Must be called from render thread.") +# define BGFX_CHECK_MAIN_THREAD() BX_CHECK(BGFX_MAIN_THREAD_MAGIC == s_threadIndex, "Must be called from main thread.") +# define BGFX_CHECK_RENDER_THREAD() BX_CHECK(BGFX_MAIN_THREAD_MAGIC != s_threadIndex, "Must be called from render thread.") #else -# define BGFX_MAIN_THREAD() -# define BGFX_RENDER_THREAD() +# define BGFX_CHECK_MAIN_THREAD() +# define BGFX_CHECK_RENDER_THREAD() #endif // BGFX_CONFIG_MULTITHREADED void fatalStub(Fatal::Enum _code, const char* _str) @@ -197,6 +197,7 @@ namespace bgfx void TextVideoMemBlitter::init() { + BGFX_CHECK_MAIN_THREAD(); m_decl.begin(); m_decl.add(Attrib::Position, 3, AttribType::Float); m_decl.add(Attrib::Color0, 4, AttribType::Uint8, true); @@ -250,6 +251,7 @@ namespace bgfx void TextVideoMemBlitter::blit(const TextVideoMem& _mem) { + BGFX_CHECK_RENDER_THREAD(); struct Vertex { float m_x; @@ -360,6 +362,7 @@ namespace bgfx void ClearQuad::init() { + BGFX_CHECK_MAIN_THREAD(); #if BGFX_CONFIG_RENDERER_DIRECT3D11 m_decl.begin(); m_decl.add(Attrib::Position, 3, AttribType::Float); @@ -544,25 +547,31 @@ namespace bgfx void shutdown() { - BGFX_MAIN_THREAD(); + BGFX_CHECK_MAIN_THREAD(); s_ctx.shutdown(); + + s_threadIndex = 0; + g_fatal = fatalStub; + g_realloc = reallocStub; + g_free = freeStub; + g_cache = cacheStub; } void reset(uint32_t _width, uint32_t _height, uint32_t _flags) { - BGFX_MAIN_THREAD(); + BGFX_CHECK_MAIN_THREAD(); s_ctx.reset(_width, _height, _flags); } void frame() { - BGFX_MAIN_THREAD(); + BGFX_CHECK_MAIN_THREAD(); s_ctx.frame(); } bool renderFrame() { - BGFX_RENDER_THREAD(); + BGFX_CHECK_RENDER_THREAD(); return s_ctx.renderFrame(); } @@ -618,7 +627,7 @@ namespace bgfx void VertexDecl::end() { - m_hash = hash(m_attributes, sizeof(m_attributes) ); + m_hash = hashMurmur2A(m_attributes, sizeof(m_attributes) ); } void VertexDecl::add(Attrib::Enum _attrib, uint8_t _num, AttribType::Enum _type, bool _normalized) @@ -668,7 +677,7 @@ namespace bgfx #if BGFX_CONFIG_DEBUG BX_TRACE("vertexdecl %08x (%08x), stride %d" , _decl.m_hash - , hash(_decl.m_attributes, sizeof(_decl.m_attributes) ) + , hashMurmur2A(_decl.m_attributes, sizeof(_decl.m_attributes) ) , _decl.m_stride ); @@ -842,16 +851,19 @@ namespace bgfx void setDebug(uint32_t _debug) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_debug = _debug; } void dbgTextClear(uint8_t _attr, bool _small) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.dbgTextClear(_attr, _small); } void dbgTextPrintf(uint16_t _x, uint16_t _y, uint8_t _attr, const char* _format, ...) { + BGFX_CHECK_MAIN_THREAD(); va_list argList; va_start(argList, _format); s_ctx.dbgTextPrintfVargs(_x, _y, _attr, _format, argList); @@ -860,11 +872,13 @@ namespace bgfx IndexBufferHandle createIndexBuffer(const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.createIndexBuffer(_mem); } void destroyIndexBuffer(IndexBufferHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyIndexBuffer(_handle); } @@ -875,126 +889,148 @@ namespace bgfx void destroyVertexBuffer(VertexBufferHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyVertexBuffer(_handle); } DynamicIndexBufferHandle createDynamicIndexBuffer(uint16_t _num) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.createDynamicIndexBuffer(_num); } DynamicIndexBufferHandle createDynamicIndexBuffer(const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); return s_ctx.createDynamicIndexBuffer(_mem); } void updateDynamicIndexBuffer(DynamicIndexBufferHandle _handle, const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); s_ctx.updateDynamicIndexBuffer(_handle, _mem); } void destroyDynamicIndexBuffer(DynamicIndexBufferHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyDynamicIndexBuffer(_handle); } DynamicVertexBufferHandle createDynamicVertexBuffer(uint16_t _num, const VertexDecl& _decl) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.createDynamicVertexBuffer(_num, _decl); } DynamicVertexBufferHandle createDynamicVertexBuffer(const Memory* _mem, const VertexDecl& _decl) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); return s_ctx.createDynamicVertexBuffer(_mem, _decl); } void updateDynamicVertexBuffer(DynamicVertexBufferHandle _handle, const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); s_ctx.updateDynamicVertexBuffer(_handle, _mem); } void destroyDynamicVertexBuffer(DynamicVertexBufferHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyDynamicVertexBuffer(_handle); } bool checkAvailTransientIndexBuffer(uint16_t _num) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.m_submit->checkAvailTransientIndexBuffer(_num); } void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint16_t _num) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _tib, "_tib can't be NULL"); return s_ctx.allocTransientIndexBuffer(_tib, _num); } bool checkAvailTransientVertexBuffer(uint16_t _num, const VertexDecl& _decl) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.m_submit->checkAvailTransientVertexBuffer(_num, _decl.m_stride); } void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint16_t _num, const VertexDecl& _decl) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _tvb, "_tvb can't be NULL"); return s_ctx.allocTransientVertexBuffer(_tvb, _num, _decl); } const InstanceDataBuffer* allocInstanceDataBuffer(uint16_t _num, uint16_t _stride) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.allocInstanceDataBuffer(_num, _stride); } VertexShaderHandle createVertexShader(const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); return s_ctx.createVertexShader(_mem); } void destroyVertexShader(VertexShaderHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyVertexShader(_handle); } FragmentShaderHandle createFragmentShader(const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); return s_ctx.createFragmentShader(_mem); } void destroyFragmentShader(FragmentShaderHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyFragmentShader(_handle); } ProgramHandle createProgram(VertexShaderHandle _vsh, FragmentShaderHandle _fsh) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.createProgram(_vsh, _fsh); } void destroyProgram(ProgramHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyProgram(_handle); } TextureHandle createTexture(const Memory* _mem, uint32_t _flags, TextureInfo* _info) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); return s_ctx.createTexture(_mem, _flags, _info); } TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate); const bgfx::Memory* mem = alloc(size); - StreamWrite stream(mem->data, mem->size); - uint32_t magic = BGFX_MAGIC; - stream.write(magic); + bx::StaticMemoryBlockWriter writer(mem->data, mem->size); + uint32_t magic = BGFX_CHUNK_MAGIC_TEX; + bx::write(&writer, magic); TextureCreate tc; tc.m_flags = _flags; @@ -1002,22 +1038,23 @@ namespace bgfx tc.m_height = _height; tc.m_depth = 0; tc.m_numMips = _numMips; - tc.m_type = uint8_t(_format); + tc.m_format = uint8_t(_format); tc.m_cubeMap = false; tc.m_mem = _mem; - stream.write(tc); + bx::write(&writer, tc); return s_ctx.createTexture(mem, _flags, NULL); } TextureHandle createTexture3D(uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate); const bgfx::Memory* mem = alloc(size); - StreamWrite stream(mem->data, mem->size); - uint32_t magic = BGFX_MAGIC; - stream.write(magic); + bx::StaticMemoryBlockWriter writer(mem->data, mem->size); + uint32_t magic = BGFX_CHUNK_MAGIC_TEX; + bx::write(&writer, magic); TextureCreate tc; tc.m_flags = _flags; @@ -1025,22 +1062,23 @@ namespace bgfx tc.m_height = _height; tc.m_depth = _depth; tc.m_numMips = _numMips; - tc.m_type = uint8_t(_format); + tc.m_format = uint8_t(_format); tc.m_cubeMap = false; tc.m_mem = _mem; - stream.write(tc); + bx::write(&writer, tc); return s_ctx.createTexture(mem, _flags, NULL); } TextureHandle createTextureCube(uint16_t _sides, uint16_t _width, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate); const bgfx::Memory* mem = alloc(size); - StreamWrite stream(mem->data, mem->size); - uint32_t magic = BGFX_MAGIC; - stream.write(magic); + bx::StaticMemoryBlockWriter writer(mem->data, mem->size); + uint32_t magic = BGFX_CHUNK_MAGIC_TEX; + bx::write(&writer, magic); TextureCreate tc; tc.m_flags = _flags; @@ -1048,21 +1086,23 @@ namespace bgfx tc.m_sides = _sides; tc.m_depth = 0; tc.m_numMips = _numMips; - tc.m_type = uint8_t(_format); + tc.m_format = uint8_t(_format); tc.m_cubeMap = true; tc.m_mem = _mem; - stream.write(tc); + bx::write(&writer, tc); return s_ctx.createTexture(mem, _flags, NULL); } void destroyTexture(TextureHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyTexture(_handle); } void updateTexture2D(TextureHandle _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); if (_width == 0 || _height == 0) @@ -1077,6 +1117,7 @@ namespace bgfx void updateTexture3D(TextureHandle _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _z, uint16_t _width, uint16_t _height, uint16_t _depth, const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); if (_width == 0 || _height == 0 @@ -1092,6 +1133,7 @@ namespace bgfx void updateTextureCube(TextureHandle _handle, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _mem, "_mem can't be NULL"); if (_width == 0 || _height == 0) @@ -1106,126 +1148,151 @@ namespace bgfx RenderTargetHandle createRenderTarget(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.createRenderTarget(_width, _height, _flags, _textureFlags); } void destroyRenderTarget(RenderTargetHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyRenderTarget(_handle); } UniformHandle createUniform(const char* _name, UniformType::Enum _type, uint16_t _num) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.createUniform(_name, _type, _num); } void destroyUniform(UniformHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.destroyUniform(_handle); } void setViewRect(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setViewRect(_id, _x, _y, _width, _height); } void setViewRectMask(uint32_t _viewMask, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setViewRectMask(_viewMask, _x, _y, _width, _height); } void setViewClear(uint8_t _id, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setViewClear(_id, _flags, _rgba, _depth, _stencil); } void setViewClearMask(uint32_t _viewMask, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setViewClearMask(_viewMask, _flags, _rgba, _depth, _stencil); } void setViewSeq(uint8_t _id, bool _enabled) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setViewSeq(_id, _enabled); } void setViewSeqMask(uint32_t _viewMask, bool _enabled) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setViewSeqMask(_viewMask, _enabled); } void setViewRenderTarget(uint8_t _id, RenderTargetHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setViewRenderTarget(_id, _handle); } void setViewRenderTargetMask(uint32_t _mask, RenderTargetHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setViewRenderTargetMask(_mask, _handle); } void setViewTransform(uint8_t _id, const void* _view, const void* _proj, uint8_t _other) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setViewTransform(_id, _view, _proj, _other); } void setViewTransformMask(uint32_t _viewMask, const void* _view, const void* _proj, uint8_t _other) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setViewTransformMask(_viewMask, _view, _proj, _other); } void setState(uint64_t _state) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setState(_state); } void setStencil(uint32_t _fstencil, uint32_t _bstencil) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setStencil(_fstencil, _bstencil); } uint32_t setTransform(const void* _mtx, uint16_t _num) { + BGFX_CHECK_MAIN_THREAD(); return s_ctx.m_submit->setTransform(_mtx, _num); } void setTransform(uint32_t _cache, uint16_t _num) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setTransform(_cache, _num); } void setUniform(UniformHandle _handle, const void* _value, uint16_t _num) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setUniform(_handle, _value, _num); } void setUniform(ProgramHandle _program, UniformHandle _handle, const void* _value) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.setUniform(_program, _handle, _value); } void setIndexBuffer(IndexBufferHandle _handle, uint32_t _firstIndex, uint32_t _numIndices) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setIndexBuffer(_handle, _firstIndex, _numIndices); } void setIndexBuffer(IndexBufferHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setIndexBuffer(_handle, BGFX_DRAW_WHOLE_INDEX_BUFFER, 0); } void setIndexBuffer(DynamicIndexBufferHandle _handle, uint32_t _firstIndex, uint32_t _numIndices) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setIndexBuffer(s_ctx.m_dynamicIndexBuffers[_handle.idx].m_handle, _firstIndex, _numIndices); } void setIndexBuffer(DynamicIndexBufferHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setIndexBuffer(s_ctx.m_dynamicIndexBuffers[_handle.idx].m_handle, BGFX_DRAW_WHOLE_INDEX_BUFFER, 0); } void setIndexBuffer(const TransientIndexBuffer* _tib, uint32_t _numIndices) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _tib, "_tib can't be NULL"); uint32_t numIndices = uint32_min(_numIndices, _tib->size/2); s_ctx.m_submit->setIndexBuffer(_tib, numIndices); @@ -1233,52 +1300,62 @@ namespace bgfx void setVertexBuffer(VertexBufferHandle _handle, uint32_t _numVertices) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setVertexBuffer(_handle, _numVertices); } void setVertexBuffer(DynamicVertexBufferHandle _handle, uint32_t _numVertices) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setVertexBuffer(s_ctx.m_dynamicVertexBuffers[_handle.idx], _numVertices); } void setVertexBuffer(const TransientVertexBuffer* _tvb, uint32_t _numVertices) { + BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _tvb, "_tvb can't be NULL"); s_ctx.m_submit->setVertexBuffer(_tvb, _numVertices); } void setInstanceDataBuffer(const InstanceDataBuffer* _idb, uint16_t _num) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setInstanceDataBuffer(_idb, _num); } void setProgram(ProgramHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setProgram(_handle); } void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setTexture(_stage, _sampler, _handle); } void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->setTexture(_stage, _sampler, _handle, _depth); } void submit(uint8_t _id, int32_t _depth) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->submit(_id, _depth); } void submitMask(uint32_t _viewMask, int32_t _depth) { + BGFX_CHECK_MAIN_THREAD(); s_ctx.m_submit->submitMask(_viewMask, _depth); } void saveScreenShot(const char* _filePath) { + BGFX_CHECK_MAIN_THREAD(); uint32_t len = (uint32_t)strlen(_filePath)+1; const Memory* mem = alloc(len); memcpy(mem->data, _filePath, mem->size); diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 2d7a9098a..a463df241 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -27,6 +27,14 @@ extern void dbgPrintfData(const void* _data, uint32_t _size, const char* _format dbgPrintf(BX_FILE_LINE_LITERAL "BGFX " _format "\n", ##__VA_ARGS__); \ } while(0) +# define BX_WARN(_condition, _format, ...) \ + do { \ + if (!(_condition) ) \ + { \ + BX_TRACE(BX_FILE_LINE_LITERAL "WARN " _format, ##__VA_ARGS__); \ + } \ + } while(0) + # define BX_CHECK(_condition, _format, ...) \ do { \ if (!(_condition) ) \ @@ -56,6 +64,7 @@ extern void dbgPrintfData(const void* _data, uint32_t _size, const char* _format #include #include #include +#include #if BX_PLATFORM_WINDOWS # include @@ -67,18 +76,11 @@ extern HWND g_bgfxHwnd; # include #endif // BX_PLATFORM_* -#ifndef MAKEFOURCC -# define MAKEFOURCC(_a, _b, _c, _d) (0 \ - | ( (uint32_t)(_a) \ - | ( (uint32_t)(_b) << 8) \ - | ( (uint32_t)(_c) << 16) \ - | ( (uint32_t)(_d) << 24) \ - ) ) -#endif // MAKEFOURCC - #include "dds.h" -#define BGFX_MAGIC MAKEFOURCC('B','G','F','X') +#define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', 0x0) +#define BGFX_CHUNK_MAGIC_TEX BX_MAKEFOURCC('T', 'E', 'X', 0x0) +#define BGFX_CHUNK_MAGIC_VSH BX_MAKEFOURCC('V', 'S', 'H', 0x0) #if BGFX_CONFIG_USE_TINYSTL @@ -174,7 +176,7 @@ namespace bgfx }; uint16_t m_depth; uint8_t m_numMips; - uint8_t m_type; + uint8_t m_format; bool m_cubeMap; const Memory* m_mem; }; @@ -201,14 +203,6 @@ namespace bgfx return _a < _b ? _b : _a; } - inline uint32_t hash(const void* _data, uint32_t _size) - { - HashMurmur2A murmur; - murmur.begin(); - murmur.add(_data, (int)_size); - return murmur.end(); - } - inline uint32_t gcd(uint32_t _a, uint32_t _b) { do @@ -413,113 +407,6 @@ namespace bgfx const char* getPredefinedUniformName(PredefinedUniform::Enum _enum); PredefinedUniform::Enum nameToPredefinedUniformEnum(const char* _name); - class StreamRead - { - public: - StreamRead(const void* _data, uint32_t _size) - : m_data( (uint8_t*)_data) - , m_size(_size) - , m_pos(0) - { - } - - ~StreamRead() - { - } - - void skip(uint32_t _size) - { - BX_CHECK(m_size-m_pos >= _size, "Available %d, requested %d.", m_size-m_pos, _size); - m_pos += _size; - } - - void read(void* _data, uint32_t _size) - { - BX_CHECK(m_size-m_pos >= _size, "Available %d, requested %d.", m_size-m_pos, _size); - memcpy(_data, &m_data[m_pos], _size); - m_pos += _size; - } - - template - void read(Ty& _value) - { - read(&_value, sizeof(Ty) ); - } - - const uint8_t* getDataPtr() const - { - return &m_data[m_pos]; - } - - uint32_t getPos() const - { - return m_pos; - } - - void align(uint16_t _align) - { - m_pos = strideAlign(m_pos, _align); - } - - uint32_t remaining() const - { - return m_size-m_pos; - } - - private: - const uint8_t* m_data; - uint32_t m_size; - uint32_t m_pos; - }; - - class StreamWrite - { - public: - StreamWrite(void* _data, uint32_t _size) - : m_data( (uint8_t*)_data) - , m_size(_size) - , m_pos(0) - { - } - - ~StreamWrite() - { - } - - void write(void* _data, uint32_t _size) - { - BX_CHECK(m_size-m_pos >= _size, "Write out of bounds. Available %d, requested %d.", m_size-m_pos, _size); - memcpy(&m_data[m_pos], _data, _size); - m_pos += _size; - } - - template - void write(Ty& _value) - { - write(&_value, sizeof(Ty) ); - } - - uint8_t* getDataPtr() const - { - return &m_data[m_pos]; - } - - uint32_t getPos() const - { - return m_pos; - } - - void align(uint16_t _align) - { - m_pos = strideAlign(m_pos, _align); - } - - private: - uint8_t* m_data; - uint32_t m_size; - uint32_t m_pos; - }; - struct CommandBuffer { CommandBuffer() @@ -1929,8 +1816,24 @@ namespace bgfx VertexShaderHandle createVertexShader(const Memory* _mem) { + bx::MemoryReader reader(_mem->data, _mem->size); + + uint32_t magic; + bx::read(&reader, magic); + + if (BGFX_CHUNK_MAGIC_VSH != magic) + { + BX_WARN(false, "Invalid vertex shader signature! 0x%08x", magic); + VertexShaderHandle invalid = BGFX_INVALID_HANDLE; + return invalid; + } + VertexShaderHandle handle = { m_vertexShaderHandle.alloc() }; - m_vertexShaderRef[handle.idx] = 1; + + VertexShaderRef& vsr = m_vertexShaderRef[handle.idx]; + vsr.m_refCount = 1; + bx::read(&reader, vsr.m_outputHash); + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateVertexShader); cmdbuf.write(handle); cmdbuf.write(_mem); @@ -1944,12 +1847,14 @@ namespace bgfx void vertexShaderIncRef(VertexShaderHandle _handle) { - ++m_vertexShaderRef[_handle.idx]; + VertexShaderRef& vsr = m_vertexShaderRef[_handle.idx]; + ++vsr.m_refCount; } void vertexShaderDecRef(VertexShaderHandle _handle) { - int32_t refs = --m_vertexShaderRef[_handle.idx]; + VertexShaderRef& vsr = m_vertexShaderRef[_handle.idx]; + int32_t refs = --vsr.m_refCount; if (0 == refs) { CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyVertexShader); @@ -1960,8 +1865,24 @@ namespace bgfx FragmentShaderHandle createFragmentShader(const Memory* _mem) { + bx::MemoryReader reader(_mem->data, _mem->size); + + uint32_t magic; + bx::read(&reader, magic); + + if (BGFX_CHUNK_MAGIC_FSH != magic) + { + BX_WARN(false, "Invalid fragment shader signature! 0x%08x", magic); + FragmentShaderHandle invalid = BGFX_INVALID_HANDLE; + return invalid; + } + FragmentShaderHandle handle = { m_fragmentShaderHandle.alloc() }; - m_fragmentShaderRef[handle.idx] = 1; + + FragmentShaderRef& fsr = m_fragmentShaderRef[handle.idx]; + fsr.m_refCount = 1; + bx::read(&reader, fsr.m_inputHash); + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateFragmentShader); cmdbuf.write(handle); cmdbuf.write(_mem); @@ -1975,12 +1896,14 @@ namespace bgfx void fragmentShaderIncRef(FragmentShaderHandle _handle) { - ++m_fragmentShaderRef[_handle.idx]; + FragmentShaderRef& fsr = m_fragmentShaderRef[_handle.idx]; + ++fsr.m_refCount; } void fragmentShaderDecRef(FragmentShaderHandle _handle) { - int32_t refs = --m_fragmentShaderRef[_handle.idx]; + FragmentShaderRef& fsr = m_fragmentShaderRef[_handle.idx]; + int32_t refs = --fsr.m_refCount; if (0 == refs) { CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyFragmentShader); @@ -1991,6 +1914,15 @@ namespace bgfx ProgramHandle createProgram(VertexShaderHandle _vsh, FragmentShaderHandle _fsh) { + const VertexShaderRef& vsr = m_vertexShaderRef[_vsh.idx]; + const FragmentShaderRef& fsr = m_fragmentShaderRef[_fsh.idx]; + if (vsr.m_outputHash != fsr.m_inputHash) + { + BX_WARN(vsr.m_outputHash == fsr.m_inputHash, "Vertex shader output doesn't match fragment shader input."); + ProgramHandle invalid = BGFX_INVALID_HANDLE; + return invalid; + } + ProgramHandle handle; handle.idx = m_programHandle.alloc(); @@ -2859,8 +2791,19 @@ namespace bgfx HandleAlloc m_renderTargetHandle; HandleAlloc m_uniformHandle; - int32_t m_vertexShaderRef[BGFX_CONFIG_MAX_VERTEX_SHADERS]; - int32_t m_fragmentShaderRef[BGFX_CONFIG_MAX_FRAGMENT_SHADERS]; + struct VertexShaderRef + { + int32_t m_refCount; + uint32_t m_outputHash; + } m_vertexShaderRef[BGFX_CONFIG_MAX_VERTEX_SHADERS]; + + struct FragmentShaderRef + { + int32_t m_refCount; + uint32_t m_inputHash; + + } m_fragmentShaderRef[BGFX_CONFIG_MAX_FRAGMENT_SHADERS]; + struct ProgramRef { VertexShaderHandle m_vsh; diff --git a/src/config.h b/src/config.h index 8a632f364..5ff0769ca 100644 --- a/src/config.h +++ b/src/config.h @@ -85,14 +85,21 @@ # define BGFX_CONFIG_DEBUG_PERFHUD 0 #endif // BGFX_CONFIG_DEBUG_NVPERFHUD +/// DX9 PIX markers #ifndef BGFX_CONFIG_DEBUG_PIX # define BGFX_CONFIG_DEBUG_PIX 0 #endif // BGFX_CONFIG_DEBUG_PIX +/// AMD gDEBugger markers #ifndef BGFX_CONFIG_DEBUG_GREMEDY # define BGFX_CONFIG_DEBUG_GREMEDY 0 #endif // BGFX_CONFIG_DEBUG_GREMEDY +/// DX11 object names +#ifndef BGFX_CONFIG_DEBUG_OBJECT_NAME +# define BGFX_CONFIG_DEBUG_OBJECT_NAME BGFX_CONFIG_DEBUG +#endif // BGFX_CONFIG_DEBUG_OBJECT_NAME + #ifndef BGFX_CONFIG_MULTITHREADED # define BGFX_CONFIG_MULTITHREADED ( (BX_PLATFORM_WINDOWS|BX_PLATFORM_XBOX360|BX_PLATFORM_NACL)&(!BGFX_CONFIG_RENDERER_NULL) ) #endif // BGFX_CONFIG_MULTITHREADED diff --git a/src/dds.cpp b/src/dds.cpp index dd6a7b7a8..316c621be 100644 --- a/src/dds.cpp +++ b/src/dds.cpp @@ -9,15 +9,15 @@ namespace bgfx { -#define DDS_MAGIC MAKEFOURCC('D','D','S',' ') +#define DDS_MAGIC BX_MAKEFOURCC('D','D','S',' ') #define DDS_HEADER_SIZE 124 #define DDS_IMAGE_DATA_OFFSET (DDS_HEADER_SIZE + 4) -#define DDS_DXT1 MAKEFOURCC('D', 'X', 'T', '1') -#define DDS_DXT2 MAKEFOURCC('D', 'X', 'T', '2') -#define DDS_DXT3 MAKEFOURCC('D', 'X', 'T', '3') -#define DDS_DXT4 MAKEFOURCC('D', 'X', 'T', '4') -#define DDS_DXT5 MAKEFOURCC('D', 'X', 'T', '5') +#define DDS_DXT1 BX_MAKEFOURCC('D', 'X', 'T', '1') +#define DDS_DXT2 BX_MAKEFOURCC('D', 'X', 'T', '2') +#define DDS_DXT3 BX_MAKEFOURCC('D', 'X', 'T', '3') +#define DDS_DXT4 BX_MAKEFOURCC('D', 'X', 'T', '4') +#define DDS_DXT5 BX_MAKEFOURCC('D', 'X', 'T', '5') #define D3DFMT_A16B16G16R16F 113 @@ -58,10 +58,10 @@ namespace bgfx bool isDds(const Memory* _mem) { - StreamRead stream(_mem->data, _mem->size); + bx::MemoryReader reader(_mem->data, _mem->size); uint32_t magic; - stream.read(magic); + bx::read(&reader, magic); return DDS_MAGIC == magic; } @@ -294,11 +294,11 @@ void Mip::decode(uint8_t* _dst) uint32_t width = m_width; uint32_t height = m_height; - if (m_bpp == 1 - || m_bpp == 4 - || m_bpp == 8) + if (m_bpp == 8 + || m_bpp == 32 + || m_bpp == 64) { - uint32_t pitch = m_width*m_bpp; + uint32_t pitch = m_width*m_bpp/8; memcpy(_dst, src, pitch*height); } else @@ -322,10 +322,10 @@ void Mip::decode(uint8_t* _dst) bool parseDds(Dds& _dds, const Memory* _mem) { - StreamRead stream(_mem->data, _mem->size); + bx::MemoryReader reader(_mem->data, _mem->size); uint32_t magic; - stream.read(magic); + bx::read(&reader, magic); if (DDS_MAGIC != magic) { @@ -333,7 +333,7 @@ bool parseDds(Dds& _dds, const Memory* _mem) } uint32_t headerSize; - stream.read(headerSize); + bx::read(&reader, headerSize); if (headerSize < DDS_HEADER_SIZE) { @@ -341,7 +341,7 @@ bool parseDds(Dds& _dds, const Memory* _mem) } uint32_t flags; - stream.read(flags); + bx::read(&reader, flags); if ( (flags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) ) != (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) ) { @@ -349,47 +349,46 @@ bool parseDds(Dds& _dds, const Memory* _mem) } uint32_t height; - stream.read(height); + bx::read(&reader, height); uint32_t width; - stream.read(width); + bx::read(&reader, width); uint32_t pitch; - stream.read(pitch); + bx::read(&reader, pitch); uint32_t depth; - stream.read(depth); + bx::read(&reader, depth); uint32_t mips; - stream.read(mips); + bx::read(&reader, mips); - stream.skip(44); // reserved - - stream.skip(4); // pixel format size + bx::skip(&reader, 44); // reserved + bx::skip(&reader, 4); // pixel format size uint32_t pixelFlags; - stream.read(pixelFlags); + bx::read(&reader, pixelFlags); uint32_t fourcc; - stream.read(fourcc); + bx::read(&reader, fourcc); uint32_t rgbCount; - stream.read(rgbCount); + bx::read(&reader, rgbCount); uint32_t rbitmask; - stream.read(rbitmask); + bx::read(&reader, rbitmask); uint32_t gbitmask; - stream.read(gbitmask); + bx::read(&reader, gbitmask); uint32_t bbitmask; - stream.read(bbitmask); + bx::read(&reader, bbitmask); uint32_t abitmask; - stream.read(abitmask); + bx::read(&reader, abitmask); uint32_t caps[4]; - stream.read(caps); + bx::read(&reader, caps); if ( (caps[0] & DDSCAPS_TEXTURE) == 0) { @@ -406,9 +405,9 @@ bool parseDds(Dds& _dds, const Memory* _mem) } } - stream.skip(4); // reserved + bx::skip(&reader, 4); // reserved - uint8_t bpp = 1; + uint8_t bpp = 0; uint8_t blockSize = 1; TextureFormat::Enum type = TextureFormat::Unknown; bool hasAlpha = pixelFlags & DDPF_ALPHAPIXELS; @@ -420,24 +419,27 @@ bool parseDds(Dds& _dds, const Memory* _mem) case DDS_DXT1: type = TextureFormat::Dxt1; blockSize = 8; + bpp = 4; break; case DDS_DXT2: case DDS_DXT3: type = TextureFormat::Dxt3; blockSize = 16; + bpp = 4; break; case DDS_DXT4: case DDS_DXT5: type = TextureFormat::Dxt5; blockSize = 16; + bpp = 4; break; case D3DFMT_A16B16G16R16F: type = TextureFormat::ABGR16; blockSize = 8; - bpp = 8; + bpp = 64; break; } } @@ -448,20 +450,20 @@ bool parseDds(Dds& _dds, const Memory* _mem) case DDPF_RGB: type = TextureFormat::XRGB8; blockSize = 3; - bpp = 3; + bpp = 24; break; case DDPF_RGB|DDPF_ALPHAPIXELS: type = TextureFormat::ARGB8; blockSize = 4; - bpp = 4; + bpp = 32; break; case DDPF_INDEXED: case DDPF_LUMINANCE: case DDPF_ALPHA: type = TextureFormat::L8; - bpp = 1; + bpp = 8; break; // type = TextureFormat::A8; diff --git a/src/fs_clear_dx11.bin.h b/src/fs_clear_dx11.bin.h index 47959dbfe..4423a3c83 100644 --- a/src/fs_clear_dx11.bin.h +++ b/src/fs_clear_dx11.bin.h @@ -1,38 +1,39 @@ -static const uint8_t fs_clear_dx11[554] = +static const uint8_t fs_clear_dx11[562] = { - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x14, 0x02, 0x44, 0x58, 0x42, 0x43, 0xda, 0x0f, 0xc3, 0x91, 0x70, 0x6f, 0xd4, // .....DXBC....po. - 0x7b, 0xeb, 0xe0, 0x21, 0x07, 0x79, 0xd8, 0x54, 0xd4, 0x01, 0x00, 0x00, 0x00, 0x14, 0x02, 0x00, // {..!.y.T........ - 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, // .....4.......... - 0x00, 0x34, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x70, 0x00, 0x00, // .4...x...RDEFp.. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, // .............<.. - 0x00, 0x00, 0x05, 0xff, 0xff, 0x00, 0x91, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x52, 0x44, 0x31, // .........<...RD1 - 0x31, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, // 1<....... ...(.. - 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, // .$...........Mic - 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, // rosoft (R) HLSL - 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, // Shader Compiler - 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, // 9.29.952.3111... - 0xab, 0x49, 0x53, 0x47, 0x4e, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, // .ISGNL.......... - 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // .8.............. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .........D...... - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, // ................ - 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, // .SV_POSITION.COL - 0x4f, 0x52, 0x00, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // OR...OSGN,...... - 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ..... .......... - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, // .............SV_ - 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x00, 0xab, 0xab, 0x53, 0x48, 0x45, 0x58, 0x3c, 0x00, 0x00, // TARGET...SHEX<.. - 0x00, 0x50, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x6a, 0x08, 0x00, 0x01, 0x62, 0x10, 0x00, // .P.......j...b.. - 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, // .........e.... . - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, // .....6.... ..... - 0x00, 0x46, 0x1e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, // .F.......>...STA - 0x54, 0x94, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // T............... - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x46, 0x53, 0x48, 0x00, 0xa4, 0x8b, 0xef, 0x49, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, // FSH....I........ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x02, 0x44, 0x58, 0x42, // .............DXB + 0x43, 0xda, 0x0f, 0xc3, 0x91, 0x70, 0x6f, 0xd4, 0x7b, 0xeb, 0xe0, 0x21, 0x07, 0x79, 0xd8, 0x54, // C....po.{..!.y.T + 0xd4, 0x01, 0x00, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, // .............4.. + 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, // .........4...x.. + 0x00, 0x52, 0x44, 0x45, 0x46, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .RDEFp.......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0xff, 0x00, 0x91, 0x00, // .....<.......... + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x52, 0x44, 0x31, 0x31, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, // .<...RD11<...... + 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, // . ...(...$...... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, // .....Microsoft ( + 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, // R) HLSL Shader C + 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, // ompiler 9.29.952 + 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x4c, 0x00, 0x00, // .3111....ISGNL.. + 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .........8...... + 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, // ................ + 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // .D.............. + 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, // .........SV_POSI + 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0xab, 0xab, 0x4f, 0x53, 0x47, // TION.COLOR...OSG + 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, // N,........... .. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x00, 0xab, // .....SV_TARGET.. + 0xab, 0x53, 0x48, 0x45, 0x58, 0x3c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, // .SHEX<...P...... + 0x00, 0x6a, 0x08, 0x00, 0x01, 0x62, 0x10, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, // .j...b.......... + 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, // .e.... ......6.. + 0x05, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x01, 0x00, 0x00, // .. ......F...... + 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x94, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, // .>...STAT....... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, // .. }; diff --git a/src/fs_debugfont_dx11.bin.h b/src/fs_debugfont_dx11.bin.h index aa93167ad..fcc54a453 100644 --- a/src/fs_debugfont_dx11.bin.h +++ b/src/fs_debugfont_dx11.bin.h @@ -1,61 +1,62 @@ -static const uint8_t fs_debugfont_dx11[922] = +static const uint8_t fs_debugfont_dx11[930] = { - 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x84, 0x03, 0x44, 0x58, 0x42, 0x43, 0x7f, 0x04, 0x32, 0xab, 0xf6, 0xa8, 0x90, // .....DXBC..2.... - 0xe5, 0x2c, 0xd4, 0x3b, 0xd7, 0xa9, 0x89, 0x79, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x84, 0x03, 0x00, // .,.;...y........ - 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, // .....4.......... - 0x00, 0xd0, 0x01, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xd4, 0x00, 0x00, // .........RDEF... - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, // .............<.. - 0x00, 0x00, 0x05, 0xff, 0xff, 0x00, 0x91, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x52, 0x44, 0x31, // .............RD1 - 0x31, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, // 1<....... ...(.. - 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, // .$...........|.. - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, // ................ - 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, // ................ - 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x74, // .............u_t - 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00, 0x75, // exColorSampler.u - 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, // _texColorTexture - 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, // .Microsoft (R) H - 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, // LSL Shader Compi - 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, // ler 9.29.952.311 - 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // 1....ISGN....... - 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // .....h.......... - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, // .............t.. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // ................ - 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .....t.......... - 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x7a, 0x00, 0x00, // .............z.. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // ................ - 0x00, 0x03, 0x03, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, // .....SV_POSITION - 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, // .COLOR.TEXCOORD. - 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, // .OSGN,.......... - 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // . .............. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x54, 0x41, 0x52, 0x47, // .........SV_TARG - 0x45, 0x54, 0x00, 0xab, 0xab, 0x53, 0x48, 0x45, 0x58, 0x10, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, // ET...SHEX....P.. - 0x00, 0x44, 0x00, 0x00, 0x00, 0x6a, 0x08, 0x00, 0x01, 0x5a, 0x00, 0x00, 0x03, 0x00, 0x60, 0x10, // .D...j...Z....`. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, // .....X....p..... - 0x00, 0x55, 0x55, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, // .UU..b.......... - 0x00, 0x62, 0x10, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, // .b...........b.. - 0x03, 0x32, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, // .2.......e.... . - 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, // .....h.......E.. - 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, // .....CU......... - 0x00, 0x46, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, // .F.......F~..... - 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf2, 0x00, 0x10, // ..`............. - 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, // .....F.......F.. - 0x80, 0x41, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x09, 0xf2, 0x00, 0x10, // .A.......2...... - 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, // .............F.. - 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, // .....F.......1.. - 0x07, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, // .........:...... - 0x00, 0x01, 0x40, 0x00, 0x00, 0x81, 0x80, 0x80, 0x3b, 0x0d, 0x00, 0x04, 0x03, 0x0a, 0x00, 0x10, // ..@.....;....... - 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, // .....6.... ..... - 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, // .F.......>...STA - 0x54, 0x94, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // T............... - 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x46, 0x53, 0x48, 0x00, 0xb8, 0xbe, 0x22, 0x66, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, // FSH..."f........ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x03, 0x44, 0x58, 0x42, // .............DXB + 0x43, 0x7f, 0x04, 0x32, 0xab, 0xf6, 0xa8, 0x90, 0xe5, 0x2c, 0xd4, 0x3b, 0xd7, 0xa9, 0x89, 0x79, // C..2.....,.;...y + 0xfd, 0x01, 0x00, 0x00, 0x00, 0x84, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, // .............4.. + 0x00, 0x10, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0xd0, 0x01, 0x00, 0x00, 0xe8, 0x02, 0x00, // ................ + 0x00, 0x52, 0x44, 0x45, 0x46, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .RDEF........... + 0x00, 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0xff, 0x00, 0x91, 0x00, // .....<.......... + 0x00, 0xa0, 0x00, 0x00, 0x00, 0x52, 0x44, 0x31, 0x31, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, // .....RD11<...... + 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, // . ...(...$...... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .....|.......... 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // ................ + 0x00, 0x01, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, // ................ + 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // ................ + 0x00, 0x0d, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, // .....u_texColorS + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, // ampler.u_texColo + 0x72, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, // rTexture.Microso + 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, // ft (R) HLSL Shad + 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, // er Compiler 9.29 + 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, // .952.3111....ISG + 0x4e, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, // N............h.. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .....t.......... + 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x74, 0x00, 0x00, // .............t.. + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, // ................ + 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .....z.......... + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x53, 0x56, 0x5f, // .............SV_ + 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, // POSITION.COLOR.T + 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x00, 0x00, // EXCOORD..OSGN,.. + 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ......... ...... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, // ................ + 0x00, 0x53, 0x56, 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x00, 0xab, 0xab, 0x53, 0x48, 0x45, // .SV_TARGET...SHE + 0x58, 0x10, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x6a, 0x08, 0x00, // X....P...D...j.. + 0x01, 0x5a, 0x00, 0x00, 0x03, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x18, 0x00, // .Z....`......X.. + 0x04, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x62, 0x10, 0x00, // ..p......UU..b.. + 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0xf2, 0x10, 0x10, // .........b...... + 0x00, 0x02, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, // .....b...2...... + 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, // .e.... ......h.. + 0x02, 0x02, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, // .....E.......CU. + 0x00, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, // .........F...... + 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, // .F~.......`..... + 0x00, 0x00, 0x00, 0x00, 0x08, 0xf2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, // .............F.. + 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, // .....F...A...... + 0x00, 0x32, 0x00, 0x00, 0x09, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, // .2.............. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, // .....F.......F.. + 0x00, 0x02, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, // .....1.......... + 0x00, 0x3a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x81, 0x80, 0x80, // .:........@..... + 0x3b, 0x0d, 0x00, 0x04, 0x03, 0x0a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, // ;............6.. + 0x05, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, // .. ......F...... + 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x94, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, // .>...STAT....... + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, // .. }; diff --git a/src/fs_debugfont_dx9.bin.h b/src/fs_debugfont_dx9.bin.h index d8e642e17..1da618f13 100644 --- a/src/fs_debugfont_dx9.bin.h +++ b/src/fs_debugfont_dx9.bin.h @@ -1,25 +1,26 @@ -static const uint8_t fs_debugfont_dx9[345] = +static const uint8_t fs_debugfont_dx9[353] = { - 0x00, 0x00, 0x54, 0x01, 0x01, 0x02, 0xff, 0xff, 0xfe, 0xff, 0x22, 0x00, 0x43, 0x54, 0x41, 0x42, // ..T.......".CTAB - 0x1c, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x02, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, // ....S........... - 0x1c, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, // ........L...0... - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........<....... - 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0xab, 0x04, 0x00, 0x0c, 0x00, // u_texColor...... - 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5f, 0x32, // ............ps_2 - 0x5f, 0x61, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, // _a.Microsoft (R) - 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, // HLSL Shader Com - 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, // piler 9.29.952.3 - 0x31, 0x31, 0x31, 0x00, 0x51, 0x00, 0x00, 0x05, 0x00, 0x00, 0x0f, 0xa0, 0x81, 0x80, 0x80, 0xbb, // 111.Q........... - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x02, // ................ - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, // ................ - 0x01, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x03, 0xb0, // ................ - 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x00, 0x08, 0x0f, 0xa0, 0x42, 0x00, 0x00, 0x03, // ............B... - 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0xb0, 0x00, 0x08, 0xe4, 0xa0, 0x01, 0x00, 0x00, 0x02, // ................ - 0x01, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, 0x90, 0x02, 0x00, 0x00, 0x03, 0x01, 0x00, 0x0f, 0x80, // ................ - 0x01, 0x00, 0xe4, 0x81, 0x00, 0x00, 0xe4, 0x90, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0f, 0x80, // ................ - 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xe4, 0x80, 0x01, 0x00, 0xe4, 0x90, 0x02, 0x00, 0x00, 0x03, // ................ - 0x01, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0xa0, 0x58, 0x00, 0x00, 0x04, // ............X... - 0x01, 0x00, 0x0f, 0x80, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x55, 0xa0, 0x00, 0x00, 0xaa, 0xa0, // ..........U..... - 0x41, 0x00, 0x00, 0x01, 0x01, 0x00, 0x0f, 0x80, 0x01, 0x00, 0x00, 0x02, 0x00, 0x08, 0x0f, 0x80, // A............... - 0x00, 0x00, 0xe4, 0x80, 0xff, 0xff, 0x00, 0x00, 0x00, // ......... + 0x46, 0x53, 0x48, 0x00, 0xb8, 0xbe, 0x22, 0x66, 0x00, 0x00, 0x54, 0x01, 0x01, 0x02, 0xff, 0xff, // FSH..."f..T..... + 0xfe, 0xff, 0x22, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, // ..".CTAB....S... + 0x01, 0x02, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, // ................ + 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, // L...0........... + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, // <.......u_texCol + 0x6f, 0x72, 0x00, 0xab, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, // or.............. + 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5f, 0x32, 0x5f, 0x61, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, // ....ps_2_a.Micro + 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, // soft (R) HLSL Sh + 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, // ader Compiler 9. + 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0x51, 0x00, 0x00, 0x05, // 29.952.3111.Q... + 0x00, 0x00, 0x0f, 0xa0, 0x81, 0x80, 0x80, 0xbb, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0xbf, // ................ + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0x90, // ................ + 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, // ................ + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x03, 0xb0, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, // ................ + 0x00, 0x08, 0x0f, 0xa0, 0x42, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0xb0, // ....B........... + 0x00, 0x08, 0xe4, 0xa0, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, 0x90, // ................ + 0x02, 0x00, 0x00, 0x03, 0x01, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, 0x81, 0x00, 0x00, 0xe4, 0x90, // ................ + 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xe4, 0x80, // ................ + 0x01, 0x00, 0xe4, 0x90, 0x02, 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x80, 0x00, 0x00, 0xff, 0x80, // ................ + 0x00, 0x00, 0x00, 0xa0, 0x58, 0x00, 0x00, 0x04, 0x01, 0x00, 0x0f, 0x80, 0x01, 0x00, 0x00, 0x80, // ....X........... + 0x00, 0x00, 0x55, 0xa0, 0x00, 0x00, 0xaa, 0xa0, 0x41, 0x00, 0x00, 0x01, 0x01, 0x00, 0x0f, 0x80, // ..U.....A....... + 0x01, 0x00, 0x00, 0x02, 0x00, 0x08, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0x80, 0xff, 0xff, 0x00, 0x00, // ................ + 0x00, // . }; diff --git a/src/fs_debugfont_glsl.bin.h b/src/fs_debugfont_glsl.bin.h index 933d4b9ac..32c6cb1bf 100644 --- a/src/fs_debugfont_glsl.bin.h +++ b/src/fs_debugfont_glsl.bin.h @@ -1,25 +1,26 @@ -static const uint8_t fs_debugfont_glsl[352] = +static const uint8_t fs_debugfont_glsl[360] = { - 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x47, 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x70, 0x72, 0x65, // #ifdef GL_ES.pre - 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, // cision highp flo - 0x61, 0x74, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x4c, // at;.#endif // GL - 0x5f, 0x45, 0x53, 0x0a, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, // _ES..uniform sam - 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, // pler2D u_texColo - 0x72, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, // r;.varying vec2 - 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, // v_texcoord0;.var - 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, // ying vec4 v_colo - 0x72, 0x31, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, // r1;.varying vec4 - 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, // v_color0;.void - 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x76, 0x65, 0x63, 0x34, // main ().{. vec4 - 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, // tmpvar_1;. tmp - 0x76, 0x61, 0x72, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x78, 0x20, 0x28, 0x76, 0x5f, 0x63, // var_1 = mix (v_c - 0x6f, 0x6c, 0x6f, 0x72, 0x31, 0x2c, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x2c, // olor1, v_color0, - 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x20, 0x28, 0x75, 0x5f, 0x74, 0x65, // texture2D (u_te - 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, // xColor, v_texcoo - 0x72, 0x64, 0x30, 0x29, 0x2e, 0x78, 0x78, 0x78, 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x69, 0x66, // rd0).xxxx);. if - 0x20, 0x28, 0x28, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x77, 0x20, 0x3c, 0x20, // ((tmpvar_1.w < - 0x30, 0x2e, 0x30, 0x30, 0x33, 0x39, 0x32, 0x31, 0x35, 0x37, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, // 0.00392157)) {. - 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, // discard;. }; - 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, // . gl_FragColor - 0x3d, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // = tmpvar_1;.}... + 0x46, 0x53, 0x48, 0x00, 0xb8, 0xbe, 0x22, 0x66, 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x47, // FSH..."f#ifdef G + 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, // L_ES.precision h + 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, // ighp float;.#end + 0x69, 0x66, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x0a, 0x75, 0x6e, 0x69, // if // GL_ES..uni + 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x75, // form sampler2D u + 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, // _texColor;.varyi + 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, // ng vec2 v_texcoo + 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, // rd0;.varying vec + 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x31, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, // 4 v_color1;.vary + 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, // ing vec4 v_color + 0x30, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, // 0;.void main (). + 0x7b, 0x0a, 0x20, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, // {. vec4 tmpvar_ + 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x20, 0x3d, 0x20, // 1;. tmpvar_1 = + 0x6d, 0x69, 0x78, 0x20, 0x28, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x31, 0x2c, 0x20, 0x76, // mix (v_color1, v + 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, // _color0, texture + 0x32, 0x44, 0x20, 0x28, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, // 2D (u_texColor, + 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x29, 0x2e, 0x78, 0x78, 0x78, // v_texcoord0).xxx + 0x78, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x28, 0x74, 0x6d, 0x70, 0x76, 0x61, // x);. if ((tmpva + 0x72, 0x5f, 0x31, 0x2e, 0x77, 0x20, 0x3c, 0x20, 0x30, 0x2e, 0x30, 0x30, 0x33, 0x39, 0x32, 0x31, // r_1.w < 0.003921 + 0x35, 0x37, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x63, 0x61, // 57)) {. disca + 0x72, 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, // rd;. };. gl_Fr + 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, // agColor = tmpvar + 0x5f, 0x31, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // _1;.}... }; diff --git a/src/glimports.h b/src/glimports.h index d96209411..7dd5616b6 100644 --- a/src/glimports.h +++ b/src/glimports.h @@ -30,6 +30,7 @@ GL_IMPORT(false, PFNGLGETINTEGERVPROC, glGetIntegerv); GL_IMPORT(false, PFNGLGETSTRINGPROC, glGetString); GL_IMPORT(false, PFNGLDRAWARRAYSPROC, glDrawArrays); GL_IMPORT(false, PFNGLBLENDFUNCPROC, glBlendFunc); +GL_IMPORT(false, PFNGLBLENDEQUATIONPROC, glBlendEquation); GL_IMPORT(false, PFNGLPOINTSIZEPROC, glPointSize); GL_IMPORT(false, PFNGLCULLFACEPROC, glCullFace); GL_IMPORT(false, PFNGLCLEARPROC, glClear); @@ -46,7 +47,9 @@ GL_IMPORT(false, PFNGLSTENCILOPPROC, glStencilOp); GL_IMPORT(false, PFNGLACTIVETEXTUREPROC, glActiveTexture); GL_IMPORT(false, PFNGLCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2D); +GL_IMPORT(false, PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2D); GL_IMPORT(false, PFNGLCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3D); +GL_IMPORT(false, PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3D); GL_IMPORT(false, PFNGLBINDBUFFERPROC, glBindBuffer); GL_IMPORT(false, PFNGLDELETEBUFFERSPROC, glDeleteBuffers); GL_IMPORT(false, PFNGLGENBUFFERSPROC, glGenBuffers); @@ -131,6 +134,9 @@ GL_IMPORT(true, PFNGLSTENCILFUNCSEPARATEPROC, glStencilFuncSeparate) GL_IMPORT(true, PFNGLSTENCILMASKSEPARATEPROC, glStencilMaskSeparate); GL_IMPORT(true, PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate); +GL_IMPORT(true, PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate); +GL_IMPORT(true, PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate); + #if BGFX_CONFIG_DEBUG_GREMEDY GL_IMPORT(true, PFNGLSTRINGMARKERGREMEDYPROC, glStringMarkerGREMEDY); GL_IMPORT(true, PFNGLFRAMETERMINATORGREMEDYPROC, glFrameTerminatorGREMEDY); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 615e917d6..b194b33d5 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -111,17 +111,27 @@ namespace bgfx uint8_t m_bpp; }; +#ifndef DXGI_FORMAT_B4G4R4A4_UNORM +// Win8 only BS +// https://blogs.msdn.com/b/chuckw/archive/2012/11/14/directx-11-1-and-windows-7.aspx?Redirected=true +// http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx +# define DXGI_FORMAT_B4G4R4A4_UNORM DXGI_FORMAT(115) +#endif // DXGI_FORMAT_B4G4R4A4_UNORM + static const TextureFormatInfo s_textureFormat[TextureFormat::Count] = { - { DXGI_FORMAT_BC1_UNORM, 1 }, - { DXGI_FORMAT_BC2_UNORM, 1 }, - { DXGI_FORMAT_BC3_UNORM, 1 }, - { DXGI_FORMAT_UNKNOWN, 0 }, - { DXGI_FORMAT_R8_UNORM, 1 }, - { DXGI_FORMAT_B8G8R8A8_UNORM, 4 }, - { DXGI_FORMAT_B8G8R8A8_UNORM, 4 }, - { DXGI_FORMAT_R16G16B16A16_FLOAT, 8 }, - { DXGI_FORMAT_B5G6R5_UNORM, 2 }, + { DXGI_FORMAT_BC1_UNORM, 4 }, + { DXGI_FORMAT_BC2_UNORM, 4 }, + { DXGI_FORMAT_BC3_UNORM, 4 }, + { DXGI_FORMAT_UNKNOWN, 0 }, + { DXGI_FORMAT_R8_UNORM, 8 }, + { DXGI_FORMAT_B8G8R8A8_UNORM, 32 }, + { DXGI_FORMAT_B8G8R8A8_UNORM, 32 }, + { DXGI_FORMAT_R16G16B16A16_FLOAT, 64 }, + { DXGI_FORMAT_B5G6R5_UNORM, 16 }, + { DXGI_FORMAT_B4G4R4A4_UNORM, 16 }, + { DXGI_FORMAT_B5G5R5A1_UNORM, 16 }, + { DXGI_FORMAT_R10G10B10A2_UNORM, 32 }, }; static const D3D11_INPUT_ELEMENT_DESC s_attrib[Attrib::Count] = @@ -205,6 +215,11 @@ namespace bgfx struct TextureStage { TextureStage() + { + clear(); + } + + void clear() { memset(m_srv, 0, sizeof(m_srv) ); memset(m_sampler, 0, sizeof(m_sampler) ); @@ -214,6 +229,23 @@ namespace bgfx ID3D11SamplerState* m_sampler[BGFX_STATE_TEX_COUNT]; }; + static const GUID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, { 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 } }; + + template + static BX_NO_INLINE void setDebugObjectName(Ty* _interface, const char* _format, ...) + { +#if BGFX_CONFIG_DEBUG_OBJECT_NAME + char temp[2048]; + va_list argList; + va_start(argList, _format); + int size = uint32_min(sizeof(temp)-1, vsnprintf(temp, sizeof(temp), _format, argList) ); + va_end(argList); + temp[size] = '\0'; + + _interface->SetPrivateData(WKPDID_D3DDebugObjectName, size, temp); +#endif // BGFX_CONFIG_DEBUG_OBJECT_NAME + } + struct RendererContext { RendererContext() @@ -372,6 +404,9 @@ namespace bgfx DX_RELEASE(depthStencil, 0); m_deviceCtx->OMSetRenderTargets(1, &m_backBufferColor, m_backBufferDepthStencil); + + m_currentColor = m_backBufferColor; + m_currentDepthStencil = m_backBufferDepthStencil; } void flip() @@ -460,37 +495,40 @@ namespace bgfx if (_rt.idx == invalidHandle) { m_deviceCtx->OMSetRenderTargets(1, &m_backBufferColor, m_backBufferDepthStencil); + + m_currentColor = m_backBufferColor; + m_currentDepthStencil = m_backBufferDepthStencil; } else { + invalidateTextureStage(); + RenderTarget& renderTarget = m_renderTargets[_rt.idx]; - m_deviceCtx->OMSetRenderTargets(1, &renderTarget.m_rtv, m_backBufferDepthStencil); + m_deviceCtx->OMSetRenderTargets(1, &renderTarget.m_rtv, renderTarget.m_dsv); + + m_currentColor = renderTarget.m_rtv; + m_currentDepthStencil = renderTarget.m_dsv; } } void clear(const Clear& _clear) { -// DX_CHECK(s_renderCtx.m_device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE) ); -// DX_CHECK(s_renderCtx.m_device->SetScissorRect(&rc) ); - - if (BGFX_CLEAR_COLOR_BIT & _clear.m_flags) + if (NULL != m_currentColor + && BGFX_CLEAR_COLOR_BIT & _clear.m_flags) { uint32_t rgba = _clear.m_rgba; float frgba[4] = { (rgba>>24)/255.0f, ( (rgba>>16)&0xff)/255.0f, ( (rgba>>8)&0xff)/255.0f, (rgba&0xff)/255.0f }; -// DX_CHECK(s_renderCtx.m_device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED|D3DCOLORWRITEENABLE_GREEN|D3DCOLORWRITEENABLE_BLUE|D3DCOLORWRITEENABLE_ALPHA) ); - m_deviceCtx->ClearRenderTargetView(m_backBufferColor, frgba); + m_deviceCtx->ClearRenderTargetView(m_currentColor, frgba); } - if ( (BGFX_CLEAR_DEPTH_BIT|BGFX_CLEAR_STENCIL_BIT) & _clear.m_flags) + if (NULL != m_currentDepthStencil + && (BGFX_CLEAR_DEPTH_BIT|BGFX_CLEAR_STENCIL_BIT) & _clear.m_flags) { DWORD flags = 0; flags |= (_clear.m_flags & BGFX_CLEAR_DEPTH_BIT) ? D3D11_CLEAR_DEPTH : 0; flags |= (_clear.m_flags & BGFX_CLEAR_STENCIL_BIT) ? D3D11_CLEAR_STENCIL : 0; -// DX_CHECK(s_renderCtx.m_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE) ); - m_deviceCtx->ClearDepthStencilView(m_backBufferDepthStencil, flags, _clear.m_depth, _clear.m_stencil); + m_deviceCtx->ClearDepthStencilView(m_currentDepthStencil, flags, _clear.m_depth, _clear.m_stencil); } - -// DX_CHECK(s_renderCtx.m_device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE) ); } void setInputLayout(const VertexDecl& _vertexDecl, const Program& _program, uint8_t _numInstanceData) @@ -513,7 +551,6 @@ namespace bgfx decl.m_attributes[ii] = attr == 0 ? 0xff : attr == 0xff ? 0 : attr; } - D3D11_INPUT_ELEMENT_DESC* elem = fillVertexDecl(vertexElements, Attrib::Count, decl); ptrdiff_t num = elem-vertexElements; @@ -638,7 +675,7 @@ namespace bgfx DX_CHECK(m_device->CreateDepthStencilState(&desc, &dss) ); - m_depthStencilStateCache.add(_state, dss); + m_depthStencilStateCache.add(hash, dss); } m_deviceCtx->OMSetDepthStencilState(dss, ref); @@ -661,12 +698,19 @@ namespace bgfx ID3D11RasterizerState* rs = m_rasterizerStateCache.find(_state); if (NULL == rs) { - D3D11_RASTERIZER_DESC desc; - memset(&desc, 0, sizeof(desc) ); - desc.FillMode = _wireframe ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID; - uint32_t cull = (_state&BGFX_STATE_CULL_MASK)>>BGFX_STATE_CULL_SHIFT; + + D3D11_RASTERIZER_DESC desc; + desc.FillMode = _wireframe ? D3D11_FILL_WIREFRAME : D3D11_FILL_SOLID; desc.CullMode = s_cullMode[cull]; + desc.FrontCounterClockwise = false; + desc.DepthBias = 0; + desc.DepthBiasClamp = 0.0f; + desc.SlopeScaledDepthBias = 0.0f; + desc.DepthClipEnable = false; + desc.ScissorEnable = false; + desc.MultisampleEnable = false; + desc.AntialiasedLineEnable = false; DX_CHECK(m_device->CreateRasterizerState(&desc, &rs) ); @@ -682,6 +726,12 @@ namespace bgfx m_deviceCtx->PSSetSamplers(0, BGFX_STATE_TEX_COUNT, m_textureStage.m_sampler); } + void invalidateTextureStage() + { + m_textureStage.clear(); + commitTextureStage(); + } + void saveScreenShot(Memory* _mem) { ID3D11Texture2D* backBuffer; @@ -704,7 +754,7 @@ namespace bgfx { if (backBufferDesc.SampleDesc.Count == 1) { - m_deviceCtx->CopyResource(texture, backBuffer); + m_deviceCtx->CopyResource(texture, backBuffer); } else { @@ -715,8 +765,8 @@ namespace bgfx if (SUCCEEDED(hr) ) { m_deviceCtx->ResolveSubresource(resolve, 0, backBuffer, 0, desc.Format); - m_deviceCtx->CopyResource(texture, resolve); - DX_RELEASE(resolve, 0); + m_deviceCtx->CopyResource(texture, resolve); + DX_RELEASE(resolve, 0); } } @@ -737,6 +787,8 @@ namespace bgfx ID3D11DeviceContext* m_deviceCtx; ID3D11RenderTargetView* m_backBufferColor; ID3D11DepthStencilView* m_backBufferDepthStencil; + ID3D11RenderTargetView* m_currentColor; + ID3D11DepthStencilView* m_currentDepthStencil; bool m_wireframe; @@ -1059,25 +1111,28 @@ namespace bgfx uint32_t m_abgr; } * vertex = (Vertex*)m_vb->data; + const uint32_t abgr = bx::endianSwap(_clear.m_rgba); + const float depth = _clear.m_depth; + vertex->m_x = -1.0f; vertex->m_y = -1.0f; - vertex->m_z = _clear.m_depth; - vertex->m_abgr = bx::endianSwap(_clear.m_rgba); + vertex->m_z = depth; + vertex->m_abgr = abgr; vertex++; vertex->m_x = 1.0f; vertex->m_y = -1.0f; - vertex->m_z = _clear.m_depth; - vertex->m_abgr = bx::endianSwap(_clear.m_rgba); + vertex->m_z = depth; + vertex->m_abgr = abgr; vertex++; vertex->m_x = 1.0f; vertex->m_y = 1.0f; - vertex->m_z = _clear.m_depth; - vertex->m_abgr = bx::endianSwap(_clear.m_rgba); + vertex->m_z = depth; + vertex->m_abgr = abgr; vertex++; vertex->m_x = -1.0f; vertex->m_y = 1.0f; - vertex->m_z = _clear.m_depth; - vertex->m_abgr = bx::endianSwap(_clear.m_rgba); + vertex->m_z = depth; + vertex->m_abgr = abgr; } s_renderCtx.m_vertexBuffers[m_vb->handle.idx].update(0, 4*m_decl.m_stride, m_vb->data); @@ -1094,17 +1149,21 @@ namespace bgfx void Shader::create(bool _fragment, const Memory* _mem) { - m_constantBuffer = ConstantBuffer::create(1024); + bx::MemoryReader reader(_mem->data, _mem->size); - StreamRead stream(_mem->data, _mem->size); + uint32_t magic; + bx::read(&reader, magic); - stream.read(m_attrMask, sizeof(m_attrMask) ); + uint32_t iohash; + bx::read(&reader, iohash); + + bx::read(&reader, m_attrMask, sizeof(m_attrMask) ); uint16_t count; - stream.read(count); + bx::read(&reader, count); uint16_t size; - stream.read(size); + bx::read(&reader, size); if (0 < size) { @@ -1125,70 +1184,75 @@ namespace bgfx uint8_t fragmentBit = _fragment ? BGFX_UNIFORM_FRAGMENTBIT : 0; - for (uint32_t ii = 0; ii < count; ++ii) + if (0 < count) { - uint8_t nameSize; - stream.read(nameSize); + m_constantBuffer = ConstantBuffer::create(1024); - char name[256]; - stream.read(&name, nameSize); - name[nameSize] = '\0'; - - uint8_t type; - stream.read(type); - - uint8_t num; - stream.read(num); - - uint16_t regIndex; - stream.read(regIndex); - - uint16_t regCount; - stream.read(regCount); - - const char* kind = "invalid"; - - const void* data = NULL; - PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name); - if (PredefinedUniform::Count != predefined) + for (uint32_t ii = 0; ii < count; ++ii) { - kind = "predefined"; - m_predefined[m_numPredefined].m_loc = regIndex; - m_predefined[m_numPredefined].m_count = regCount; - m_predefined[m_numPredefined].m_type = predefined|fragmentBit; - m_numPredefined++; - } - else - { - const UniformInfo* info = s_renderCtx.m_uniformReg.find(name); - UniformBuffer* uniform = info != NULL ? (UniformBuffer*)info->m_data : NULL; + uint8_t nameSize; + bx::read(&reader, nameSize); - if (NULL != uniform) + char name[256]; + bx::read(&reader, &name, nameSize); + name[nameSize] = '\0'; + + uint8_t type; + bx::read(&reader, type); + + uint8_t num; + bx::read(&reader, num); + + uint16_t regIndex; + bx::read(&reader, regIndex); + + uint16_t regCount; + bx::read(&reader, regCount); + + const char* kind = "invalid"; + + const void* data = NULL; + PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name); + if (PredefinedUniform::Count != predefined) { - kind = "user"; - data = uniform->m_data; - m_constantBuffer->writeUniformRef( (UniformType::Enum)(type|fragmentBit), regIndex, data, regCount); + kind = "predefined"; + m_predefined[m_numPredefined].m_loc = regIndex; + m_predefined[m_numPredefined].m_count = regCount; + m_predefined[m_numPredefined].m_type = predefined|fragmentBit; + m_numPredefined++; } + else + { + const UniformInfo* info = s_renderCtx.m_uniformReg.find(name); + UniformBuffer* uniform = info != NULL ? (UniformBuffer*)info->m_data : NULL; + + if (NULL != uniform) + { + kind = "user"; + data = uniform->m_data; + m_constantBuffer->writeUniformRef( (UniformType::Enum)(type|fragmentBit), regIndex, data, regCount); + } + } + + BX_TRACE("\t%s: %s, type %2d, num %2d, r.index %3d, r.count %2d" + , kind + , name + , type + , num + , regIndex + , regCount + ); + BX_UNUSED(kind); } - BX_TRACE("\t%s: %s, type %2d, num %2d, r.index %3d, r.count %2d" - , kind - , name - , type - , num - , regIndex - , regCount - ); - BX_UNUSED(kind); + m_constantBuffer->finish(); } uint16_t shaderSize; - stream.read(shaderSize); + bx::read(&reader, shaderSize); - m_constantBuffer->finish(); - - const DWORD* code = (const DWORD*)stream.getDataPtr(); - stream.skip(shaderSize); + const DWORD* code = (const DWORD*)reader.getDataPtr(); + bx::skip(&reader, shaderSize); if (_fragment) { @@ -1196,7 +1260,7 @@ namespace bgfx } else { - m_hash = hash(code, shaderSize); + m_hash = hashMurmur2A(code, shaderSize); m_code = alloc(shaderSize); memcpy(m_code->data, code, shaderSize); @@ -1234,8 +1298,6 @@ namespace bgfx if (parseDds(dds, _mem) ) { - uint8_t bpp = dds.m_bpp; - bool decompress = false; if (dds.m_cubeMap) @@ -1281,16 +1343,16 @@ namespace bgfx { if (convert) { - uint8_t* temp = (uint8_t*)g_realloc(NULL, mip.m_width*bpp*mip.m_height); + uint8_t* temp = (uint8_t*)g_realloc(NULL, mip.m_width*bpp*mip.m_height/8); mip.decode(temp); srd[kk].pSysMem = temp; - srd[kk].SysMemPitch = mip.m_width*bpp; + srd[kk].SysMemPitch = mip.m_width*bpp/8; } else { srd[kk].pSysMem = mip.m_data; - srd[kk].SysMemPitch = mip.m_width*mip.m_bpp; + srd[kk].SysMemPitch = mip.m_width*mip.m_bpp/8; } srd[kk].SysMemSlicePitch = mip.m_height*srd[kk].SysMemPitch; @@ -1320,7 +1382,7 @@ namespace bgfx } else { - srd[kk].SysMemPitch = mip.m_width*mip.m_bpp; + srd[kk].SysMemPitch = mip.m_width*mip.m_bpp/8; srd[kk].SysMemSlicePitch = mip.m_height*srd[kk].SysMemPitch; } @@ -1407,22 +1469,22 @@ namespace bgfx } else { - StreamRead stream(_mem->data, _mem->size); + bx::MemoryReader reader(_mem->data, _mem->size); uint32_t magic; - stream.read(magic); + bx::read(&reader, magic); - if (BGFX_MAGIC == magic) + if (BGFX_CHUNK_MAGIC_TEX == magic) { TextureCreate tc; - stream.read(tc); + bx::read(&reader, tc); D3D11_TEXTURE2D_DESC desc; desc.Width = tc.m_width; desc.Height = tc.m_height; desc.MipLevels = tc.m_numMips; desc.ArraySize = 1; - desc.Format = s_textureFormat[tc.m_type].m_fmt; + desc.Format = s_textureFormat[tc.m_format].m_fmt; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; @@ -1436,14 +1498,14 @@ namespace bgfx desc.Usage = D3D11_USAGE_IMMUTABLE; D3D11_SUBRESOURCE_DATA* srd = (D3D11_SUBRESOURCE_DATA*)alloca(tc.m_numMips*sizeof(D3D11_SUBRESOURCE_DATA) ); - uint32_t bpp = s_textureFormat[tc.m_type].m_bpp; + uint32_t bpp = s_textureFormat[tc.m_format].m_bpp; uint8_t* data = tc.m_mem->data; for (uint8_t side = 0, numSides = tc.m_cubeMap ? 6 : 1; side < numSides; ++side) { uint32_t width = tc.m_width; uint32_t height = tc.m_height; - uint32_t depth = tc.m_depth; + uint32_t depth = tc.m_depth; for (uint32_t lod = 0, num = tc.m_numMips; lod < num; ++lod) { @@ -1452,14 +1514,14 @@ namespace bgfx depth = uint32_max(1, depth); srd[lod].pSysMem = data; - srd[lod].SysMemPitch = width*bpp; + srd[lod].SysMemPitch = width*bpp/8; srd[lod].SysMemSlicePitch = 0; - data += width*height*bpp; + data += width*height*bpp/8; width >>= 1; height >>= 1; - depth >>= 1; + depth >>= 1; } } @@ -1493,16 +1555,16 @@ namespace bgfx s_renderCtx.m_textureStage.m_sampler[_stage] = m_sampler; } - void Texture::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, const Memory* _mem) - { + void Texture::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, const Memory* _mem) + { ID3D11DeviceContext* deviceCtx = s_renderCtx.m_deviceCtx; - D3D11_BOX box; - box.left = _rect.m_x; - box.top = _rect.m_y; - box.right = box.left + _rect.m_width; + D3D11_BOX box; + box.left = _rect.m_x; + box.top = _rect.m_y; + box.right = box.left + _rect.m_width; box.bottom = box.top + _rect.m_height; - box.front = _z; + box.front = _z; box.back = box.front + _depth; uint32_t subres = _mip + (_side * m_numMips); @@ -1523,7 +1585,7 @@ namespace bgfx #else deviceCtx->UpdateSubresource(m_ptr, subres, &box, _mem->data, _rect.m_width, 0); #endif // 0 - } + } void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) { @@ -1532,6 +1594,7 @@ namespace bgfx m_flags = _flags; uint32_t colorFormat = (m_flags&BGFX_RENDER_TARGET_COLOR_MASK)>>BGFX_RENDER_TARGET_COLOR_SHIFT; + uint32_t depthFormat = (m_flags&BGFX_RENDER_TARGET_DEPTH_MASK)>>BGFX_RENDER_TARGET_DEPTH_SHIFT; D3D11_TEXTURE2D_DESC desc; desc.Width = _width; @@ -1550,6 +1613,26 @@ namespace bgfx DX_CHECK(s_renderCtx.m_device->CreateRenderTargetView(m_colorTexture, NULL, &m_rtv) ); DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(m_colorTexture, NULL, &m_srv) ); + if (0 < depthFormat) + { + D3D11_TEXTURE2D_DESC desc; + desc.Width = _width; + desc.Height = _height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = s_depthFormat[colorFormat]; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, NULL, &m_depthTexture) ); + DX_CHECK(s_renderCtx.m_device->CreateDepthStencilView(m_depthTexture, NULL, &m_dsv) ); +// DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(m_depthTexture, NULL, &m_srv) ); + } + m_sampler = s_renderCtx.m_samplerStateCache.find(_flags); if (NULL == m_sampler) { @@ -1578,6 +1661,8 @@ namespace bgfx DX_RELEASE(m_srv, 0); DX_RELEASE(m_rtv, 0); DX_RELEASE(m_colorTexture, 0); + DX_RELEASE(m_dsv, 0); + DX_RELEASE(m_depthTexture, 0); m_flags = 0; } @@ -1889,8 +1974,7 @@ namespace bgfx s_renderCtx.setDepthStencilState(newFlags, newStencil); } - if ( (BGFX_STATE_CULL_MASK - |BGFX_STATE_ALPHA_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE + if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_ALPHA_MASK|BGFX_STATE_RGB_WRITE |BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK |BGFX_STATE_POINT_SIZE_MASK|BGFX_STATE_SRGBWRITE|BGFX_STATE_MSAA) & changedFlags) { @@ -1904,6 +1988,12 @@ namespace bgfx s_renderCtx.setRasterizerState(newFlags, wireframe); } + if ( (BGFX_STATE_ALPHA_TEST|BGFX_STATE_ALPHA_REF_MASK) & changedFlags) + { + uint32_t ref = (newFlags&BGFX_STATE_ALPHA_REF_MASK)>>BGFX_STATE_ALPHA_REF_SHIFT; + alphaRef = ref/255.0f; + } + uint8_t primIndex = uint8_t( (newFlags&BGFX_STATE_PT_MASK)>>BGFX_STATE_PT_SHIFT); if (primType != s_primType[primIndex]) { @@ -1950,8 +2040,7 @@ namespace bgfx if (constantsChanged) { - program.m_vsh->m_constantBuffer->commit(); - program.m_fsh->m_constantBuffer->commit(); + program.commit(); } for (uint32_t ii = 0, num = program.m_numPredefined; ii < num; ++ii) diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index fb23f4df8..162eeb787 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -199,6 +199,19 @@ namespace bgfx m_fsh = NULL; } + void commit() + { + if (NULL != m_vsh->m_constantBuffer) + { + m_vsh->m_constantBuffer->commit(); + } + + if (NULL != m_fsh->m_constantBuffer) + { + m_fsh->m_constantBuffer->commit(); + } + } + const Shader* m_vsh; const Shader* m_fsh; @@ -224,10 +237,6 @@ namespace bgfx { } -// void createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips, D3DFORMAT _fmt); -// void createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _numMips, D3DFORMAT _fmt); -// void createCubeTexture(uint32_t _edge, uint32_t _numMips, D3DFORMAT _fmt); - void create(const Memory* _mem, uint32_t _flags); void destroy() @@ -236,14 +245,14 @@ namespace bgfx DX_RELEASE(m_ptr, 1); } - void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, const Memory* _mem); + void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, const Memory* _mem); void commit(uint8_t _stage); union { ID3D11Resource* m_ptr; ID3D11Texture2D* m_texture2d; - ID3D11Texture3D* m_texture3d; + ID3D11Texture3D* m_texture3d; }; ID3D11ShaderResourceView* m_srv; @@ -256,15 +265,14 @@ namespace bgfx struct RenderTarget { RenderTarget() - : -// m_rt(NULL) -// , m_colorTexture(NULL) -// , m_color(NULL) -// , m_depthTexture(NULL) -// , m_depth(NULL) + : m_colorTexture(NULL) + , m_depthTexture(NULL) + , m_rtv(NULL) + , m_dsv(NULL) + , m_srv(NULL) // , m_minFilter(D3DTEXF_LINEAR) // , m_magFilter(D3DTEXF_LINEAR) - m_width(0) + , m_width(0) , m_height(0) , m_flags(0) , m_depthOnly(false) @@ -287,7 +295,9 @@ namespace bgfx // D3DTEXTUREFILTERTYPE m_magFilter; ID3D11Texture2D* m_colorTexture; + ID3D11Texture2D* m_depthTexture; ID3D11RenderTargetView* m_rtv; + ID3D11DepthStencilView* m_dsv; ID3D11ShaderResourceView* m_srv; ID3D11SamplerState* m_sampler; uint16_t m_width; diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 5aad557e9..30d9e8453 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -171,15 +171,18 @@ namespace bgfx static const TextureFormatInfo s_textureFormat[TextureFormat::Count] = { - { D3DFMT_DXT1, 1 }, - { D3DFMT_DXT3, 1 }, - { D3DFMT_DXT5, 1 }, - { D3DFMT_UNKNOWN, 0 }, - { D3DFMT_L8, 1 }, - { D3DFMT_X8R8G8B8, 4 }, - { D3DFMT_A8R8G8B8, 4 }, - { D3DFMT_A16B16G16R16, 8 }, - { D3DFMT_R5G6B5, 2 }, + { D3DFMT_DXT1, 4 }, + { D3DFMT_DXT3, 4 }, + { D3DFMT_DXT5, 4 }, + { D3DFMT_UNKNOWN, 0 }, + { D3DFMT_L8, 8 }, + { D3DFMT_X8R8G8B8, 32 }, + { D3DFMT_A8R8G8B8, 32 }, + { D3DFMT_A16B16G16R16, 64 }, + { D3DFMT_R5G6B5, 16 }, + { D3DFMT_A4R4G4B4, 16 }, + { D3DFMT_A1R5G5B5, 16 }, + { D3DFMT_A2B10G10R10, 32 }, }; static ExtendedFormat s_extendedFormats[ExtendedFormat::Count] = @@ -730,8 +733,8 @@ namespace bgfx point.y = rc.top; ClientToScreen(g_bgfxHwnd, &point); uint8_t* data = (uint8_t*)rect.pBits; - uint32_t bpp = rect.Pitch/dm.Width; - saveTga( (const char*)_mem->data, m_params.BackBufferWidth, m_params.BackBufferHeight, rect.Pitch, &data[point.y*rect.Pitch+point.x*bpp]); + uint32_t bytesPerPixel = rect.Pitch/dm.Width; + saveTga( (const char*)_mem->data, m_params.BackBufferWidth, m_params.BackBufferHeight, rect.Pitch, &data[point.y*rect.Pitch+point.x*bytesPerPixel]); DX_CHECK(surface->UnlockRect() ); DX_RELEASE(surface, 0); @@ -993,11 +996,16 @@ namespace bgfx void Shader::create(bool _fragment, const Memory* _mem) { - m_constantBuffer = ConstantBuffer::create(1024); + bx::MemoryReader reader(_mem->data, _mem->size); + + uint32_t magic; + bx::read(&reader, magic); + + uint32_t iohash; + bx::read(&reader, iohash); - StreamRead stream(_mem->data, _mem->size); uint16_t count; - stream.read(count); + bx::read(&reader, count); m_numPredefined = 0; @@ -1005,76 +1013,83 @@ namespace bgfx uint8_t fragmentBit = _fragment ? BGFX_UNIFORM_FRAGMENTBIT : 0; - for (uint32_t ii = 0; ii < count; ++ii) + if (0 < count) { - uint8_t nameSize; - stream.read(nameSize); + m_constantBuffer = ConstantBuffer::create(1024); - char name[256]; - stream.read(&name, nameSize); - name[nameSize] = '\0'; - - uint8_t type; - stream.read(type); - - uint8_t num; - stream.read(num); - - uint16_t regIndex; - stream.read(regIndex); - - uint16_t regCount; - stream.read(regCount); - - const char* kind = "invalid"; - - const void* data = NULL; - PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name); - if (PredefinedUniform::Count != predefined) + for (uint32_t ii = 0; ii < count; ++ii) { - kind = "predefined"; - m_predefined[m_numPredefined].m_loc = regIndex; - m_predefined[m_numPredefined].m_count = regCount; - m_predefined[m_numPredefined].m_type = predefined|fragmentBit; - m_numPredefined++; - } - else - { - const UniformInfo* info = s_renderCtx.m_uniformReg.find(name); - BX_CHECK(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name); - if (NULL != info) + uint8_t nameSize; + bx::read(&reader, nameSize); + + char name[256]; + bx::read(&reader, &name, nameSize); + name[nameSize] = '\0'; + + uint8_t type; + bx::read(&reader, type); + + uint8_t num; + bx::read(&reader, num); + + uint16_t regIndex; + bx::read(&reader, regIndex); + + uint16_t regCount; + bx::read(&reader, regCount); + + const char* kind = "invalid"; + + const void* data = NULL; + PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name); + if (PredefinedUniform::Count != predefined) { - kind = "user"; - data = info->m_data; - m_constantBuffer->writeUniformRef( (UniformType::Enum)(type|fragmentBit), regIndex, data, regCount); + kind = "predefined"; + m_predefined[m_numPredefined].m_loc = regIndex; + m_predefined[m_numPredefined].m_count = regCount; + m_predefined[m_numPredefined].m_type = predefined|fragmentBit; + m_numPredefined++; } + else + { + const UniformInfo* info = s_renderCtx.m_uniformReg.find(name); + BX_CHECK(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name); + if (NULL != info) + { + kind = "user"; + data = info->m_data; + m_constantBuffer->writeUniformRef( (UniformType::Enum)(type|fragmentBit), regIndex, data, regCount); + } + } + + BX_TRACE("\t%s: %s, type %2d, num %2d, r.index %3d, r.count %2d" + , kind + , name + , type + , num + , regIndex + , regCount + ); + BX_UNUSED(kind); } - BX_TRACE("\t%s: %s, type %2d, num %2d, r.index %3d, r.count %2d" - , kind - , name - , type - , num - , regIndex - , regCount - ); - BX_UNUSED(kind); + m_constantBuffer->finish(); } uint16_t shaderSize; - stream.read(shaderSize); + bx::read(&reader, shaderSize); - m_constantBuffer->finish(); - - const DWORD* code = (const DWORD*)stream.getDataPtr(); + const DWORD* code = (const DWORD*)reader.getDataPtr(); if (_fragment) { DX_CHECK(s_renderCtx.m_device->CreatePixelShader(code, (IDirect3DPixelShader9**)&m_ptr) ); + BX_CHECK(NULL != m_ptr, "Failed to create fragment shader."); } else { DX_CHECK(s_renderCtx.m_device->CreateVertexShader(code, (IDirect3DVertexShader9**)&m_ptr) ); + BX_CHECK(NULL != m_ptr, "Failed to create vertex shader."); } } @@ -1234,23 +1249,25 @@ namespace bgfx if (parseDds(dds, _mem) ) { - uint8_t bpp = dds.m_bpp; + const TextureFormatInfo& tfi = s_textureFormat[dds.m_type]; bool decompress = false; if (dds.m_cubeMap) { - createCubeTexture(dds.m_width, dds.m_numMips, s_textureFormat[dds.m_type].m_fmt); + createCubeTexture(dds.m_width, dds.m_numMips, tfi.m_fmt); } else if (dds.m_depth > 1) { - createVolumeTexture(dds.m_width, dds.m_height, dds.m_depth, dds.m_numMips, s_textureFormat[dds.m_type].m_fmt); + createVolumeTexture(dds.m_width, dds.m_height, dds.m_depth, dds.m_numMips, tfi.m_fmt); } else { - createTexture(dds.m_width, dds.m_height, dds.m_numMips, s_textureFormat[dds.m_type].m_fmt); + createTexture(dds.m_width, dds.m_height, dds.m_numMips, tfi.m_fmt); } + uint8_t bpp = tfi.m_bpp; + if (decompress || TextureFormat::Unknown < dds.m_type) { @@ -1276,7 +1293,7 @@ namespace bgfx if (width != mip.m_width || height != mip.m_height) { - uint32_t srcpitch = mip.m_width*bpp; + uint32_t srcpitch = mip.m_width*bpp/8; uint8_t* temp = (uint8_t*)g_realloc(NULL, srcpitch*mip.m_height); mip.decode(temp); @@ -1328,32 +1345,32 @@ namespace bgfx } else { - StreamRead stream(_mem->data, _mem->size); + bx::MemoryReader reader(_mem->data, _mem->size); uint32_t magic; - stream.read(magic); + bx::read(&reader, magic); - if (BGFX_MAGIC == magic) + if (BGFX_CHUNK_MAGIC_TEX == magic) { TextureCreate tc; - stream.read(tc); + bx::read(&reader, tc); if (tc.m_cubeMap) { - createCubeTexture(tc.m_width, tc.m_numMips, s_textureFormat[tc.m_type].m_fmt); + createCubeTexture(tc.m_width, tc.m_numMips, s_textureFormat[tc.m_format].m_fmt); } else if (tc.m_depth > 1) { - createVolumeTexture(tc.m_width, tc.m_height, tc.m_depth, tc.m_numMips, s_textureFormat[tc.m_type].m_fmt); + createVolumeTexture(tc.m_width, tc.m_height, tc.m_depth, tc.m_numMips, s_textureFormat[tc.m_format].m_fmt); } else { - createTexture(tc.m_width, tc.m_height, tc.m_numMips, s_textureFormat[tc.m_type].m_fmt); + createTexture(tc.m_width, tc.m_height, tc.m_numMips, s_textureFormat[tc.m_format].m_fmt); } if (NULL != tc.m_mem) { - uint32_t bpp = s_textureFormat[tc.m_type].m_bpp; + uint32_t bpp = s_textureFormat[tc.m_format].m_bpp; uint8_t* data = tc.m_mem->data; for (uint8_t side = 0, numSides = tc.m_cubeMap ? 6 : 1; side < numSides; ++side) @@ -1371,7 +1388,7 @@ namespace bgfx uint32_t pitch; uint32_t slicePitch; uint8_t* dst = lock(side, lod, pitch, slicePitch); - uint32_t len = width*height*bpp; + uint32_t len = width*height*bpp/8; memcpy(dst, data, len); data += len; unlock(side, lod); @@ -1956,7 +1973,6 @@ namespace bgfx PIX_BEGINEVENT(D3DCOLOR_RGBA(0xff, 0x00, 0x00, 0xff), "view"); view = key.m_view; - programIdx = invalidHandle; if (m_render->m_rt[view].idx != rt.idx) @@ -2080,9 +2096,9 @@ namespace bgfx } if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK - |BGFX_STATE_ALPHA_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE - |BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK - |BGFX_STATE_POINT_SIZE_MASK|BGFX_STATE_SRGBWRITE|BGFX_STATE_MSAA) & changedFlags) + |BGFX_STATE_ALPHA_MASK|BGFX_STATE_RGB_WRITE|BGFX_STATE_BLEND_MASK + |BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK|BGFX_STATE_POINT_SIZE_MASK + |BGFX_STATE_SRGBWRITE|BGFX_STATE_MSAA) & changedFlags) { if (BGFX_STATE_CULL_MASK & changedFlags) { @@ -2192,8 +2208,7 @@ namespace bgfx if (constantsChanged) { - program.m_vsh->m_constantBuffer->commit(); - program.m_fsh->m_constantBuffer->commit(); + program.commit(); } for (uint32_t ii = 0, num = program.m_numPredefined; ii < num; ++ii) diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index 3fc343728..d91a388a8 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -71,43 +71,43 @@ namespace bgfx #endif // BGFX_CONFIG_DEBUG_PIX # ifndef D3DFMT_ATI1 -# define D3DFMT_ATI1 ( (D3DFORMAT)MAKEFOURCC('A','T','I','1') ) +# define D3DFMT_ATI1 ( (D3DFORMAT)BX_MAKEFOURCC('A','T','I','1') ) # endif // D3DFMT_ATI1 # ifndef D3DFMT_ATI2 -# define D3DFMT_ATI2 ( (D3DFORMAT)MAKEFOURCC('A','T','I','2') ) +# define D3DFMT_ATI2 ( (D3DFORMAT)BX_MAKEFOURCC('A','T','I','2') ) # endif // D3DFMT_ATI2 # ifndef D3DFMT_ATOC -# define D3DFMT_ATOC ( (D3DFORMAT)MAKEFOURCC('A','T','O','C') ) +# define D3DFMT_ATOC ( (D3DFORMAT)BX_MAKEFOURCC('A','T','O','C') ) # endif // D3DFMT_ATOC # ifndef D3DFMT_DF16 -# define D3DFMT_DF16 ( (D3DFORMAT)MAKEFOURCC('D','F','1','6') ) +# define D3DFMT_DF16 ( (D3DFORMAT)BX_MAKEFOURCC('D','F','1','6') ) # endif // D3DFMT_DF16 # ifndef D3DFMT_DF24 -# define D3DFMT_DF24 ( (D3DFORMAT)MAKEFOURCC('D','F','2','4') ) +# define D3DFMT_DF24 ( (D3DFORMAT)BX_MAKEFOURCC('D','F','2','4') ) # endif // D3DFMT_DF24 # ifndef D3DFMT_INST -# define D3DFMT_INST ( (D3DFORMAT)MAKEFOURCC('I','N','S','T') ) +# define D3DFMT_INST ( (D3DFORMAT)BX_MAKEFOURCC('I','N','S','T') ) # endif // D3DFMT_INST # ifndef D3DFMT_INTZ -# define D3DFMT_INTZ ( (D3DFORMAT)MAKEFOURCC('I','N','T','Z') ) +# define D3DFMT_INTZ ( (D3DFORMAT)BX_MAKEFOURCC('I','N','T','Z') ) # endif // D3DFMT_INTZ # ifndef D3DFMT_NULL -# define D3DFMT_NULL ( (D3DFORMAT)MAKEFOURCC('N','U','L','L') ) +# define D3DFMT_NULL ( (D3DFORMAT)BX_MAKEFOURCC('N','U','L','L') ) # endif // D3DFMT_NULL # ifndef D3DFMT_RESZ -# define D3DFMT_RESZ ( (D3DFORMAT)MAKEFOURCC('R','E','S','Z') ) +# define D3DFMT_RESZ ( (D3DFORMAT)BX_MAKEFOURCC('R','E','S','Z') ) # endif // D3DFMT_RESZ # ifndef D3DFMT_RAWZ -# define D3DFMT_RAWZ ( (D3DFORMAT)MAKEFOURCC('R','A','W','Z') ) +# define D3DFMT_RAWZ ( (D3DFORMAT)BX_MAKEFOURCC('R','A','W','Z') ) # endif // D3DFMT_RAWZ struct ExtendedFormat @@ -280,6 +280,19 @@ namespace bgfx m_fsh = NULL; } + void commit() + { + if (NULL != m_vsh->m_constantBuffer) + { + m_vsh->m_constantBuffer->commit(); + } + + if (NULL != m_fsh->m_constantBuffer) + { + m_fsh->m_constantBuffer->commit(); + } + } + const Shader* m_vsh; const Shader* m_fsh; diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 47397cb4e..408e9aa4f 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -19,6 +19,9 @@ # define glGetProgramBinary glGetProgramBinaryOES # define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES # define GL_HALF_FLOAT GL_HALF_FLOAT_OES +# define GL_RGB10_A2 GL_RGB10_A2_EXT +# define GL_UNSIGNED_INT_2_10_10_10_REV GL_UNSIGNED_INT_2_10_10_10_REV_EXT +# define GL_SAMPLER_3D GL_SAMPLER_3D_OES #endif // BGFX_CONFIG_RENDERER_OPENGLES2 namespace bgfx @@ -617,13 +620,19 @@ namespace bgfx EXT_texture_compression_dxt1, CHROMIUM_texture_compression_dxt3, CHROMIUM_texture_compression_dxt5, + ARB_texture_float, + OES_texture_float, + OES_texture_float_linear, + OES_texture_half_float, + OES_texture_half_float_linear, + EXT_texture_type_2_10_10_10_REV, + EXT_texture_sRGB, OES_standard_derivatives, ARB_get_program_binary, OES_get_program_binary, EXT_framebuffer_blit, ARB_timer_query, EXT_timer_query, - EXT_texture_sRGB, ARB_framebuffer_sRGB, EXT_framebuffer_sRGB, ARB_multisample, @@ -631,11 +640,6 @@ namespace bgfx ANGLE_translated_shader_source, ARB_instanced_arrays, ANGLE_instanced_arrays, - ARB_texture_float, - OES_texture_float, - OES_texture_float_linear, - OES_texture_half_float, - OES_texture_half_float_linear, ARB_half_float_vertex, OES_vertex_half_float, ARB_vertex_type_2_10_10_10_rev, @@ -662,13 +666,19 @@ namespace bgfx { "GL_EXT_texture_compression_dxt1", false, true }, { "GL_CHROMIUM_texture_compression_dxt3", false, true }, { "GL_CHROMIUM_texture_compression_dxt5", false, true }, + { "GL_ARB_texture_float", false, true }, + { "GL_OES_texture_float", false, true }, + { "GL_OES_texture_float_linear", false, true }, + { "GL_OES_texture_half_float", false, true }, + { "GL_OES_texture_half_float_linear", false, true }, + { "GL_EXT_texture_type_2_10_10_10_REV", false, true }, + { "GL_EXT_texture_sRGB", false, true }, { "GL_OES_standard_derivatives", false, true }, { "GL_ARB_get_program_binary", false, true }, { "GL_OES_get_program_binary", false, false }, { "GL_EXT_framebuffer_blit", false, true }, { "GL_ARB_timer_query", false, true }, { "GL_EXT_timer_query", false, true }, - { "GL_EXT_texture_sRGB", false, true }, { "GL_ARB_framebuffer_sRGB", false, true }, { "GL_EXT_framebuffer_sRGB", false, true }, { "GL_ARB_multisample", false, true }, @@ -676,11 +686,6 @@ namespace bgfx { "GL_ANGLE_translated_shader_source", false, true }, { "GL_ARB_instanced_arrays", false, true }, { "GL_ANGLE_instanced_arrays", false, true }, - { "GL_ARB_texture_float", false, true }, - { "GL_OES_texture_float", false, true }, - { "GL_OES_texture_float_linear", false, true }, - { "GL_OES_texture_half_float", false, true }, - { "GL_OES_texture_half_float_linear", false, true }, { "GL_ARB_half_float_vertex", false, true }, { "GL_OES_vertex_half_float", false, true }, { "GL_ARB_vertex_type_2_10_10_10_rev", false, true }, @@ -841,19 +846,22 @@ namespace bgfx static const TextureFormatInfo s_textureFormat[TextureFormat::Count] = { - { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, GL_ZERO, 4 }, - { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, GL_ZERO, 4 }, - { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, GL_ZERO, 4 }, - { GL_ZERO, GL_ZERO, GL_ZERO, 0 }, - { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 }, + { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, 4 }, + { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, 4 }, + { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, 4 }, + { GL_ZERO, GL_ZERO, GL_ZERO, 0 }, + { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8 }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32 }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32 }, #if BGFX_CONFIG_RENDERER_OPENGL - { GL_RGBA16, GL_RGBA, GL_HALF_FLOAT, 8 }, + { GL_RGBA16, GL_RGBA, GL_HALF_FLOAT, 64 }, #else - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 8 }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 64 }, #endif // BGFX_CONFIG_RENDERER_OPENGL - { GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 2 }, + { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16 }, + { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16 }, + { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16 }, + { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, 32 }, }; const char* glslTypeName(GLuint _type) @@ -877,7 +885,7 @@ namespace bgfx // GLSL_TYPE(GL_FLOAT_MAT4x3); // GLSL_TYPE(GL_SAMPLER_1D); GLSL_TYPE(GL_SAMPLER_2D); -// GLSL_TYPE(GL_SAMPLER_3D); + GLSL_TYPE(GL_SAMPLER_3D); GLSL_TYPE(GL_SAMPLER_CUBE); // GLSL_TYPE(GL_SAMPLER_1D_SHADOW); // GLSL_TYPE(GL_SAMPLER_2D_SHADOW); @@ -936,10 +944,10 @@ namespace bgfx // case GL_FLOAT_MAT4x3: // break; - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: // case GL_SAMPLER_1D: -// case GL_SAMPLER_3D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: // case GL_SAMPLER_1D_SHADOW: // case GL_SAMPLER_2D_SHADOW: return UniformType::Uniform1iv; @@ -969,12 +977,12 @@ namespace bgfx void* data = g_realloc(NULL, length); g_cache(id, false, data, length); - StreamRead stream(data, length); + bx::MemoryReader reader(data, length); GLenum format; - stream.read(format); + bx::read(&reader, format); - GL_CHECK(glProgramBinary(m_id, format, stream.getDataPtr(), stream.remaining() ) ); + GL_CHECK(glProgramBinary(m_id, format, reader.getDataPtr(), (GLsizei)reader.remaining() ) ); g_free(data); } @@ -1347,7 +1355,7 @@ namespace bgfx m_type = GL_UNSIGNED_BYTE; } - uint8_t* bits = (uint8_t*)g_realloc(NULL, dds.m_width*dds.m_height*tfi.m_bpp); + uint8_t* bits = (uint8_t*)g_realloc(NULL, dds.m_width*dds.m_height*tfi.m_bpp/8); for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side) { @@ -1406,6 +1414,8 @@ namespace bgfx } else { + m_compressed = true; + for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side) { uint32_t width = dds.m_width; @@ -1442,15 +1452,15 @@ namespace bgfx } else { - StreamRead stream(_mem->data, _mem->size); + bx::MemoryReader reader(_mem->data, _mem->size); uint32_t magic; - stream.read(magic); + bx::read(&reader, magic); - if (BGFX_MAGIC == magic) + if (BGFX_CHUNK_MAGIC_TEX == magic) { TextureCreate tc; - stream.read(tc); + bx::read(&reader, tc); if (tc.m_cubeMap) { @@ -1471,10 +1481,11 @@ namespace bgfx BX_CHECK(0 != m_id, "Failed to generate texture id."); GL_CHECK(glBindTexture(m_target, m_id) ); - const TextureFormatInfo& tfi = s_textureFormat[tc.m_type]; + const TextureFormatInfo& tfi = s_textureFormat[tc.m_format]; GLenum internalFmt = tfi.m_internalFmt; m_fmt = tfi.m_fmt; m_type = tfi.m_type; + m_compressed = tc.m_format < TextureFormat::Unknown; GLenum target = m_target; if (tc.m_cubeMap) @@ -1482,8 +1493,9 @@ namespace bgfx target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; } - uint32_t bpp = s_textureFormat[tc.m_type].m_bpp; + uint32_t bpp = tfi.m_bpp; uint8_t* data = NULL != tc.m_mem ? tc.m_mem->data : NULL; + uint32_t min = m_compressed ? 4 : 1; for (uint8_t side = 0, numSides = tc.m_cubeMap ? 6 : 1; side < numSides; ++side) { @@ -1493,25 +1505,42 @@ namespace bgfx for (uint32_t lod = 0, num = tc.m_numMips; lod < num; ++lod) { - width = uint32_max(width, 1); - height = uint32_max(height, 1); + width = uint32_max(width, min); + height = uint32_max(height, min); depth = uint32_max(1, depth); + uint32_t size = width*height*bpp/8; - texImage(target+side - , lod - , internalFmt - , width - , height - , depth - , 0 - , m_fmt - , m_type - , data - ); + if (m_compressed) + { + compressedTexImage(target+side + , lod + , internalFmt + , width + , height + , depth + , 0 + , size + , data + ); + } + else + { + texImage(target+side + , lod + , internalFmt + , width + , height + , depth + , 0 + , m_fmt + , m_type + , data + ); + } if (NULL != data) { - data += width*height*bpp; + data += size; } width >>= 1; @@ -1623,6 +1652,20 @@ namespace bgfx switch (m_target) { case GL_TEXTURE_2D: + if (m_compressed) + { + GL_CHECK(glCompressedTexSubImage2D(m_target + , _mip + , _rect.m_x + , _rect.m_y + , _rect.m_width + , _rect.m_height + , m_fmt + , _mem->size + , _mem->data + ) ); + } + else { GL_CHECK(glTexSubImage2D(m_target , _mip @@ -1638,6 +1681,20 @@ namespace bgfx break; case GL_TEXTURE_CUBE_MAP: + if (m_compressed) + { + GL_CHECK(glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+_side + , _mip + , _rect.m_x + , _rect.m_y + , _rect.m_width + , _rect.m_height + , m_fmt + , _mem->size + , _mem->data + ) ); + } + else { GL_CHECK(glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+_side , _mip @@ -1654,6 +1711,22 @@ namespace bgfx #if BGFX_CONFIG_RENDERER_OPENGL case GL_TEXTURE_3D: + if (m_compressed) + { + GL_CHECK(glCompressedTexSubImage3D(m_target + , _mip + , _rect.m_x + , _rect.m_y + , _z + , _rect.m_width + , _rect.m_height + , _depth + , m_fmt + , _mem->size + , _mem->data + ) ); + } + else { GL_CHECK(glTexSubImage3D(m_target , _mip @@ -2091,7 +2164,7 @@ namespace bgfx void Context::rendererCreateVertexShader(VertexShaderHandle _handle, Memory* _mem) { - s_renderCtx.m_vertexShaders[_handle.idx].create(GL_VERTEX_SHADER, _mem->data); + s_renderCtx.m_vertexShaders[_handle.idx].create(GL_VERTEX_SHADER, _mem); } void Context::rendererDestroyVertexShader(VertexShaderHandle _handle) @@ -2101,7 +2174,7 @@ namespace bgfx void Context::rendererCreateFragmentShader(FragmentShaderHandle _handle, Memory* _mem) { - s_renderCtx.m_fragmentShaders[_handle.idx].create(GL_FRAGMENT_SHADER, _mem->data); + s_renderCtx.m_fragmentShaders[_handle.idx].create(GL_FRAGMENT_SHADER, _mem); } void Context::rendererDestroyFragmentShader(FragmentShaderHandle _handle) @@ -2329,7 +2402,7 @@ namespace bgfx // if (BGFX_STENCIL_FUNC_RMASK_MASK & bchanged) // { // uint32_t wmask = (bstencil&BGFX_STENCIL_FUNC_RMASK_MASK)>>BGFX_STENCIL_FUNC_RMASK_SHIFT; -// BX_CHECK(glStencilMask(wmask) ); +// GL_CHECK(glStencilMask(wmask) ); // } for (uint32_t ii = 0, num = frontAndBack+1; ii < num; ++ii) @@ -2362,9 +2435,8 @@ namespace bgfx } if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK - |BGFX_STATE_ALPHA_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE - |BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK - |BGFX_STATE_POINT_SIZE_MASK) & changedFlags) + |BGFX_STATE_ALPHA_MASK|BGFX_STATE_RGB_WRITE|BGFX_STATE_BLEND_MASK + |BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK|BGFX_STATE_POINT_SIZE_MASK) & changedFlags) { if (BGFX_STATE_CULL_MASK & changedFlags) { @@ -2478,7 +2550,7 @@ namespace bgfx if (constantsChanged) { - program.m_constantBuffer->commit(); + program.commit(); } for (uint32_t ii = 0, num = program.m_numPredefined; ii < num; ++ii) diff --git a/src/renderer_gl.h b/src/renderer_gl.h index ecbf0f45b..a7695331c 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -325,6 +325,9 @@ namespace bgfx Texture() : m_id(0) , m_target(GL_TEXTURE_2D) + , m_fmt(GL_ZERO) + , m_type(GL_ZERO) + , m_compressed(false) { } @@ -338,19 +341,30 @@ namespace bgfx GLenum m_target; GLenum m_fmt; GLenum m_type; + bool m_compressed; }; struct Shader { - void create(GLenum _type, const uint8_t* _code) + void create(GLenum _type, Memory* _mem) { m_id = glCreateShader(_type); m_type = _type; + bx::MemoryReader reader(_mem->data, _mem->size); + m_hash = hashMurmur2A(_mem->data, _mem->size); + + uint32_t magic; + bx::read(&reader, magic); + + uint32_t hash; + bx::read(&reader, hash); + + const uint8_t* code = reader.getDataPtr(); + if (0 != m_id) { - m_hash = hash(_code, (uint32_t)strlen( (const char*)_code) ); - GL_CHECK(glShaderSource(m_id, 1, (const GLchar**)&_code, NULL) ); + GL_CHECK(glShaderSource(m_id, 1, (const GLchar**)&code, NULL) ); GL_CHECK(glCompileShader(m_id) ); GLint compiled = 0; @@ -361,9 +375,10 @@ namespace bgfx char log[1024]; GL_CHECK(glGetShaderInfoLog(m_id, sizeof(log), NULL, log) ); BX_TRACE("Failed to compile shader. %d: %s", compiled, log); - BX_TRACE("\n####\n%s\n####", _code); + BX_TRACE("\n####\n%s\n####", code); GL_CHECK(glDeleteShader(m_id) ); + BGFX_FATAL(false, bgfx::Fatal::InvalidShader, "Failed to compile shader."); } } } @@ -398,6 +413,11 @@ namespace bgfx void init(); void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const; void bindInstanceData(uint32_t _stride, uint32_t _baseVertex = 0) const; + + void commit() + { + m_constantBuffer->commit(); + } GLuint m_id; diff --git a/src/renderer_null.cpp b/src/renderer_null.cpp index 883755e85..d66829402 100644 --- a/src/renderer_null.cpp +++ b/src/renderer_null.cpp @@ -107,15 +107,15 @@ namespace bgfx void Context::rendererCreateTexture(TextureHandle /*_handle*/, Memory* _mem, uint32_t /*_flags*/) { - StreamRead stream(_mem->data, _mem->size); + bx::MemoryReader reader(_mem->data, _mem->size); uint32_t magic; - stream.read(magic); + bx::read(&reader, magic); - if (BGFX_MAGIC == magic) + if (BGFX_CHUNK_MAGIC_TEX == magic) { TextureCreate tc; - stream.read(tc); + bx::read(&reader, tc); if (NULL != tc.m_mem) { diff --git a/src/vs_clear_dx11.bin.h b/src/vs_clear_dx11.bin.h index 20112fb21..53cb6aaf4 100644 --- a/src/vs_clear_dx11.bin.h +++ b/src/vs_clear_dx11.bin.h @@ -1,44 +1,45 @@ -static const uint8_t vs_clear_dx11[650] = +static const uint8_t vs_clear_dx11[658] = { - 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x74, 0x02, 0x44, 0x58, 0x42, 0x43, 0x9f, 0x90, 0x55, 0x9a, 0x15, 0xd7, 0x4d, // ...t.DXBC..U...M - 0x46, 0x12, 0x19, 0x32, 0x30, 0xa7, 0xfd, 0x7a, 0x83, 0x01, 0x00, 0x00, 0x00, 0x74, 0x02, 0x00, // F..20..z.....t.. - 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, // .....4.......... - 0x00, 0x50, 0x01, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x70, 0x00, 0x00, // .P.......RDEFp.. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, // .............<.. - 0x00, 0x00, 0x05, 0xfe, 0xff, 0x00, 0x91, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x52, 0x44, 0x31, // .........<...RD1 - 0x31, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, // 1<....... ...(.. - 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, // .$...........Mic - 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, // rosoft (R) HLSL - 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, // Shader Compiler - 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, // 9.29.952.3111... - 0xab, 0x49, 0x53, 0x47, 0x4e, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, // .ISGNH.......... - 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // .8.............. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .........A...... - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, // ................ - 0x00, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, // .POSITION.COLOR. - 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, // .OSGNL.......... - 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // .8.............. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .........D...... - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, // ................ - 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, // .SV_POSITION.COL - 0x4f, 0x52, 0x00, 0xab, 0xab, 0x53, 0x48, 0x45, 0x58, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x01, // OR...SHEX....P.. - 0x00, 0x20, 0x00, 0x00, 0x00, 0x6a, 0x08, 0x00, 0x01, 0x5f, 0x00, 0x00, 0x03, 0x72, 0x10, 0x10, // . ...j..._...r.. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, // ....._.......... - 0x00, 0x67, 0x00, 0x00, 0x04, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // .g.... ......... - 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, // .e.... ......6.. - 0x05, 0x72, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, // .r ......F...... - 0x00, 0x36, 0x00, 0x00, 0x05, 0x82, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, // .6.... .......@. - 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, // ....?6.... ..... - 0x00, 0x46, 0x1e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, // .F.......>...STA - 0x54, 0x94, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // T............... - 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x56, 0x53, 0x48, 0x00, 0xa4, 0x8b, 0xef, 0x49, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, // VSH....I........ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x02, 0x44, 0x58, 0x42, // ...........t.DXB + 0x43, 0xda, 0x52, 0xa4, 0x82, 0x31, 0xef, 0x9d, 0x65, 0xc3, 0x64, 0xcc, 0x10, 0x3d, 0x4f, 0x86, // C.R..1..e.d..=O. + 0x53, 0x01, 0x00, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, // S....t.......4.. + 0x00, 0xac, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0xd8, 0x01, 0x00, // .........P...... + 0x00, 0x52, 0x44, 0x45, 0x46, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .RDEFp.......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x05, 0xfe, 0xff, 0x00, 0x91, 0x00, // .....<.......... + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x52, 0x44, 0x31, 0x31, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, // .<...RD11<...... + 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, // . ...(...$...... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, // .....Microsoft ( + 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, // R) HLSL Shader C + 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, // ompiler 9.29.952 + 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x48, 0x00, 0x00, // .3111....ISGNH.. + 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .........8...... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, // ................ + 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // .>.............. + 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x50, // .........COLOR.P + 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x4c, 0x00, 0x00, // OSITION..OSGNL.. + 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .........8...... + 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, // ................ + 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // .D.............. + 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, // .........SV_POSI + 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0xab, 0xab, 0x53, 0x48, 0x45, // TION.COLOR...SHE + 0x58, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x6a, 0x08, 0x00, // X....P... ...j.. + 0x01, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, // ._..........._.. + 0x03, 0x72, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, 0xf2, 0x20, 0x10, // .r.......g.... . + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, // .........e.... . + 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x72, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, // .....6...r ..... + 0x00, 0x46, 0x12, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x82, 0x20, 0x10, // .F.......6.... . + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x00, // ......@.....?6.. + 0x05, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x00, // .. ......F...... + 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x94, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, // .>...STAT....... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, // .. }; diff --git a/src/vs_debugfont_dx11.bin.h b/src/vs_debugfont_dx11.bin.h index 5dfbefe30..d75ce2230 100644 --- a/src/vs_debugfont_dx11.bin.h +++ b/src/vs_debugfont_dx11.bin.h @@ -1,96 +1,96 @@ -static const uint8_t vs_debugfont_dx11[1476] = +static const uint8_t vs_debugfont_dx11[1484] = { - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ................ - 0x00, 0xc0, 0x01, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, // ....u_modelViewP - 0x72, 0x6f, 0x6a, 0x09, 0x00, 0x00, 0x01, 0x04, 0x00, 0x98, 0x05, 0x44, 0x58, 0x42, 0x43, 0x46, // roj........DXBCF - 0xbf, 0xfc, 0xa7, 0xce, 0x2a, 0xea, 0x90, 0xbc, 0x31, 0x32, 0x0a, 0x66, 0x1f, 0xa2, 0x34, 0x01, // ....*...12.f..4. - 0x00, 0x00, 0x00, 0x98, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x88, // ...........4.... - 0x02, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x9c, 0x03, 0x00, 0x00, 0xfc, 0x04, 0x00, 0x00, 0x52, // ...............R - 0x44, 0x45, 0x46, 0x4c, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x01, // DEFL.......h.... - 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x05, 0xfe, 0xff, 0x00, 0x91, 0x00, 0x00, 0x18, // ...<............ - 0x02, 0x00, 0x00, 0x52, 0x44, 0x31, 0x31, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, // ...RD11<....... - 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, // ...(...$........ - 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x24, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x00, 0xab, 0xab, 0xab, 0x5c, // ...$Globals..... - 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, // ...............@ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcc, // ................ - 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, // ...@...@........ + 0x56, 0x53, 0x48, 0x00, 0xb8, 0xbe, 0x22, 0x66, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, // VSH..."f........ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x01, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, // ............u_mo + 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x00, 0x00, 0x01, 0x04, // delViewProj..... + 0x00, 0x98, 0x05, 0x44, 0x58, 0x42, 0x43, 0x4e, 0x14, 0xcf, 0x18, 0xca, 0x5f, 0xd6, 0x83, 0xb0, // ...DXBCN...._... + 0x52, 0x90, 0x95, 0x2f, 0xd3, 0xd3, 0x43, 0x01, 0x00, 0x00, 0x00, 0x98, 0x05, 0x00, 0x00, 0x05, // R../..C......... + 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x88, 0x02, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x9c, // ...4............ + 0x03, 0x00, 0x00, 0xfc, 0x04, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x4c, 0x02, 0x00, 0x00, 0x01, // .......RDEFL.... + 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, // ...h.......<.... + 0x05, 0xfe, 0xff, 0x00, 0x91, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00, 0x52, 0x44, 0x31, 0x31, 0x3c, // ...........RD11< + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, // ....... ...(...$ + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x47, 0x6c, 0x6f, 0x62, // ...........$Glob + 0x61, 0x6c, 0x73, 0x00, 0xab, 0xab, 0xab, 0x5c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x80, // als............. + 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, // ................ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, // .......@........ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd7, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, // ...............@ + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, // ...........@...@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, // ................ - 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, // .......@........ + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd7, // ................ + 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, // .......@........ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, // ...............@ - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfb, // ................ - 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, // ...@...@........ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, // ...............@ + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x40, // ...............@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x75, // ...............u - 0x5f, 0x76, 0x69, 0x65, 0x77, 0x00, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x00, 0x03, // _view.float4x4.. - 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, // ................ - 0x01, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x75, 0x5f, // ...u_viewProj.u_ - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, // model.u_modelVie - 0x77, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, // w.u_modelViewPro - 0x6a, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, // j.u_modelViewPro - 0x6a, 0x58, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x58, 0x00, 0x4d, // jX.u_viewProjX.M - 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, // icrosoft (R) HLS - 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, // L Shader Compile - 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, // r 9.29.952.3111. - 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, // ...ISGN......... - 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // ...h............ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x00, // ...........q.... - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, // ................ - 0x0f, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // ...q............ - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, // ...........w.... - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, // ................ - 0x03, 0x00, 0x00, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, // ...POSITION.COLO - 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x4e, 0x84, // R.TEXCOORD.OSGN. + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xeb, // ................ + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa8, // .......@........ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x40, // ...........@...@ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0c, // ................ + 0x02, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, // .......@........ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, // ................ + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x00, 0x66, 0x6c, // .......u_view.fl + 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, // oat4x4.......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x01, 0x00, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, // ...........u_vie + 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x00, 0x75, 0x5f, // wProj.u_model.u_ + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, // modelView.u_mode + 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, // lViewProj.u_mode + 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x58, 0x00, 0x75, 0x5f, 0x76, 0x69, 0x65, // lViewProjX.u_vie + 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x58, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, // wProjX.Microsoft + 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, // (R) HLSL Shader + 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, // Compiler 9.29.9 + 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x80, // 52.3111....ISGN. 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, // ...........h.... - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, // ................ - 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // ...t............ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, // ...........t.... - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, // ................ - 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // ...z............ - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, // ...........SV_PO - 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, // SITION.COLOR.TEX - 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, 0x53, 0x48, 0x45, 0x58, 0x58, 0x01, 0x00, 0x00, 0x50, // COORD..SHEXX...P - 0x00, 0x01, 0x00, 0x56, 0x00, 0x00, 0x00, 0x6a, 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x04, 0x46, // ...V...j...Y...F - 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x72, // . ........._...r - 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, // ......._........ - 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x5f, // ..._..........._ - 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, 0xf2, // ...2.......g.... - 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, // ..........e.... - 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x02, // ......e.... ... - 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x32, 0x20, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x68, // ...e...2 ......h - 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x08, 0xf2, 0x00, 0x10, 0x00, 0x00, // .......8........ - 0x00, 0x00, 0x00, 0x56, 0x15, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, // ...V.......F. .. - 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0xf2, 0x00, 0x10, 0x00, 0x00, // .......2........ - 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, // ...F. .......... - 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, // .......F.......2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, // ................ + 0x0f, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // ...h............ + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, // ...........n.... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, // ................ + 0x07, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // ...w............ + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, // ...........COLOR + 0x00, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, // .POSITION.TEXCOO + 0x52, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x4e, 0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, // RD.OSGN......... + 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, // ...h............ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, // ...........t.... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, // ................ + 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, // ...t............ + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x00, // ...........z.... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, // ................ + 0x0c, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, // ...SV_POSITION.C + 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, 0x53, // OLOR.TEXCOORD..S + 0x48, 0x45, 0x58, 0x58, 0x01, 0x00, 0x00, 0x50, 0x00, 0x01, 0x00, 0x56, 0x00, 0x00, 0x00, 0x6a, // HEXX...P...V...j + 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, // ...Y...F. ...... + 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, // ..._..........._ + 0x00, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x72, // ..........._...r + 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x03, // ......._...2.... + 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ...g.... ....... + 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, // ...e.... ......e + 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x32, // .... ......e...2 + 0x20, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x38, // ......h.......8 + 0x00, 0x00, 0x08, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x15, 0x10, 0x00, 0x02, // ...........V.... + 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x32, // ...F. .........2 0x00, 0x00, 0x0a, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, // ...........F. .. - 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa6, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, // ...............F - 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf2, 0x20, 0x10, 0x00, 0x00, // ............ ... - 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, // ...F.......F. .. - 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x01, // .......6.... ... - 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, // ...F.......6.... - 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x36, // ......F.......6 - 0x00, 0x00, 0x05, 0x32, 0x20, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x03, // ...2 ......F.... - 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x94, 0x00, 0x00, 0x00, 0x08, // ...>...STAT..... - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, // ...............F + 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0xf2, 0x00, 0x10, 0x00, 0x00, // .......2........ + 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xa6, // ...F. .......... + 0x1a, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .......F........ + 0x00, 0x00, 0x08, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, // .... ......F.... + 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x36, // ...F. .........6 + 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x00, // .... ......F.... + 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, // ...6.... ......F + 0x1e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x32, 0x20, 0x10, 0x00, 0x03, // .......6...2 ... + 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, // ...F.......>...S + 0x54, 0x41, 0x54, 0x94, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // TAT............. + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ - 0x00, 0x00, 0x00, 0x00, // .... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ............ }; diff --git a/src/vs_debugfont_dx9.bin.h b/src/vs_debugfont_dx9.bin.h index 4b333f4d0..3626ce809 100644 --- a/src/vs_debugfont_dx9.bin.h +++ b/src/vs_debugfont_dx9.bin.h @@ -1,24 +1,25 @@ -static const uint8_t vs_debugfont_dx9[335] = +static const uint8_t vs_debugfont_dx9[343] = { - 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, // ...u_modelViewPr - 0x6f, 0x6a, 0x09, 0x01, 0x00, 0x00, 0x04, 0x00, 0x34, 0x01, 0x00, 0x02, 0xfe, 0xff, 0xfe, 0xff, // oj......4....... - 0x23, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x02, // #.CTAB....W..... - 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x50, 0x00, // ..............P. - 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, // ..0...........@. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, // ......u_modelVie - 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, // wProj........... - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x73, 0x5f, 0x32, 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, // ......vs_2_0.Mic - 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, // rosoft (R) HLSL - 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, // Shader Compiler - 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0x1f, 0x00, // 9.29.952.3111... - 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x0a, 0x00, // ................ - 0x00, 0x80, 0x01, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x01, 0x80, 0x02, 0x00, // ................ - 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x80, 0x03, 0x00, 0x0f, 0x90, 0x05, 0x00, // ................ - 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x55, 0x90, 0x01, 0x00, 0xe4, 0xa0, 0x04, 0x00, // ........U....... - 0x00, 0x04, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xe4, 0xa0, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, // ................ - 0xe4, 0x80, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0f, 0x80, 0x02, 0x00, 0xe4, 0xa0, 0x00, 0x00, // ................ - 0xaa, 0x90, 0x00, 0x00, 0xe4, 0x80, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, // ................ - 0xe4, 0x80, 0x03, 0x00, 0xe4, 0xa0, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0f, 0xd0, 0x01, 0x00, // ................ - 0xe4, 0x90, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x0f, 0xd0, 0x02, 0x00, 0xe4, 0x90, 0x01, 0x00, // ................ - 0x00, 0x02, 0x00, 0x00, 0x03, 0xe0, 0x03, 0x00, 0xe4, 0x90, 0xff, 0xff, 0x00, 0x00, 0x00, // ............... + 0x56, 0x53, 0x48, 0x00, 0xb8, 0xbe, 0x22, 0x66, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH..."f...u_mod + 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x09, 0x01, 0x00, 0x00, 0x04, 0x00, // elViewProj...... + 0x34, 0x01, 0x00, 0x02, 0xfe, 0xff, 0xfe, 0xff, 0x23, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, // 4.......#.CTAB.. + 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, // ..W............. + 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, // ......P...0..... + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, // ......@.......u_ + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x03, 0x00, // modelViewProj... + 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x73, // ..............vs + 0x5f, 0x32, 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, // _2_0.Microsoft ( + 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, // R) HLSL Shader C + 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, // ompiler 9.29.952 + 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0x1f, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x80, 0x00, 0x00, // .3111........... + 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x01, 0x80, 0x01, 0x00, 0x0f, 0x90, 0x1f, 0x00, // ................ + 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x05, 0x00, // ................ + 0x00, 0x80, 0x03, 0x00, 0x0f, 0x90, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x02, 0x00, // ................ + 0x55, 0x90, 0x01, 0x00, 0xe4, 0xa0, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, // U............... + 0xe4, 0xa0, 0x02, 0x00, 0x00, 0x90, 0x00, 0x00, 0xe4, 0x80, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, // ................ + 0x0f, 0x80, 0x02, 0x00, 0xe4, 0xa0, 0x02, 0x00, 0xaa, 0x90, 0x00, 0x00, 0xe4, 0x80, 0x02, 0x00, // ................ + 0x00, 0x03, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0xe4, 0x80, 0x03, 0x00, 0xe4, 0xa0, 0x01, 0x00, // ................ + 0x00, 0x02, 0x00, 0x00, 0x0f, 0xd0, 0x00, 0x00, 0xe4, 0x90, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, // ................ + 0x0f, 0xd0, 0x01, 0x00, 0xe4, 0x90, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0xe0, 0x03, 0x00, // ................ + 0xe4, 0x90, 0xff, 0xff, 0x00, 0x00, 0x00, // ....... }; diff --git a/src/vs_debugfont_glsl.bin.h b/src/vs_debugfont_glsl.bin.h index 6bbeb7d2b..6ca4a20f5 100644 --- a/src/vs_debugfont_glsl.bin.h +++ b/src/vs_debugfont_glsl.bin.h @@ -1,33 +1,33 @@ -static const uint8_t vs_debugfont_glsl[466] = +static const uint8_t vs_debugfont_glsl[474] = { - 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x47, 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x70, 0x72, 0x65, // #ifdef GL_ES.pre - 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, // cision highp flo - 0x61, 0x74, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x4c, // at;.#endif // GL - 0x5f, 0x45, 0x53, 0x0a, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x61, 0x74, // _ES..uniform mat - 0x34, 0x20, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, // 4 u_modelViewPro - 0x6a, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, // j;.varying vec2 - 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, // v_texcoord0;.var - 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, // ying vec4 v_colo - 0x72, 0x31, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, // r1;.varying vec4 - 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, // v_color0;.attri - 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, // bute vec2 a_texc - 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, // oord0;.attribute - 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x31, 0x3b, 0x0a, // vec4 a_color1;. - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x61, // attribute vec4 a - 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, // _color0;.attribu - 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, // te vec3 a_positi - 0x6f, 0x6e, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, // on;.void main () - 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, // .{. vec4 tmpvar - 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x77, // _1;. tmpvar_1.w - 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, // = 1.0;. tmpvar - 0x5f, 0x31, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, // _1.xyz = a_posit - 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, // ion;. gl_Positi - 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, // on = (u_modelVie - 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x20, 0x2a, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, // wProj * tmpvar_1 - 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, // );. v_texcoord0 - 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, // = a_texcoord0;. - 0x20, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x63, // v_color0 = a_c - 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, // olor0;. v_color - 0x31, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x31, 0x3b, 0x0a, 0x7d, 0x0a, // 1 = a_color1;.}. - 0x0a, 0x00, // .. + 0x56, 0x53, 0x48, 0x00, 0xb8, 0xbe, 0x22, 0x66, 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x47, // VSH..."f#ifdef G + 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x68, // L_ES.precision h + 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x0a, 0x23, 0x65, 0x6e, 0x64, // ighp float;.#end + 0x69, 0x66, 0x20, 0x2f, 0x2f, 0x20, 0x47, 0x4c, 0x5f, 0x45, 0x53, 0x0a, 0x0a, 0x75, 0x6e, 0x69, // if // GL_ES..uni + 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, // form mat4 u_mode + 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, // lViewProj;.varyi + 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, // ng vec2 v_texcoo + 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, // rd0;.varying vec + 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x31, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, // 4 v_color1;.vary + 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, // ing vec4 v_color + 0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, // 0;.attribute vec + 0x32, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x61, // 2 a_texcoord0;.a + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x61, 0x5f, // ttribute vec3 a_ + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, // position;.attrib + 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, // ute vec4 a_color + 0x31, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, // 1;.attribute vec + 0x34, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, // 4 a_color0;.void + 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x76, 0x65, 0x63, // main ().{. vec + 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, // 4 tmpvar_1;. tm + 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x77, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x3b, 0x0a, // pvar_1.w = 1.0;. + 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x3d, // tmpvar_1.xyz = + 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x67, // a_position;. g + 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x5f, // l_Position = (u_ + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x20, 0x2a, 0x20, // modelViewProj * + 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x74, // tmpvar_1);. v_t + 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, // excoord0 = a_tex + 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, // coord0;. v_colo + 0x72, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x20, // r0 = a_color0;. + 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x31, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x63, 0x6f, // v_color1 = a_co + 0x6c, 0x6f, 0x72, 0x31, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // lor1;.}... }; diff --git a/tools/bin/shaderc.exe b/tools/bin/shaderc.exe index a20695dfeb74dcd3d144f66f9e9330332f58fa02..40acd5f11dff9befd976ecbb68bc664f48161347 100644 GIT binary patch delta 141202 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

=jB_6_R&6{&sg|s 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%0A3t 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≪(gCeev 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ⅇ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

%WY9v5Ud|M^At^;|fkR`T-L}sxV6R5r6st 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 #include #include +#include #include #include #include @@ -29,20 +30,18 @@ extern "C" # define BX_TRACE(_format, ...) fprintf(stderr, "" _format "\n", ##__VA_ARGS__) #endif // DEBUG -#define BX_NAMESPACE 1 +#define BGFX_CHUNK_MAGIC_VSH BX_MAKEFOURCC('V', 'S', 'H', 0x0) +#define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', 0x0) + #include -#if BX_PLATFORM_LINUX -# include - -# define _stricmp strcasecmp -# define _snprintf snprintf -#endif // BX_PLATFORM_LINUX - #include #include #include #include +#include +#include +#include #include "glsl_optimizer.h" @@ -267,208 +266,128 @@ static uint32_t s_optimizationLevelDx11[4] = }; #endif // BX_PLATFORM_WINDOWS -class IStreamWriter +int32_t writef(bx::WriterI* _writer, const char* _format, ...) { -public: - virtual ~IStreamWriter() = 0; - virtual bool open() = 0; - virtual void close() = 0; - virtual void writef(const char* _format, ...) = 0; - virtual void write(const char* _str) = 0; - virtual void write(const void* _data, size_t _size) = 0; + va_list argList; + va_start(argList, _format); - template - void write(Ty _value) + char temp[2048]; + + char* out = temp; + int32_t max = sizeof(temp); + int32_t len = bx::vsnprintf(out, max, _format, argList); + if (len > max) { - write(&_value, sizeof(Ty) ); + out = (char*)alloca(len); + len = bx::vsnprintf(out, len, _format, argList); } - void writeString(const char* _str) - { - uint16_t len = (uint16_t)strlen(_str); - write(len); - write(_str); - char term = '\0'; - write(term); - } -}; + len = _writer->write(out, len); -IStreamWriter::~IStreamWriter() -{ + va_end(argList); + + return len; } -class FileWriter : public IStreamWriter +class Bin2cWriter : public bx::CrtFileWriter { public: - FileWriter(const char* _filePath, bool _bigEndian = false) - : m_filePath(_filePath) - , m_file(NULL) - , m_bigEndian(_bigEndian) + Bin2cWriter(const char* _name) + : m_name(_name) { } - ~FileWriter() + virtual ~Bin2cWriter() { } - bool open() + virtual int32_t close() BX_OVERRIDE { - BX_CHECK(NULL == m_file, "Still open!"); - - m_file = fopen(m_filePath.c_str(), "wb"); - return NULL != m_file; + generate(); + return bx::CrtFileWriter::close(); } - void close() + virtual int32_t write(const void* _data, int32_t _size) BX_OVERRIDE { - if (NULL != m_file) - { - fclose(m_file); - m_file = NULL; - } - } - - void writef(const char* _format, ...) - { - if (NULL != m_file) - { - va_list argList; - va_start(argList, _format); - - char temp[2048]; - int len = vsnprintf(temp, sizeof(temp), _format, argList); - fwrite(temp, len, 1, m_file); - - va_end(argList); - } - } - - void write(const char* _str) - { - if (NULL != m_file) - { - fwrite(_str, strlen(_str), 1, m_file); - } - } - - void write(const void* _data, size_t _size) - { - if (NULL != m_file) - { - fwrite(_data, _size, 1, m_file); - } + const char* data = (const char*)_data; + m_buffer.insert(m_buffer.end(), data, data+_size); + return _size; } private: - std::string m_filePath; - FILE* m_file; - bool m_bigEndian; -}; - -class Bin2cStream : public IStreamWriter -{ -public: - Bin2cStream(const char* _filePath, const char* _name) - : m_filePath(_filePath) - , m_name(_name) - , m_file(NULL) + void generate() { - } - - ~Bin2cStream() - { - } - - bool open() - { - BX_CHECK(NULL == m_file, "Still open!"); - - m_file = fopen(m_filePath.c_str(), "wb"); - return NULL != m_file; - } - - void close() - { - if (NULL != m_file) - { #define HEX_DUMP_WIDTH 16 #define HEX_DUMP_SPACE_WIDTH 96 #define HEX_DUMP_FORMAT "%-" BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "." BX_STRINGIZE(HEX_DUMP_SPACE_WIDTH) "s" - const uint8_t* data = &m_buffer[0]; - uint32_t size = m_buffer.size(); + const uint8_t* data = &m_buffer[0]; + uint32_t size = (uint32_t)m_buffer.size(); - fprintf(m_file, "static const uint8_t %s[%d] =\n{\n", m_name.c_str(), size); + outf("static const uint8_t %s[%d] =\n{\n", m_name.c_str(), size); - if (NULL != data) + if (NULL != data) + { + char hex[HEX_DUMP_SPACE_WIDTH+1]; + char ascii[HEX_DUMP_WIDTH+1]; + uint32_t hexPos = 0; + uint32_t asciiPos = 0; + for (uint32_t ii = 0; ii < size; ++ii) { - char hex[HEX_DUMP_SPACE_WIDTH+1]; - char ascii[HEX_DUMP_WIDTH+1]; - uint32_t hexPos = 0; - uint32_t asciiPos = 0; - for (uint32_t ii = 0; ii < size; ++ii) - { - _snprintf(&hex[hexPos], sizeof(hex)-hexPos, "0x%02x, ", data[asciiPos]); - hexPos += 6; + _snprintf(&hex[hexPos], sizeof(hex)-hexPos, "0x%02x, ", data[asciiPos]); + hexPos += 6; - ascii[asciiPos] = isprint(data[asciiPos]) && data[asciiPos] != '\\' ? data[asciiPos] : '.'; - asciiPos++; + ascii[asciiPos] = isprint(data[asciiPos]) && data[asciiPos] != '\\' ? data[asciiPos] : '.'; + asciiPos++; - if (HEX_DUMP_WIDTH == asciiPos) - { - ascii[asciiPos] = '\0'; - fprintf(m_file, "\t" HEX_DUMP_FORMAT "// %s\n", hex, ascii); - data += asciiPos; - hexPos = 0; - asciiPos = 0; - } - } - - if (0 != asciiPos) + if (HEX_DUMP_WIDTH == asciiPos) { ascii[asciiPos] = '\0'; - fprintf(m_file, "\t" HEX_DUMP_FORMAT "// %s\n", hex, ascii); + outf("\t" HEX_DUMP_FORMAT "// %s\n", hex, ascii); + data += asciiPos; + hexPos = 0; + asciiPos = 0; } } - fprintf(m_file, "};\n"); + if (0 != asciiPos) + { + ascii[asciiPos] = '\0'; + outf("\t" HEX_DUMP_FORMAT "// %s\n", hex, ascii); + } + } + + outf("};\n"); #undef HEX_DUMP_WIDTH #undef HEX_DUMP_SPACE_WIDTH #undef HEX_DUMP_FORMAT - - fclose(m_file); - m_file = NULL; - } } - void writef(const char* _format, ...) + int32_t outf(const char* _format, ...) { va_list argList; va_start(argList, _format); char temp[2048]; - int len = vsnprintf(temp, sizeof(temp), _format, argList); - m_buffer.insert(m_buffer.end(), temp, temp+len); + char* out = temp; + int32_t max = sizeof(temp); + int32_t len = bx::vsnprintf(out, max, _format, argList); + if (len > max) + { + out = (char*)alloca(len); + len = bx::vsnprintf(out, len, _format, argList); + } + + int32_t size = bx::CrtFileWriter::write(out, len); va_end(argList); + + return size; } - void write(const char* _str) - { - m_buffer.insert(m_buffer.end(), _str, _str+strlen(_str) ); - } - - void write(const void* _data, size_t _size) - { - const char* data = (const char*)_data; - m_buffer.insert(m_buffer.end(), data, data+_size); - } - -private: std::string m_filePath; std::string m_name; typedef std::vector Buffer; Buffer m_buffer; - FILE* m_file; }; struct Varying @@ -492,7 +411,7 @@ public: { m_size = fsize(file); m_data = new char[m_size+1]; - m_size = fread(m_data, 1, m_size, file); + m_size = (uint32_t)fread(m_data, 1, m_size, file); m_data[m_size] = '\0'; fclose(file); } @@ -508,90 +427,16 @@ public: return m_data; } - long int getSize() const + uint32_t getSize() const { return m_size; } private: char* m_data; - long int m_size; + uint32_t m_size; }; -const char* strnl(const char* _str) -{ - const char* eol = strstr(_str, "\n\r"); - if (NULL != eol) - { - return eol + 2; - } - - eol = strstr(_str, "\n"); - if (NULL != eol) - { - return eol + 1; - } - - return eol + strlen(_str); -} - -const char* streol(const char* _str) -{ - const char* eol = strstr(_str, "\n\r"); - if (NULL != eol) - { - return eol; - } - - eol = strstr(_str, "\n"); - if (NULL != eol) - { - return eol; - } - - return eol + strlen(_str); -} - -const char* strws(const char* _str) -{ - for (; isspace(*_str); ++_str); - return _str; -} - -const char* strnws(const char* _str) -{ - for (; !isspace(*_str); ++_str); - return _str; -} - -const char* strword(const char* _str) -{ - for (char ch = *_str++; isalnum(ch) || '_' == ch; ch = *_str++); - return _str-1; -} - -const char* strmb(const char* _str, char _open, char _close) -{ - int count = 0; - for (char ch = *_str++; ch != '\0' && count >= 0; ch = *_str++) - { - if (ch == _open) - { - count++; - } - else if (ch == _close) - { - count--; - if (0 == count) - { - return _str-1; - } - } - } - - return NULL; -} - void strins(char* _str, const char* _insert) { size_t len = strlen(_insert); @@ -630,7 +475,7 @@ private: void skipLine() { const char* str = &m_str[m_pos]; - const char* nl = strnl(str); + const char* nl = bx::strnl(str); m_pos += (uint32_t)(nl - str); } @@ -662,7 +507,7 @@ void writeFile(const char* _filePath, void* _data, uint32_t _size) } } -bool compileGLSLShader(CommandLine& _cmdLine, const std::string& _code, IStreamWriter& _stream) +bool compileGLSLShader(bx::CommandLine& _cmdLine, const std::string& _code, bx::WriterI* _writer) { const glslopt_shader_type type = tolower(_cmdLine.findOption('\0', "type")[0]) == 'f' ? kGlslOptShaderFragment : kGlslOptShaderVertex; @@ -683,36 +528,34 @@ bool compileGLSLShader(CommandLine& _cmdLine, const std::string& _code, IStreamW const char* profile = _cmdLine.findOption('p'); if (NULL == profile) { - _stream.write("#ifdef GL_ES\n"); - _stream.write("precision highp float;\n"); - _stream.write("#endif // GL_ES\n\n"); + writef(_writer, "#ifdef GL_ES\n"); + writef(_writer, "precision highp float;\n"); + writef(_writer, "#endif // GL_ES\n\n"); } else { - _stream.writef("#version %s\n\n", profile); + writef(_writer, "#version %s\n\n", profile); } - _stream.write(optimizedShader, strlen(optimizedShader) ); + _writer->write(optimizedShader, (int32_t)strlen(optimizedShader) ); uint8_t nul = 0; - _stream.write(nul); + bx::write(_writer, nul); glslopt_cleanup(ctx); return true; } -bool compileHLSLShaderDx9(CommandLine& _cmdLine, const std::string& _code, IStreamWriter& _stream) +bool compileHLSLShaderDx9(bx::CommandLine& _cmdLine, const std::string& _code, bx::WriterI* _writer) { #if BX_PLATFORM_WINDOWS const char* profile = _cmdLine.findOption('p'); if (NULL == profile) { - printf("Shader profile must be specified.\n"); + fprintf(stderr, "Shader profile must be specified.\n"); return false; } - bool bigEndian = _cmdLine.hasArg('\0', "xbox360"); - uint32_t flags = 0; flags |= _cmdLine.hasArg('\0', "debug") ? D3DXSHADER_DEBUG : 0; flags |= _cmdLine.hasArg('\0', "avoid-flow-control") ? D3DXSHADER_AVOID_FLOW_CONTROL : 0; @@ -736,14 +579,13 @@ bool compileHLSLShaderDx9(CommandLine& _cmdLine, const std::string& _code, IStre BX_TRACE("Profile: %s", profile); BX_TRACE("Flags: 0x%08x", flags); - BX_TRACE("Big Endian: %s", bigEndian?"true":"false"); LPD3DXBUFFER code; LPD3DXBUFFER errorMsg; LPD3DXCONSTANTTABLE constantTable; HRESULT hr = D3DXCompileShader(_code.c_str() - , _code.size() + , (uint32_t)_code.size() , NULL , NULL , "main" @@ -754,10 +596,10 @@ bool compileHLSLShaderDx9(CommandLine& _cmdLine, const std::string& _code, IStre , &constantTable ); if (FAILED(hr) - || werror && NULL != errorMsg) + || (werror && NULL != errorMsg) ) { printCode(_code.c_str() ); - fprintf(stderr, "Error: 0x%08x %s\n", hr, errorMsg->GetBufferPointer() ); + fprintf(stderr, "Error: 0x%08x %s\n", (uint32_t)hr, (const char*)errorMsg->GetBufferPointer() ); return false; } @@ -765,7 +607,7 @@ bool compileHLSLShaderDx9(CommandLine& _cmdLine, const std::string& _code, IStre hr = constantTable->GetDesc(&desc); if (FAILED(hr) ) { - fprintf(stderr, "Error 0x%08x\n", hr); + fprintf(stderr, "Error 0x%08x\n", (uint32_t)hr); return false; } @@ -809,19 +651,20 @@ bool compileHLSLShaderDx9(CommandLine& _cmdLine, const std::string& _code, IStre } uint16_t count = (uint16_t)uniforms.size(); - _stream.write(count); + bx::write(_writer, count); uint32_t fragmentBit = profile[0] == 'p' ? ConstantType::FragmentBit : 0; for (UniformArray::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it) { const Uniform& un = *it; uint8_t nameSize = (uint8_t)un.name.size(); - _stream.write(nameSize); - _stream.write(un.name.c_str(), nameSize); - _stream.write(un.type|fragmentBit); - _stream.write(un.num); - _stream.write(un.regIndex); - _stream.write(un.regCount); + bx::write(_writer, nameSize); + _writer->write(un.name.c_str(), nameSize); + uint8_t type = un.type|fragmentBit; + bx::write(_writer, type); + bx::write(_writer, un.num); + bx::write(_writer, un.regIndex); + bx::write(_writer, un.regCount); BX_TRACE("%s, %s, %d, %d, %d" , un.name.c_str() @@ -830,13 +673,14 @@ bool compileHLSLShaderDx9(CommandLine& _cmdLine, const std::string& _code, IStre , un.regIndex , un.regCount ); + BX_UNUSED(s_constantTypeName); } uint16_t shaderSize = (uint16_t)code->GetBufferSize(); - _stream.write(shaderSize); - _stream.write(code->GetBufferPointer(), shaderSize); + bx::write(_writer, shaderSize); + _writer->write(code->GetBufferPointer(), shaderSize); uint8_t nul = 0; - _stream.write(nul); + bx::write(_writer, nul); if (_cmdLine.hasArg('\0', "disasm") ) { @@ -879,18 +723,16 @@ bool compileHLSLShaderDx9(CommandLine& _cmdLine, const std::string& _code, IStre #endif // BX_PLATFORM_WINDOWS } -bool compileHLSLShaderDx11(CommandLine& _cmdLine, const std::string& _code, IStreamWriter& _stream) +bool compileHLSLShaderDx11(bx::CommandLine& _cmdLine, const std::string& _code, bx::WriterI* _writer) { #if BX_PLATFORM_WINDOWS const char* profile = _cmdLine.findOption('p'); if (NULL == profile) { - printf("Shader profile must be specified.\n"); + fprintf(stderr, "Shader profile must be specified.\n"); return false; } - bool bigEndian = _cmdLine.hasArg('\0', "xbox360"); - uint32_t flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; flags |= _cmdLine.hasArg('\0', "debug") ? D3DCOMPILE_DEBUG : 0; flags |= _cmdLine.hasArg('\0', "avoid-flow-control") ? D3DCOMPILE_AVOID_FLOW_CONTROL : 0; @@ -919,7 +761,6 @@ bool compileHLSLShaderDx11(CommandLine& _cmdLine, const std::string& _code, IStr BX_TRACE("Profile: %s", profile); BX_TRACE("Flags: 0x%08x", flags); - BX_TRACE("Big Endian: %s", bigEndian?"true":"false"); ID3DBlob* code; ID3DBlob* errorMsg; @@ -937,10 +778,10 @@ bool compileHLSLShaderDx11(CommandLine& _cmdLine, const std::string& _code, IStr , &errorMsg ); if (FAILED(hr) - || werror && NULL != errorMsg) + || (werror && NULL != errorMsg) ) { printCode(_code.c_str() ); - fprintf(stderr, BX_FILE_LINE_LITERAL "Error: 0x%08x %s\n", hr, (char*)errorMsg->GetBufferPointer() ); + fprintf(stderr, BX_FILE_LINE_LITERAL "Error: 0x%08x %s\n", (uint32_t)hr, (char*)errorMsg->GetBufferPointer() ); errorMsg->Release(); return false; } @@ -955,7 +796,7 @@ bool compileHLSLShaderDx11(CommandLine& _cmdLine, const std::string& _code, IStr ); if (FAILED(hr) ) { - fprintf(stderr, BX_FILE_LINE_LITERAL "Error: 0x%08x\n", hr); + fprintf(stderr, BX_FILE_LINE_LITERAL "Error: 0x%08x\n", (uint32_t)hr); return false; } @@ -963,7 +804,7 @@ bool compileHLSLShaderDx11(CommandLine& _cmdLine, const std::string& _code, IStr hr = reflect->GetDesc(&desc); if (FAILED(hr) ) { - fprintf(stderr, BX_FILE_LINE_LITERAL "Error: 0x%08x\n", hr); + fprintf(stderr, BX_FILE_LINE_LITERAL "Error: 0x%08x\n", (uint32_t)hr); return false; } @@ -995,7 +836,7 @@ bool compileHLSLShaderDx11(CommandLine& _cmdLine, const std::string& _code, IStr } } - _stream.write(attrMask, sizeof(attrMask) ); + _writer->write(attrMask, sizeof(attrMask) ); BX_TRACE("Output:"); for (uint32_t ii = 0; ii < desc.OutputParameters; ++ii) @@ -1084,21 +925,22 @@ bool compileHLSLShaderDx11(CommandLine& _cmdLine, const std::string& _code, IStr } uint16_t count = (uint16_t)uniforms.size(); - _stream.write(count); + bx::write(_writer, count); - _stream.write(size); + bx::write(_writer, size); uint32_t fragmentBit = profile[0] == 'p' ? ConstantType::FragmentBit : 0; for (UniformArray::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it) { const Uniform& un = *it; uint8_t nameSize = (uint8_t)un.name.size(); - _stream.write(nameSize); - _stream.write(un.name.c_str(), nameSize); - _stream.write(un.type|fragmentBit); - _stream.write(un.num); - _stream.write(un.regIndex); - _stream.write(un.regCount); + bx::write(_writer, nameSize); + _writer->write(un.name.c_str(), nameSize); + uint8_t type = un.type|fragmentBit; + bx::write(_writer, type); + bx::write(_writer, un.num); + bx::write(_writer, un.regIndex); + bx::write(_writer, un.regCount); BX_TRACE("%s, %s, %d, %d, %d" , un.name.c_str() @@ -1110,10 +952,10 @@ bool compileHLSLShaderDx11(CommandLine& _cmdLine, const std::string& _code, IStr } uint16_t shaderSize = (uint16_t)code->GetBufferSize(); - _stream.write(shaderSize); - _stream.write(code->GetBufferPointer(), shaderSize); + bx::write(_writer, shaderSize); + _writer->write(code->GetBufferPointer(), shaderSize); uint8_t nul = 0; - _stream.write(nul); + bx::write(_writer, nul); if (_cmdLine.hasArg('\0', "disasm") ) { @@ -1130,7 +972,7 @@ bool compileHLSLShaderDx11(CommandLine& _cmdLine, const std::string& _code, IStr std::string ofp = _cmdLine.findOption('o'); ofp += ".disasm"; - writeFile(ofp.c_str(), disasm->GetBufferPointer(), disasm->GetBufferSize() ); + writeFile(ofp.c_str(), disasm->GetBufferPointer(), (uint32_t)disasm->GetBufferSize() ); disasm->Release(); } } @@ -1206,7 +1048,7 @@ struct Preprocessor void setDefaultDefine(const char* _name) { char temp[1024]; - _snprintf(temp, countof(temp) + bx::snprintf(temp, countof(temp) , "#ifndef %s\n" "# define %s 0\n" "#endif // %s\n" @@ -1223,11 +1065,7 @@ struct Preprocessor { va_list argList; va_start(argList, _format); - - char temp[2048]; - int len = vsnprintf(temp, sizeof(temp), _format, argList); - m_default += temp; - + m_default += bx::stringPrintfVargs(_format, argList); va_end(argList); } @@ -1242,6 +1080,7 @@ struct Preprocessor m_fgetsPos = 0; m_input = m_default; + m_input += "\n\n"; m_input += _input; fppTag* tagptr = m_tagptr; @@ -1300,7 +1139,7 @@ struct Preprocessor { char* result = &m_scratch[m_scratchPos]; strcpy(result, _str); - m_scratchPos += strlen(_str)+1; + m_scratchPos += (uint32_t)strlen(_str)+1; return result; } @@ -1331,6 +1170,44 @@ const char* baseName(const char* _filePath) return _filePath; } +typedef std::vector InOut; + +uint32_t parseInOut(InOut& _inout, const char* _str, const char* _eol) +{ + uint32_t hash = 0; + _str = bx::strws(_str); + + if (_str < _eol) + { + const char* delim; + do + { + delim = strpbrk(_str, " ,"); + if (NULL != delim) + { + delim = delim > _eol ? _eol : delim; + std::string token; + token.assign(_str, delim-_str); + _inout.push_back(token); + _str = bx::strws(delim + 1); + } + } + while (delim < _eol && NULL != delim); + + std::sort(_inout.begin(), _inout.end() ); + + bx::HashMurmur2A murmur; + murmur.begin(); + for (InOut::const_iterator it = _inout.begin(), itEnd = _inout.end(); it != itEnd; ++it) + { + murmur.add(it->c_str(), it->size() ); + } + hash = murmur.end(); + } + + return hash; +} + // OpenGL #version Features Direct3D Features Shader Model // 2.1 120 vf 9.0 vf 2.0 // 3.0 130 @@ -1382,7 +1259,7 @@ void help(const char* _error = NULL) int main(int _argc, const char* _argv[]) { - CommandLine cmdLine(_argc, _argv); + bx::CommandLine cmdLine(_argc, _argv); if (cmdLine.hasArg('h', "help") ) { @@ -1443,7 +1320,7 @@ int main(int _argc, const char* _argv[]) if (NULL == bin2c) { bin2c = baseName(outFilePath); - uint32_t len = strlen(bin2c); + uint32_t len = (uint32_t)strlen(bin2c); char* temp = (char*)alloca(len+1); for (char *out = temp; *bin2c != '\0';) { @@ -1482,44 +1359,44 @@ int main(int _argc, const char* _argv[]) bool glsl = false; - if (0 == _stricmp(platform, "android") ) + if (0 == bx::stricmp(platform, "android") ) { preprocessor.setDefine("BX_PLATFORM_ANDROID=1"); preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1"); glsl = true; } - else if (0 == _stricmp(platform, "ios") ) + else if (0 == bx::stricmp(platform, "ios") ) { preprocessor.setDefine("BX_PLATFORM_IOS=1"); preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1"); glsl = true; } - else if (0 == _stricmp(platform, "linux") ) + else if (0 == bx::stricmp(platform, "linux") ) { preprocessor.setDefine("BX_PLATFORM_IOS=1"); preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1"); glsl = true; } - else if (0 == _stricmp(platform, "nacl") ) + else if (0 == bx::stricmp(platform, "nacl") ) { preprocessor.setDefine("BX_PLATFORM_NACL=1"); preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1"); glsl = true; } - else if (0 == _stricmp(platform, "osx") ) + else if (0 == bx::stricmp(platform, "osx") ) { preprocessor.setDefine("BX_PLATFORM_OSX=1"); preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1"); glsl = true; } - else if (0 == _stricmp(platform, "windows") ) + else if (0 == bx::stricmp(platform, "windows") ) { preprocessor.setDefine("BX_PLATFORM_WINDOWS=1"); char temp[256]; - _snprintf(temp, sizeof(temp), "BGFX_SHADER_LANGUAGE_HLSL=%d", hlsl); + bx::snprintf(temp, sizeof(temp), "BGFX_SHADER_LANGUAGE_HLSL=%d", hlsl); preprocessor.setDefine(temp); } - else if (0 == _stricmp(platform, "xbox360") ) + else if (0 == bx::stricmp(platform, "xbox360") ) { preprocessor.setDefine("BX_PLATFORM_XBOX360=1"); preprocessor.setDefine("BGFX_SHADER_LANGUAGE_HLSL=3"); @@ -1559,16 +1436,16 @@ int main(int _argc, const char* _argv[]) while (NULL != parse && *parse != '\0') { - parse = strws(parse); + parse = bx::strws(parse); const char* eol = strchr(parse, ';'); if (NULL != eol) { const char* type = parse; - const char* name = parse = strws(strword(parse) ); - const char* column = parse = strws(strword(parse) ); - const char* semantics = parse = strws(strnws(parse) ); - const char* assign = parse = strws(strword(parse) ); - const char* init = parse = strws(strnws(parse) ); + const char* name = parse = bx::strws(bx::strword(parse) ); + const char* column = parse = bx::strws(bx::strword(parse) ); + const char* semantics = parse = bx::strws(bx::strnws(parse) ); + const char* assign = parse = bx::strws(bx::strword(parse) ); + const char* init = parse = bx::strws(bx::strnws(parse) ); if (type < eol && name < eol @@ -1577,9 +1454,9 @@ int main(int _argc, const char* _argv[]) && semantics < eol) { Varying var; - var.m_type.assign(type, strword(type)-type); - var.m_name.assign(name, strword(name)-name); - var.m_semantics.assign(semantics, strword(semantics)-semantics); + var.m_type.assign(type, bx::strword(type)-type); + var.m_name.assign(name, bx::strword(name)-name); + var.m_semantics.assign(semantics, bx::strword(semantics)-semantics); if (assign < eol && '=' == *assign @@ -1596,69 +1473,34 @@ int main(int _argc, const char* _argv[]) } const size_t padding = 16; - long int size = fsize(file); + uint32_t size = (uint32_t)fsize(file); char* data = new char[size+padding]; - size = fread(data, 1, size, file); + size = (uint32_t)fread(data, 1, size, file); memset(&data[size], 0, padding); fclose(file); - typedef std::vector InOut; InOut shaderInputs; InOut shaderOutputs; + uint32_t inputHash = 0; + uint32_t outputHash = 0; const char* input = data; while (input[0] == '$') { const char* str = input+1; - const char* eol = streol(str); - const char* nl = strnl(eol); + const char* eol = bx::streol(str); + const char* nl = bx::strnl(eol); input = nl; if (0 == strncmp(str, "input", 5) ) { str += 5; - str = strws(str); - - if (str < eol) - { - const char* delim; - do - { - delim = strpbrk(str, " ,"); - if (NULL != delim) - { - delim = delim > eol ? eol : delim; - std::string token; - token.assign(str, delim-str); - shaderInputs.push_back(token); - str = strws(delim + 1); - } - } - while (delim < eol && NULL != delim); - } + inputHash = parseInOut(shaderInputs, str, eol); } else if (0 == strncmp(str, "output", 6) ) { str += 6; - str = strws(str); - - if (str < eol) - { - const char* delim; - do - { - delim = strpbrk(str, " ,"); - if (NULL != delim) - { - delim = delim > eol ? eol : delim; - std::string token; - token.assign(str, delim-str); - shaderOutputs.push_back(token); - str = strws(delim + 1); - } - } - while (delim < eol && NULL != delim); - } + outputHash = parseInOut(shaderOutputs, str, eol); } } @@ -1756,7 +1598,7 @@ int main(int _argc, const char* _argv[]) const char* brace = strstr(entry, "{"); if (NULL != brace) { - const char* end = strmb(brace, '{', '}'); + const char* end = bx::strmb(brace, '{', '}'); if (NULL != end) { strins(const_cast(end), "__RETURN__;\n"); @@ -1828,9 +1670,9 @@ int main(int _argc, const char* _argv[]) if (preprocessOnly) { - FileWriter stream(outFilePath); + bx::CrtFileWriter writer; - if (!stream.open() ) + if (0 != writer.open(outFilePath) ) { fprintf(stderr, "Unable to open output file '%s'.", outFilePath); return false; @@ -1841,17 +1683,17 @@ int main(int _argc, const char* _argv[]) const char* profile = cmdLine.findOption('p'); if (NULL == profile) { - stream.write("#ifdef GL_ES\n"); - stream.write("precision highp float;\n"); - stream.write("#endif // GL_ES\n\n"); + writef(&writer, "#ifdef GL_ES\n"); + writef(&writer, "precision highp float;\n"); + writef(&writer, "#endif // GL_ES\n\n"); } else { - stream.writef("#version %s\n\n", profile); + writef(&writer, "#version %s\n\n", profile); } } - stream.write(preprocessor.m_preprocessed.c_str(), preprocessor.m_preprocessed.size() ); - stream.close(); + writer.write(preprocessor.m_preprocessed.c_str(), (int32_t)preprocessor.m_preprocessed.size() ); + writer.close(); return EXIT_SUCCESS; } @@ -1859,45 +1701,52 @@ int main(int _argc, const char* _argv[]) bool compiled = false; { - IStreamWriter* stream = NULL; + bx::CrtFileWriter* writer = NULL; if (NULL != bin2c) { - stream = new Bin2cStream(outFilePath, bin2c); + writer = new Bin2cWriter(bin2c); } else { - stream = new FileWriter(outFilePath); + writer = new bx::CrtFileWriter; } - if (!stream->open() ) + if (0 != writer->open(outFilePath) ) { fprintf(stderr, "Unable to open output file '%s'.", outFilePath); return false; } + if (fragment) + { + bx::write(writer, BGFX_CHUNK_MAGIC_FSH); + bx::write(writer, inputHash); + } + else + { + bx::write(writer, BGFX_CHUNK_MAGIC_VSH); + bx::write(writer, outputHash); + } + if (glsl) { - compiled = compileGLSLShader(cmdLine, preprocessor.m_preprocessed, *stream); + compiled = compileGLSLShader(cmdLine, preprocessor.m_preprocessed, writer); } else { if (hlsl > 3) { - compiled = compileHLSLShaderDx11(cmdLine, preprocessor.m_preprocessed, *stream); + compiled = compileHLSLShaderDx11(cmdLine, preprocessor.m_preprocessed, writer); } else { - compiled = compileHLSLShaderDx9(cmdLine, preprocessor.m_preprocessed, *stream); + compiled = compileHLSLShaderDx9(cmdLine, preprocessor.m_preprocessed, writer); } } -#if SHADERC_DEBUG - stream->writeString(filePath); -#endif // SHADERC_DEBUG - - stream->close(); - delete stream; + writer->close(); + delete writer; } if (compiled) @@ -1906,14 +1755,11 @@ int main(int _argc, const char* _argv[]) { std::string ofp = outFilePath; ofp += ".d"; - FileWriter stream(ofp.c_str() ); - if (stream.open() ) + bx::CrtFileWriter writer; + if (0 == writer.open(ofp.c_str() ) ) { - stream.write(outFilePath); - stream.write(":"); - stream.write(preprocessor.m_depends.c_str() ); - stream.write("\n"); - stream.close(); + writef(&writer, "%s : %s\n", outFilePath, preprocessor.m_depends.c_str() ); + writer.close(); } } diff --git a/tools/ddsdump.cpp b/tools/texturec/texturec.cpp similarity index 91% rename from tools/ddsdump.cpp rename to tools/texturec/texturec.cpp index 351c282d9..698868582 100644 --- a/tools/ddsdump.cpp +++ b/tools/texturec/texturec.cpp @@ -17,7 +17,6 @@ using namespace bgfx; # define BX_TRACE(_format, ...) fprintf(stderr, "" _format "\n", ##__VA_ARGS__) #endif // DEBUG -#define BX_NAMESPACE 1 #include #include #include @@ -95,7 +94,7 @@ long int fsize(FILE* _file) int main(int _argc, const char* _argv[]) { - CommandLine cmdLine(_argc, _argv); + bx::CommandLine cmdLine(_argc, _argv); FILE* file = fopen(_argv[1], "rb"); uint32_t size = fsize(file); @@ -157,7 +156,7 @@ int main(int _argc, const char* _argv[]) } char filePath[256]; - _snprintf(filePath, sizeof(filePath), "mip%d_%d.tga", side, lod); + bx::snprintf(filePath, sizeof(filePath), "mip%d_%d.tga", side, lod); saveTga(filePath, width, height, dstpitch, bits); free(bits); @@ -176,7 +175,7 @@ int main(int _argc, const char* _argv[]) if (getRawImageData(dds, 0, lod, mem, mip) ) { char filePath[256]; - _snprintf(filePath, sizeof(filePath), "mip%d.bin", lod); + bx::snprintf(filePath, sizeof(filePath), "mip%d.bin", lod); file = fopen(filePath, "wb"); fwrite(mip.m_data, 1, mip.m_size, file); fclose(file);