ANGLE: Update to version 2446
Update ANGLE and reapply patches. Patch changes: "Dynamically resolve functions of dwmapi.dll" Removed; ANGLE no longer uses DWM API "Make it possible to link ANGLE statically for single-thread use" Avoid name collision by using ANGLE-style getCurrent() "Fix build when SSE2 is not available." Added guard for __cpuid(), which is not available on ARM "Make DX9/DX11 mutually exclusive" Adjustments due to underlying code changes "ANGLE: Avoid memory copies on buffers when data is null" Removed; fixed upstream "Add missing intrin.h include for __cpuid" Removed; fixed upstream Change-Id: I4f3d850fc555d3194ddc05e0b51c4966d33f7eaf Reviewed-by: Oliver Wolff <oliver.wolff@digia.com> Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com> Reviewed-by: Kai Koehne <kai.koehne@digia.com>bb10
parent
d84ed9a92a
commit
1a334f8135
|
|
@ -36,7 +36,8 @@ src/libGLESv2/renderer/shaders/compiled/PassthroughRGB11ps.h
|
|||
src/libGLESv2/renderer/shaders/compiled/PassthroughLumAlpha11ps.h
|
||||
src/libGLESv2/renderer/shaders/compiled/PassthroughLum11ps.h
|
||||
src/libGLESv2/renderer/shaders/compiled/Passthrough11vs.h
|
||||
src/libGLESv2/renderer/shaders/compiled/Clear11ps.h
|
||||
src/libGLESv2/renderer/shaders/compiled/Clear11vs.h
|
||||
src/libGLESv2/renderer/shaders/compiled/clear11vs.h
|
||||
src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h
|
||||
src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ Cloud Party, Inc.
|
|||
Intel Corporation
|
||||
Mozilla Corporation
|
||||
Turbulenz
|
||||
Klarälvdalens Datakonsult AB
|
||||
|
||||
Jacek Caban
|
||||
Mark Callow
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
TransGaming Inc.
|
||||
Nicolas Capens
|
||||
Daniel Koch
|
||||
Geoff Lang
|
||||
Andrew Lewycky
|
||||
Jamie Madill
|
||||
Gavriel State
|
||||
Shannon Woods
|
||||
|
||||
|
|
@ -36,6 +38,8 @@ Google Inc.
|
|||
Ben Vanik
|
||||
Adrienne Walker
|
||||
thestig@chromium.org
|
||||
Justin Schuh
|
||||
Scott Graham
|
||||
|
||||
Adobe Systems Inc.
|
||||
Alexandru Chiculita
|
||||
|
|
@ -53,6 +57,9 @@ Intel Corporation
|
|||
Andy Chen
|
||||
Josh Triplett
|
||||
|
||||
Klarälvdalens Datakonsult AB
|
||||
Milian Wolff
|
||||
|
||||
Mozilla Corp.
|
||||
Ehsan Akhgari
|
||||
Jeff Gilbert
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2002-2010 The ANGLE Project Authors.
|
||||
// Copyright (C) 2002-2013 The ANGLE Project Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
|||
|
|
@ -306,6 +306,12 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay
|
|||
#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
|
||||
#endif
|
||||
|
||||
#ifndef EGL_ANGLE_direct3d_display
|
||||
#define EGL_ANGLE_direct3d_display 1
|
||||
#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
|
||||
#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
|
||||
#endif
|
||||
|
||||
#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
|
||||
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
|
||||
#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ extern "C" {
|
|||
|
||||
// Version number for shader translation API.
|
||||
// It is incremented everytime the API changes.
|
||||
#define ANGLE_SH_VERSION 110
|
||||
#define ANGLE_SH_VERSION 112
|
||||
|
||||
//
|
||||
// The names of the following enums have been derived by replacing GL prefix
|
||||
|
|
@ -108,6 +108,13 @@ typedef enum {
|
|||
SH_SAMPLER_EXTERNAL_OES = 0x8D66
|
||||
} ShDataType;
|
||||
|
||||
typedef enum {
|
||||
SH_PRECISION_HIGHP = 0x5001,
|
||||
SH_PRECISION_MEDIUMP = 0x5002,
|
||||
SH_PRECISION_LOWP = 0x5003,
|
||||
SH_PRECISION_UNDEFINED = 0
|
||||
} ShPrecisionType;
|
||||
|
||||
typedef enum {
|
||||
SH_INFO_LOG_LENGTH = 0x8B84,
|
||||
SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH
|
||||
|
|
@ -115,6 +122,8 @@ typedef enum {
|
|||
SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87,
|
||||
SH_ACTIVE_ATTRIBUTES = 0x8B89,
|
||||
SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A,
|
||||
SH_VARYINGS = 0x8BBB,
|
||||
SH_VARYING_MAX_LENGTH = 0x8BBC,
|
||||
SH_MAPPED_NAME_MAX_LENGTH = 0x6000,
|
||||
SH_NAME_MAX_LENGTH = 0x6001,
|
||||
SH_HASHED_NAME_MAX_LENGTH = 0x6002,
|
||||
|
|
@ -128,7 +137,7 @@ typedef enum {
|
|||
SH_VALIDATE_LOOP_INDEXING = 0x0001,
|
||||
SH_INTERMEDIATE_TREE = 0x0002,
|
||||
SH_OBJECT_CODE = 0x0004,
|
||||
SH_ATTRIBUTES_UNIFORMS = 0x0008,
|
||||
SH_VARIABLES = 0x0008,
|
||||
SH_LINE_DIRECTIVES = 0x0010,
|
||||
SH_SOURCE_PATH = 0x0020,
|
||||
SH_MAP_LONG_VARIABLE_NAMES = 0x0040,
|
||||
|
|
@ -154,6 +163,11 @@ typedef enum {
|
|||
SH_DEPENDENCY_GRAPH = 0x0400,
|
||||
|
||||
// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
|
||||
// This flag only enforces (and can only enforce) the packing
|
||||
// restrictions for uniform variables in both vertex and fragment
|
||||
// shaders. ShCheckVariablesWithinPackingLimits() lets embedders
|
||||
// enforce the packing restrictions for varying variables during
|
||||
// program link time.
|
||||
SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
|
||||
|
||||
// This flag ensures all indirect (expression-based) array indexing
|
||||
|
|
@ -162,7 +176,19 @@ typedef enum {
|
|||
// vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
|
||||
// specified in the ShBuiltInResources when constructing the
|
||||
// compiler, selects the strategy for the clamping implementation.
|
||||
SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000
|
||||
SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000,
|
||||
|
||||
// This flag limits the complexity of an expression.
|
||||
SH_LIMIT_EXPRESSION_COMPLEXITY = 0x2000,
|
||||
|
||||
// This flag limits the depth of the call stack.
|
||||
SH_LIMIT_CALL_STACK_DEPTH = 0x4000,
|
||||
|
||||
// This flag initializes gl_Position to vec4(0.0, 0.0, 0.0, 1.0) at
|
||||
// the beginning of the vertex shader, and has no effect in the
|
||||
// fragment shader. It is intended as a workaround for drivers which
|
||||
// incorrectly fail to link programs if gl_Position is not written.
|
||||
SH_INIT_GL_POSITION = 0x8000,
|
||||
} ShCompileOptions;
|
||||
|
||||
// Defines alternate strategies for implementing array index clamping.
|
||||
|
|
@ -212,6 +238,7 @@ typedef struct
|
|||
int OES_EGL_image_external;
|
||||
int ARB_texture_rectangle;
|
||||
int EXT_draw_buffers;
|
||||
int EXT_frag_depth;
|
||||
|
||||
// Set to 1 if highp precision is supported in the fragment language.
|
||||
// Default is 0.
|
||||
|
|
@ -225,6 +252,12 @@ typedef struct
|
|||
// Selects a strategy to use when implementing array index clamping.
|
||||
// Default is SH_CLAMP_WITH_CLAMP_INTRINSIC.
|
||||
ShArrayIndexClampingStrategy ArrayIndexClampingStrategy;
|
||||
|
||||
// The maximum complexity an expression can be.
|
||||
int MaxExpressionComplexity;
|
||||
|
||||
// The maximum depth a call stack can be.
|
||||
int MaxCallStackDepth;
|
||||
} ShBuiltInResources;
|
||||
|
||||
//
|
||||
|
|
@ -281,9 +314,8 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle);
|
|||
// Can be queried by calling ShGetInfoLog().
|
||||
// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
|
||||
// Can be queried by calling ShGetObjectCode().
|
||||
// SH_ATTRIBUTES_UNIFORMS: Extracts attributes and uniforms.
|
||||
// Can be queried by calling ShGetActiveAttrib() and
|
||||
// ShGetActiveUniform().
|
||||
// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
|
||||
// Can be queried by calling ShGetVariableInfo().
|
||||
//
|
||||
COMPILER_EXPORT int ShCompile(
|
||||
const ShHandle handle,
|
||||
|
|
@ -309,6 +341,9 @@ COMPILER_EXPORT int ShCompile(
|
|||
// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
|
||||
// variable name including the null
|
||||
// termination character.
|
||||
// SH_VARYINGS: the number of varying variables.
|
||||
// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name
|
||||
// including the null termination character.
|
||||
// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
|
||||
// the null termination character.
|
||||
// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the
|
||||
|
|
@ -342,60 +377,44 @@ COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
|
|||
// ShGetInfo with SH_OBJECT_CODE_LENGTH.
|
||||
COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
|
||||
|
||||
// Returns information about an active attribute variable.
|
||||
// Returns information about a shader variable.
|
||||
// Parameters:
|
||||
// handle: Specifies the compiler
|
||||
// index: Specifies the index of the attribute variable to be queried.
|
||||
// variableType: Specifies the variable type; options include
|
||||
// SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS.
|
||||
// index: Specifies the index of the variable to be queried.
|
||||
// length: Returns the number of characters actually written in the string
|
||||
// indicated by name (excluding the null terminator) if a value other
|
||||
// than NULL is passed.
|
||||
// size: Returns the size of the attribute variable.
|
||||
// type: Returns the data type of the attribute variable.
|
||||
// size: Returns the size of the variable.
|
||||
// type: Returns the data type of the variable.
|
||||
// precision: Returns the precision of the variable.
|
||||
// staticUse: Returns 1 if the variable is accessed in a statement after
|
||||
// pre-processing, whether or not run-time flow of control will
|
||||
// cause that statement to be executed.
|
||||
// Returns 0 otherwise.
|
||||
// name: Returns a null terminated string containing the name of the
|
||||
// attribute variable. It is assumed that name has enough memory to
|
||||
// accomodate the attribute variable name. The size of the buffer
|
||||
// required to store the attribute variable name can be obtained by
|
||||
// calling ShGetInfo with SH_ACTIVE_ATTRIBUTE_MAX_LENGTH.
|
||||
// variable. It is assumed that name has enough memory to accormodate
|
||||
// the variable name. The size of the buffer required to store the
|
||||
// variable name can be obtained by calling ShGetInfo with
|
||||
// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH,
|
||||
// SH_VARYING_MAX_LENGTH.
|
||||
// mappedName: Returns a null terminated string containing the mapped name of
|
||||
// the attribute variable, It is assumed that mappedName has enough
|
||||
// memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
|
||||
// about the mapped name. If the name is not mapped, then name and
|
||||
// mappedName are the same.
|
||||
COMPILER_EXPORT void ShGetActiveAttrib(const ShHandle handle,
|
||||
// the variable, It is assumed that mappedName has enough memory
|
||||
// (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the
|
||||
// mapped name. If the name is not mapped, then name and mappedName
|
||||
// are the same.
|
||||
COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle,
|
||||
ShShaderInfo variableType,
|
||||
int index,
|
||||
size_t* length,
|
||||
int* size,
|
||||
ShDataType* type,
|
||||
ShPrecisionType* precision,
|
||||
int* staticUse,
|
||||
char* name,
|
||||
char* mappedName);
|
||||
|
||||
// Returns information about an active uniform variable.
|
||||
// Parameters:
|
||||
// handle: Specifies the compiler
|
||||
// index: Specifies the index of the uniform variable to be queried.
|
||||
// length: Returns the number of characters actually written in the string
|
||||
// indicated by name (excluding the null terminator) if a value
|
||||
// other than NULL is passed.
|
||||
// size: Returns the size of the uniform variable.
|
||||
// type: Returns the data type of the uniform variable.
|
||||
// name: Returns a null terminated string containing the name of the
|
||||
// uniform variable. It is assumed that name has enough memory to
|
||||
// accomodate the uniform variable name. The size of the buffer required
|
||||
// to store the uniform variable name can be obtained by calling
|
||||
// ShGetInfo with SH_ACTIVE_UNIFORMS_MAX_LENGTH.
|
||||
// mappedName: Returns a null terminated string containing the mapped name of
|
||||
// the uniform variable, It is assumed that mappedName has enough
|
||||
// memory (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care
|
||||
// about the mapped name. If the name is not mapped, then name and
|
||||
// mappedName are the same.
|
||||
COMPILER_EXPORT void ShGetActiveUniform(const ShHandle handle,
|
||||
int index,
|
||||
size_t* length,
|
||||
int* size,
|
||||
ShDataType* type,
|
||||
char* name,
|
||||
char* mappedName);
|
||||
|
||||
// Returns information about a name hashing entry from the latest compile.
|
||||
// Parameters:
|
||||
// handle: Specifies the compiler
|
||||
|
|
@ -426,6 +445,25 @@ COMPILER_EXPORT void ShGetInfoPointer(const ShHandle handle,
|
|||
ShShaderInfo pname,
|
||||
void** params);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ShDataType type;
|
||||
int size;
|
||||
} ShVariableInfo;
|
||||
|
||||
// Returns 1 if the passed in variables pack in maxVectors following
|
||||
// the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
|
||||
// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
|
||||
// flag above.
|
||||
// Parameters:
|
||||
// maxVectors: the available rows of registers.
|
||||
// varInfoArray: an array of variable info (types and sizes).
|
||||
// varInfoArraySize: the size of the variable array.
|
||||
COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
|
||||
int maxVectors,
|
||||
ShVariableInfo* varInfoArray,
|
||||
size_t varInfoArraySize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@
|
|||
*-------------------------------------------------------------------------
|
||||
* This precedes the return type of the function in the function prototype.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC)
|
||||
# define KHRONOS_APICALL __declspec(dllimport)
|
||||
#elif defined (__SYMBIAN32__)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#ifndef COMMON_ANGLEUTILS_H_
|
||||
#define COMMON_ANGLEUTILS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// A macro to disallow the copy constructor and operator= functions
|
||||
// This must be used in the private: declarations for a class
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
#include "common/debug.h"
|
||||
#include "common/system.h"
|
||||
#ifdef ANGLE_ENABLE_D3D11
|
||||
typedef DWORD D3DCOLOR;
|
||||
#else
|
||||
#ifndef ANGLE_ENABLE_D3D11
|
||||
#include <d3d9.h>
|
||||
#else
|
||||
typedef DWORD D3DCOLOR;
|
||||
#endif
|
||||
|
||||
namespace gl
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "common/event_tracer.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
|
||||
AddTraceEventFunc g_addTraceEvent;
|
||||
|
||||
} // namespace gl
|
||||
|
||||
extern "C" {
|
||||
|
||||
void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag,
|
||||
AddTraceEventFunc addTraceEvent)
|
||||
{
|
||||
gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag;
|
||||
gl::g_addTraceEvent = addTraceEvent;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name)
|
||||
{
|
||||
if (g_getCategoryEnabledFlag)
|
||||
{
|
||||
return g_getCategoryEnabledFlag(name);
|
||||
}
|
||||
static unsigned char disabled = 0;
|
||||
return &disabled;
|
||||
}
|
||||
|
||||
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
|
||||
int numArgs, const char** argNames, const unsigned char* argTypes,
|
||||
const unsigned long long* argValues, unsigned char flags)
|
||||
{
|
||||
if (g_addTraceEvent)
|
||||
{
|
||||
g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef COMMON_EVENT_TRACER_H_
|
||||
#define COMMON_EVENT_TRACER_H_
|
||||
|
||||
extern "C" {
|
||||
|
||||
typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name);
|
||||
typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name,
|
||||
unsigned long long id, int numArgs, const char** argNames,
|
||||
const unsigned char* argTypes, const unsigned long long* argValues,
|
||||
unsigned char flags);
|
||||
|
||||
// extern "C" so that it has a reasonable name for GetProcAddress.
|
||||
void __stdcall SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag,
|
||||
AddTraceEventFunc add_trace_event_func);
|
||||
|
||||
}
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name);
|
||||
|
||||
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
|
||||
int numArgs, const char** argNames, const unsigned char* argTypes,
|
||||
const unsigned long long* argValues, unsigned char flags);
|
||||
|
||||
}
|
||||
|
||||
#endif // COMMON_EVENT_TRACER_H_
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#define MAJOR_VERSION 1
|
||||
#define MINOR_VERSION 1
|
||||
#define MINOR_VERSION 2
|
||||
#define BUILD_VERSION 0
|
||||
#define BUILD_REVISION 2037
|
||||
#define BUILD_REVISION 2446
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define MACRO_STRINGIFY(x) STRINGIFY(x)
|
||||
|
|
|
|||
|
|
@ -90,10 +90,6 @@ enum TQualifier
|
|||
EvqInvariantVaryingOut, // vertex shaders only read/write
|
||||
EvqUniform, // Readonly, vertex and fragment
|
||||
|
||||
// pack/unpack input and output
|
||||
EvqInput,
|
||||
EvqOutput,
|
||||
|
||||
// parameters
|
||||
EvqIn,
|
||||
EvqOut,
|
||||
|
|
@ -112,6 +108,7 @@ enum TQualifier
|
|||
// built-ins written by fragment shader
|
||||
EvqFragColor,
|
||||
EvqFragData,
|
||||
EvqFragDepth,
|
||||
|
||||
// end of list
|
||||
EvqLast
|
||||
|
|
@ -137,14 +134,13 @@ inline const char* getQualifierString(TQualifier q)
|
|||
case EvqIn: return "in"; break;
|
||||
case EvqOut: return "out"; break;
|
||||
case EvqInOut: return "inout"; break;
|
||||
case EvqInput: return "input"; break;
|
||||
case EvqOutput: return "output"; break;
|
||||
case EvqPosition: return "Position"; break;
|
||||
case EvqPointSize: return "PointSize"; break;
|
||||
case EvqFragCoord: return "FragCoord"; break;
|
||||
case EvqFrontFacing: return "FrontFacing"; break;
|
||||
case EvqFragColor: return "FragColor"; break;
|
||||
case EvqFragData: return "FragData"; break;
|
||||
case EvqFragDepth: return "FragDepth"; break;
|
||||
default: return "unknown qualifier";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,36 +14,24 @@
|
|||
|
||||
#include "compiler/PoolAlloc.h"
|
||||
|
||||
// We need two pieces of information to report errors/warnings - string and
|
||||
// line number. We encode these into a single int so that it can be easily
|
||||
// incremented/decremented by lexer. The right SOURCE_LOC_LINE_SIZE bits store
|
||||
// line number while the rest store the string number. Since the shaders are
|
||||
// usually small, we should not run out of memory. SOURCE_LOC_LINE_SIZE
|
||||
// can be increased to alleviate this issue.
|
||||
typedef int TSourceLoc;
|
||||
const unsigned int SOURCE_LOC_LINE_SIZE = 16; // in bits.
|
||||
const unsigned int SOURCE_LOC_LINE_MASK = (1 << SOURCE_LOC_LINE_SIZE) - 1;
|
||||
|
||||
inline TSourceLoc EncodeSourceLoc(int string, int line) {
|
||||
return (string << SOURCE_LOC_LINE_SIZE) | (line & SOURCE_LOC_LINE_MASK);
|
||||
}
|
||||
|
||||
inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) {
|
||||
if (string) *string = loc >> SOURCE_LOC_LINE_SIZE;
|
||||
if (line) *line = loc & SOURCE_LOC_LINE_MASK;
|
||||
}
|
||||
struct TSourceLoc {
|
||||
int first_file;
|
||||
int first_line;
|
||||
int last_file;
|
||||
int last_line;
|
||||
};
|
||||
|
||||
//
|
||||
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
|
||||
//
|
||||
#define POOL_ALLOCATOR_NEW_DELETE(A) \
|
||||
void* operator new(size_t s) { return (A).allocate(s); } \
|
||||
void* operator new(size_t, void *_Where) { return (_Where); } \
|
||||
void operator delete(void*) { } \
|
||||
void operator delete(void *, void *) { } \
|
||||
void* operator new[](size_t s) { return (A).allocate(s); } \
|
||||
void* operator new[](size_t, void *_Where) { return (_Where); } \
|
||||
void operator delete[](void*) { } \
|
||||
#define POOL_ALLOCATOR_NEW_DELETE() \
|
||||
void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
|
||||
void* operator new(size_t, void *_Where) { return (_Where); } \
|
||||
void operator delete(void*) { } \
|
||||
void operator delete(void *, void *) { } \
|
||||
void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
|
||||
void* operator new[](size_t, void *_Where) { return (_Where); } \
|
||||
void operator delete[](void*) { } \
|
||||
void operator delete[](void *, void *) { }
|
||||
|
||||
//
|
||||
|
|
@ -54,7 +42,7 @@ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TStri
|
|||
typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
|
||||
inline TString* NewPoolTString(const char* s)
|
||||
{
|
||||
void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
|
||||
void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
|
||||
return new(memory) TString(s);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
//
|
||||
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#include "compiler/BuiltInFunctionEmulator.h"
|
||||
#include "compiler/DetectRecursion.h"
|
||||
#include "compiler/DetectCallDepth.h"
|
||||
#include "compiler/ForLoopUnroll.h"
|
||||
#include "compiler/Initialize.h"
|
||||
#include "compiler/InitializeGLPosition.h"
|
||||
#include "compiler/InitializeParseContext.h"
|
||||
#include "compiler/MapLongVariableNames.h"
|
||||
#include "compiler/ParseHelper.h"
|
||||
|
|
@ -27,66 +28,34 @@ bool isWebGLBasedSpec(ShShaderSpec spec)
|
|||
}
|
||||
|
||||
namespace {
|
||||
bool InitializeSymbolTable(
|
||||
const TBuiltInStrings& builtInStrings,
|
||||
ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
|
||||
TInfoSink& infoSink, TSymbolTable& symbolTable)
|
||||
{
|
||||
TIntermediate intermediate(infoSink);
|
||||
TExtensionBehavior extBehavior;
|
||||
InitExtensionBehavior(resources, extBehavior);
|
||||
// The builtins deliberately don't specify precisions for the function
|
||||
// arguments and return types. For that reason we don't try to check them.
|
||||
TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink);
|
||||
parseContext.fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
|
||||
|
||||
GlobalParseContext = &parseContext;
|
||||
|
||||
assert(symbolTable.isEmpty());
|
||||
//
|
||||
// Parse the built-ins. This should only happen once per
|
||||
// language symbol table.
|
||||
//
|
||||
// Push the symbol table to give it an initial scope. This
|
||||
// push should not have a corresponding pop, so that built-ins
|
||||
// are preserved, and the test for an empty table fails.
|
||||
//
|
||||
symbolTable.push();
|
||||
|
||||
for (TBuiltInStrings::const_iterator i = builtInStrings.begin(); i != builtInStrings.end(); ++i)
|
||||
{
|
||||
const char* builtInShaders = i->c_str();
|
||||
int builtInLengths = static_cast<int>(i->size());
|
||||
if (builtInLengths <= 0)
|
||||
continue;
|
||||
|
||||
if (PaParseStrings(1, &builtInShaders, &builtInLengths, &parseContext) != 0)
|
||||
{
|
||||
infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
IdentifyBuiltIns(type, spec, resources, symbolTable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class TScopedPoolAllocator {
|
||||
public:
|
||||
TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
|
||||
: mAllocator(allocator), mPushPopAllocator(pushPop) {
|
||||
if (mPushPopAllocator) mAllocator->push();
|
||||
TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) {
|
||||
mAllocator->push();
|
||||
SetGlobalPoolAllocator(mAllocator);
|
||||
}
|
||||
~TScopedPoolAllocator() {
|
||||
SetGlobalPoolAllocator(NULL);
|
||||
if (mPushPopAllocator) mAllocator->pop();
|
||||
mAllocator->pop();
|
||||
}
|
||||
|
||||
private:
|
||||
TPoolAllocator* mAllocator;
|
||||
bool mPushPopAllocator;
|
||||
};
|
||||
|
||||
class TScopedSymbolTableLevel {
|
||||
public:
|
||||
TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) {
|
||||
ASSERT(mTable->atBuiltInLevel());
|
||||
mTable->push();
|
||||
}
|
||||
~TScopedSymbolTableLevel() {
|
||||
while (!mTable->atBuiltInLevel())
|
||||
mTable->pop();
|
||||
}
|
||||
|
||||
private:
|
||||
TSymbolTable* mTable;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
|
@ -103,6 +72,9 @@ TShHandleBase::~TShHandleBase() {
|
|||
TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
|
||||
: shaderType(type),
|
||||
shaderSpec(spec),
|
||||
maxUniformVectors(0),
|
||||
maxExpressionComplexity(0),
|
||||
maxCallStackDepth(0),
|
||||
fragmentPrecisionHigh(false),
|
||||
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
|
||||
builtInFunctionEmulator(type)
|
||||
|
|
@ -121,7 +93,10 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
|
|||
maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
|
||||
resources.MaxVertexUniformVectors :
|
||||
resources.MaxFragmentUniformVectors;
|
||||
TScopedPoolAllocator scopedAlloc(&allocator, false);
|
||||
maxExpressionComplexity = resources.MaxExpressionComplexity;
|
||||
maxCallStackDepth = resources.MaxCallStackDepth;
|
||||
|
||||
SetGlobalPoolAllocator(&allocator);
|
||||
|
||||
// Generate built-in symbol table.
|
||||
if (!InitBuiltInSymbolTable(resources))
|
||||
|
|
@ -141,7 +116,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
|
|||
size_t numStrings,
|
||||
int compileOptions)
|
||||
{
|
||||
TScopedPoolAllocator scopedAlloc(&allocator, true);
|
||||
TScopedPoolAllocator scopedAlloc(&allocator);
|
||||
clearResults();
|
||||
|
||||
if (numStrings == 0)
|
||||
|
|
@ -165,13 +140,11 @@ bool TCompiler::compile(const char* const shaderStrings[],
|
|||
shaderType, shaderSpec, compileOptions, true,
|
||||
sourcePath, infoSink);
|
||||
parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
|
||||
GlobalParseContext = &parseContext;
|
||||
SetGlobalParseContext(&parseContext);
|
||||
|
||||
// We preserve symbols at the built-in level from compile-to-compile.
|
||||
// Start pushing the user-defined symbols at global level.
|
||||
symbolTable.push();
|
||||
if (!symbolTable.atGlobalLevel())
|
||||
infoSink.info.message(EPrefixInternalError, "Wrong symbol table level");
|
||||
TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
|
||||
|
||||
// Parse shader.
|
||||
bool success =
|
||||
|
|
@ -182,7 +155,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
|
|||
success = intermediate.postProcess(root);
|
||||
|
||||
if (success)
|
||||
success = detectRecursion(root);
|
||||
success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
|
||||
|
||||
if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
|
||||
success = validateLimitations(root);
|
||||
|
|
@ -205,6 +178,10 @@ bool TCompiler::compile(const char* const shaderStrings[],
|
|||
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
|
||||
arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
|
||||
|
||||
// Disallow expressions deemed too complex.
|
||||
if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
|
||||
success = limitExpressionComplexity(root);
|
||||
|
||||
// Call mapLongVariableNames() before collectAttribsUniforms() so in
|
||||
// collectAttribsUniforms() we already have the mapped symbol names and
|
||||
// we could composite mapped and original variable names.
|
||||
|
|
@ -212,12 +189,18 @@ bool TCompiler::compile(const char* const shaderStrings[],
|
|||
if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
|
||||
mapLongVariableNames(root);
|
||||
|
||||
if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
|
||||
collectAttribsUniforms(root);
|
||||
if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) {
|
||||
InitializeGLPosition initGLPosition;
|
||||
root->traverse(&initGLPosition);
|
||||
}
|
||||
|
||||
if (success && (compileOptions & SH_VARIABLES)) {
|
||||
collectVariables(root);
|
||||
if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) {
|
||||
success = enforcePackingRestrictions();
|
||||
if (!success) {
|
||||
infoSink.info.message(EPrefixError, "too many uniforms");
|
||||
infoSink.info.prefix(EPrefixError);
|
||||
infoSink.info << "too many uniforms";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -231,22 +214,58 @@ bool TCompiler::compile(const char* const shaderStrings[],
|
|||
|
||||
// Cleanup memory.
|
||||
intermediate.remove(parseContext.treeRoot);
|
||||
// Ensure symbol table is returned to the built-in level,
|
||||
// throwing away all but the built-ins.
|
||||
while (!symbolTable.atBuiltInLevel())
|
||||
symbolTable.pop();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources)
|
||||
bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
|
||||
{
|
||||
TBuiltIns builtIns;
|
||||
|
||||
compileResources = resources;
|
||||
builtIns.initialize(shaderType, shaderSpec, resources);
|
||||
return InitializeSymbolTable(builtIns.getBuiltInStrings(),
|
||||
shaderType, shaderSpec, resources, infoSink, symbolTable);
|
||||
|
||||
assert(symbolTable.isEmpty());
|
||||
symbolTable.push();
|
||||
|
||||
TPublicType integer;
|
||||
integer.type = EbtInt;
|
||||
integer.size = 1;
|
||||
integer.matrix = false;
|
||||
integer.array = false;
|
||||
|
||||
TPublicType floatingPoint;
|
||||
floatingPoint.type = EbtFloat;
|
||||
floatingPoint.size = 1;
|
||||
floatingPoint.matrix = false;
|
||||
floatingPoint.array = false;
|
||||
|
||||
TPublicType sampler;
|
||||
sampler.size = 1;
|
||||
sampler.matrix = false;
|
||||
sampler.array = false;
|
||||
|
||||
switch(shaderType)
|
||||
{
|
||||
case SH_FRAGMENT_SHADER:
|
||||
symbolTable.setDefaultPrecision(integer, EbpMedium);
|
||||
break;
|
||||
case SH_VERTEX_SHADER:
|
||||
symbolTable.setDefaultPrecision(integer, EbpHigh);
|
||||
symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
|
||||
break;
|
||||
default: assert(false && "Language not supported");
|
||||
}
|
||||
// We set defaults for all the sampler types, even those that are
|
||||
// only available if an extension exists.
|
||||
for (int samplerType = EbtGuardSamplerBegin + 1;
|
||||
samplerType < EbtGuardSamplerEnd; ++samplerType) {
|
||||
sampler.type = static_cast<TBasicType>(samplerType);
|
||||
symbolTable.setDefaultPrecision(sampler, EbpLow);
|
||||
}
|
||||
|
||||
InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
|
||||
|
||||
IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TCompiler::clearResults()
|
||||
|
|
@ -258,24 +277,31 @@ void TCompiler::clearResults()
|
|||
|
||||
attribs.clear();
|
||||
uniforms.clear();
|
||||
varyings.clear();
|
||||
|
||||
builtInFunctionEmulator.Cleanup();
|
||||
|
||||
nameMap.clear();
|
||||
}
|
||||
|
||||
bool TCompiler::detectRecursion(TIntermNode* root)
|
||||
bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
|
||||
{
|
||||
DetectRecursion detect;
|
||||
DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
|
||||
root->traverse(&detect);
|
||||
switch (detect.detectRecursion()) {
|
||||
case DetectRecursion::kErrorNone:
|
||||
switch (detect.detectCallDepth()) {
|
||||
case DetectCallDepth::kErrorNone:
|
||||
return true;
|
||||
case DetectRecursion::kErrorMissingMain:
|
||||
infoSink.info.message(EPrefixError, "Missing main()");
|
||||
case DetectCallDepth::kErrorMissingMain:
|
||||
infoSink.info.prefix(EPrefixError);
|
||||
infoSink.info << "Missing main()";
|
||||
return false;
|
||||
case DetectRecursion::kErrorRecursion:
|
||||
infoSink.info.message(EPrefixError, "Function recursion detected");
|
||||
case DetectCallDepth::kErrorRecursion:
|
||||
infoSink.info.prefix(EPrefixError);
|
||||
infoSink.info << "Function recursion detected";
|
||||
return false;
|
||||
case DetectCallDepth::kErrorMaxDepthExceeded:
|
||||
infoSink.info.prefix(EPrefixError);
|
||||
infoSink.info << "Function call stack too deep";
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
|
@ -321,6 +347,28 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
|
|||
}
|
||||
}
|
||||
|
||||
bool TCompiler::limitExpressionComplexity(TIntermNode* root)
|
||||
{
|
||||
TIntermTraverser traverser;
|
||||
root->traverse(&traverser);
|
||||
TDependencyGraph graph(root);
|
||||
|
||||
for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
|
||||
iter != graph.endUserDefinedFunctionCalls();
|
||||
++iter)
|
||||
{
|
||||
TGraphFunctionCall* samplerSymbol = *iter;
|
||||
TDependencyGraphTraverser graphTraverser;
|
||||
samplerSymbol->traverse(&graphTraverser);
|
||||
}
|
||||
|
||||
if (traverser.getMaxDepth() > maxExpressionComplexity) {
|
||||
infoSink.info << "Expression too complex.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
|
||||
{
|
||||
RestrictFragmentShaderTiming restrictor(infoSink.info);
|
||||
|
|
@ -335,9 +383,9 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
|
|||
return restrictor.numErrors() == 0;
|
||||
}
|
||||
|
||||
void TCompiler::collectAttribsUniforms(TIntermNode* root)
|
||||
void TCompiler::collectVariables(TIntermNode* root)
|
||||
{
|
||||
CollectAttribsUniforms collect(attribs, uniforms, hashFunction);
|
||||
CollectVariables collect(attribs, uniforms, varyings, hashFunction);
|
||||
root->traverse(&collect);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@
|
|||
|
||||
class ConstantUnion {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
ConstantUnion()
|
||||
{
|
||||
iConst = 0;
|
||||
type = EbtVoid;
|
||||
}
|
||||
|
||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||
void setIConst(int i) {iConst = i; type = EbtInt; }
|
||||
void setFConst(float f) {fConst = f; type = EbtFloat; }
|
||||
void setBConst(bool b) {bConst = b; type = EbtBool; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
//
|
||||
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#include "compiler/DetectCallDepth.h"
|
||||
#include "compiler/InfoSink.h"
|
||||
|
||||
DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
|
||||
: name(fname),
|
||||
visit(PreVisit)
|
||||
{
|
||||
}
|
||||
|
||||
const TString& DetectCallDepth::FunctionNode::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
void DetectCallDepth::FunctionNode::addCallee(
|
||||
DetectCallDepth::FunctionNode* callee)
|
||||
{
|
||||
for (size_t i = 0; i < callees.size(); ++i) {
|
||||
if (callees[i] == callee)
|
||||
return;
|
||||
}
|
||||
callees.push_back(callee);
|
||||
}
|
||||
|
||||
int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
|
||||
{
|
||||
ASSERT(visit == PreVisit);
|
||||
ASSERT(detectCallDepth);
|
||||
|
||||
int maxDepth = depth;
|
||||
visit = InVisit;
|
||||
for (size_t i = 0; i < callees.size(); ++i) {
|
||||
switch (callees[i]->visit) {
|
||||
case InVisit:
|
||||
// cycle detected, i.e., recursion detected.
|
||||
return kInfiniteCallDepth;
|
||||
case PostVisit:
|
||||
break;
|
||||
case PreVisit: {
|
||||
// Check before we recurse so we don't go too depth
|
||||
if (detectCallDepth->checkExceedsMaxDepth(depth))
|
||||
return depth;
|
||||
int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
|
||||
// Check after we recurse so we can exit immediately and provide info.
|
||||
if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
|
||||
detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
|
||||
return callDepth;
|
||||
}
|
||||
maxDepth = std::max(callDepth, maxDepth);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
visit = PostVisit;
|
||||
return maxDepth;
|
||||
}
|
||||
|
||||
void DetectCallDepth::FunctionNode::reset()
|
||||
{
|
||||
visit = PreVisit;
|
||||
}
|
||||
|
||||
DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
|
||||
: TIntermTraverser(true, false, true, false),
|
||||
currentFunction(NULL),
|
||||
infoSink(infoSink),
|
||||
maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
|
||||
{
|
||||
}
|
||||
|
||||
DetectCallDepth::~DetectCallDepth()
|
||||
{
|
||||
for (size_t i = 0; i < functions.size(); ++i)
|
||||
delete functions[i];
|
||||
}
|
||||
|
||||
bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
|
||||
{
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpPrototype:
|
||||
// Function declaration.
|
||||
// Don't add FunctionNode here because node->getName() is the
|
||||
// unmangled function name.
|
||||
break;
|
||||
case EOpFunction: {
|
||||
// Function definition.
|
||||
if (visit == PreVisit) {
|
||||
currentFunction = findFunctionByName(node->getName());
|
||||
if (currentFunction == NULL) {
|
||||
currentFunction = new FunctionNode(node->getName());
|
||||
functions.push_back(currentFunction);
|
||||
}
|
||||
} else if (visit == PostVisit) {
|
||||
currentFunction = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EOpFunctionCall: {
|
||||
// Function call.
|
||||
if (visit == PreVisit) {
|
||||
FunctionNode* func = findFunctionByName(node->getName());
|
||||
if (func == NULL) {
|
||||
func = new FunctionNode(node->getName());
|
||||
functions.push_back(func);
|
||||
}
|
||||
if (currentFunction)
|
||||
currentFunction->addCallee(func);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DetectCallDepth::checkExceedsMaxDepth(int depth)
|
||||
{
|
||||
return depth >= maxDepth;
|
||||
}
|
||||
|
||||
void DetectCallDepth::resetFunctionNodes()
|
||||
{
|
||||
for (size_t i = 0; i < functions.size(); ++i) {
|
||||
functions[i]->reset();
|
||||
}
|
||||
}
|
||||
|
||||
DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
|
||||
{
|
||||
currentFunction = NULL;
|
||||
resetFunctionNodes();
|
||||
|
||||
int maxCallDepth = func->detectCallDepth(this, 1);
|
||||
|
||||
if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
|
||||
return kErrorRecursion;
|
||||
|
||||
if (maxCallDepth >= maxDepth)
|
||||
return kErrorMaxDepthExceeded;
|
||||
|
||||
return kErrorNone;
|
||||
}
|
||||
|
||||
DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
|
||||
{
|
||||
if (maxDepth != FunctionNode::kInfiniteCallDepth) {
|
||||
// Check all functions because the driver may fail on them
|
||||
// TODO: Before detectingRecursion, strip unused functions.
|
||||
for (size_t i = 0; i < functions.size(); ++i) {
|
||||
ErrorCode error = detectCallDepthForFunction(functions[i]);
|
||||
if (error != kErrorNone)
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
FunctionNode* main = findFunctionByName("main(");
|
||||
if (main == NULL)
|
||||
return kErrorMissingMain;
|
||||
|
||||
return detectCallDepthForFunction(main);
|
||||
}
|
||||
|
||||
return kErrorNone;
|
||||
}
|
||||
|
||||
DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
|
||||
const TString& name)
|
||||
{
|
||||
for (size_t i = 0; i < functions.size(); ++i) {
|
||||
if (functions[i]->getName() == name)
|
||||
return functions[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#ifndef COMPILER_DETECT_RECURSION_H_
|
||||
#define COMPILER_DETECT_RECURSION_H_
|
||||
|
||||
#include "GLSLANG/ShaderLang.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include "compiler/intermediate.h"
|
||||
#include "compiler/VariableInfo.h"
|
||||
|
||||
class TInfoSink;
|
||||
|
||||
// Traverses intermediate tree to detect function recursion.
|
||||
class DetectCallDepth : public TIntermTraverser {
|
||||
public:
|
||||
enum ErrorCode {
|
||||
kErrorMissingMain,
|
||||
kErrorRecursion,
|
||||
kErrorMaxDepthExceeded,
|
||||
kErrorNone
|
||||
};
|
||||
|
||||
DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth);
|
||||
~DetectCallDepth();
|
||||
|
||||
virtual bool visitAggregate(Visit, TIntermAggregate*);
|
||||
|
||||
bool checkExceedsMaxDepth(int depth);
|
||||
|
||||
ErrorCode detectCallDepth();
|
||||
|
||||
private:
|
||||
class FunctionNode {
|
||||
public:
|
||||
static const int kInfiniteCallDepth = INT_MAX;
|
||||
|
||||
FunctionNode(const TString& fname);
|
||||
|
||||
const TString& getName() const;
|
||||
|
||||
// If a function is already in the callee list, this becomes a no-op.
|
||||
void addCallee(FunctionNode* callee);
|
||||
|
||||
// Returns kInifinityCallDepth if recursive function calls are detected.
|
||||
int detectCallDepth(DetectCallDepth* detectCallDepth, int depth);
|
||||
|
||||
// Reset state.
|
||||
void reset();
|
||||
|
||||
private:
|
||||
// mangled function name is unique.
|
||||
TString name;
|
||||
|
||||
// functions that are directly called by this function.
|
||||
TVector<FunctionNode*> callees;
|
||||
|
||||
Visit visit;
|
||||
};
|
||||
|
||||
ErrorCode detectCallDepthForFunction(FunctionNode* func);
|
||||
FunctionNode* findFunctionByName(const TString& name);
|
||||
void resetFunctionNodes();
|
||||
|
||||
TInfoSink& getInfoSink() { return infoSink; }
|
||||
|
||||
TVector<FunctionNode*> functions;
|
||||
FunctionNode* currentFunction;
|
||||
TInfoSink& infoSink;
|
||||
int maxDepth;
|
||||
|
||||
DetectCallDepth(const DetectCallDepth&);
|
||||
void operator=(const DetectCallDepth&);
|
||||
};
|
||||
|
||||
#endif // COMPILER_DETECT_RECURSION_H_
|
||||
|
|
@ -46,7 +46,7 @@ void TDiagnostics::writeInfo(Severity severity,
|
|||
TInfoSinkBase& sink = mInfoSink.info;
|
||||
/* VC++ format: file(linenum) : error #: 'token' : extrainfo */
|
||||
sink.prefix(prefix);
|
||||
sink.location(EncodeSourceLoc(loc.file, loc.line));
|
||||
sink.location(loc.file, loc.line);
|
||||
sink << "'" << token << "' : " << reason << " " << extra << "\n";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include "compiler/InfoSink.h"
|
||||
|
||||
void TInfoSinkBase::prefix(TPrefixType message) {
|
||||
switch(message) {
|
||||
void TInfoSinkBase::prefix(TPrefixType p) {
|
||||
switch(p) {
|
||||
case EPrefixNone:
|
||||
break;
|
||||
case EPrefixWarning:
|
||||
|
|
@ -31,29 +31,24 @@ void TInfoSinkBase::prefix(TPrefixType message) {
|
|||
}
|
||||
}
|
||||
|
||||
void TInfoSinkBase::location(TSourceLoc loc) {
|
||||
int string = 0, line = 0;
|
||||
DecodeSourceLoc(loc, &string, &line);
|
||||
|
||||
void TInfoSinkBase::location(int file, int line) {
|
||||
TPersistStringStream stream;
|
||||
if (line)
|
||||
stream << string << ":" << line;
|
||||
stream << file << ":" << line;
|
||||
else
|
||||
stream << string << ":? ";
|
||||
stream << file << ":? ";
|
||||
stream << ": ";
|
||||
|
||||
sink.append(stream.str());
|
||||
}
|
||||
|
||||
void TInfoSinkBase::message(TPrefixType message, const char* s) {
|
||||
prefix(message);
|
||||
sink.append(s);
|
||||
sink.append("\n");
|
||||
void TInfoSinkBase::location(const TSourceLoc& loc) {
|
||||
location(loc.first_file, loc.first_line);
|
||||
}
|
||||
|
||||
void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) {
|
||||
prefix(message);
|
||||
void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) {
|
||||
prefix(p);
|
||||
location(loc);
|
||||
sink.append(s);
|
||||
sink.append(m);
|
||||
sink.append("\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,10 +96,10 @@ public:
|
|||
const TPersistString& str() const { return sink; }
|
||||
const char* c_str() const { return sink.c_str(); }
|
||||
|
||||
void prefix(TPrefixType message);
|
||||
void location(TSourceLoc loc);
|
||||
void message(TPrefixType message, const char* s);
|
||||
void message(TPrefixType message, const char* s, TSourceLoc loc);
|
||||
void prefix(TPrefixType p);
|
||||
void location(int file, int line);
|
||||
void location(const TSourceLoc& loc);
|
||||
void message(TPrefixType p, const TSourceLoc& loc, const char* m);
|
||||
|
||||
private:
|
||||
TPersistString sink;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
|
@ -14,513 +14,413 @@
|
|||
|
||||
#include "compiler/intermediate.h"
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Prototypes for built-in functions seen by both vertex and fragment shaders.
|
||||
//
|
||||
//============================================================================
|
||||
static TString BuiltInFunctionsCommon(const ShBuiltInResources& resources)
|
||||
void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
|
||||
{
|
||||
TString s;
|
||||
TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1);
|
||||
TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2);
|
||||
TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3);
|
||||
TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4);
|
||||
|
||||
TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2);
|
||||
TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3);
|
||||
TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4);
|
||||
|
||||
//
|
||||
// Angle and Trigonometric Functions.
|
||||
//
|
||||
s.append(TString("float radians(float degrees);"));
|
||||
s.append(TString("vec2 radians(vec2 degrees);"));
|
||||
s.append(TString("vec3 radians(vec3 degrees);"));
|
||||
s.append(TString("vec4 radians(vec4 degrees);"));
|
||||
symbolTable.insertBuiltIn(float1, "radians", float1);
|
||||
symbolTable.insertBuiltIn(float2, "radians", float2);
|
||||
symbolTable.insertBuiltIn(float3, "radians", float3);
|
||||
symbolTable.insertBuiltIn(float4, "radians", float4);
|
||||
|
||||
s.append(TString("float degrees(float radians);"));
|
||||
s.append(TString("vec2 degrees(vec2 radians);"));
|
||||
s.append(TString("vec3 degrees(vec3 radians);"));
|
||||
s.append(TString("vec4 degrees(vec4 radians);"));
|
||||
symbolTable.insertBuiltIn(float1, "degrees", float1);
|
||||
symbolTable.insertBuiltIn(float2, "degrees", float2);
|
||||
symbolTable.insertBuiltIn(float3, "degrees", float3);
|
||||
symbolTable.insertBuiltIn(float4, "degrees", float4);
|
||||
|
||||
s.append(TString("float sin(float angle);"));
|
||||
s.append(TString("vec2 sin(vec2 angle);"));
|
||||
s.append(TString("vec3 sin(vec3 angle);"));
|
||||
s.append(TString("vec4 sin(vec4 angle);"));
|
||||
symbolTable.insertBuiltIn(float1, "sin", float1);
|
||||
symbolTable.insertBuiltIn(float2, "sin", float2);
|
||||
symbolTable.insertBuiltIn(float3, "sin", float3);
|
||||
symbolTable.insertBuiltIn(float4, "sin", float4);
|
||||
|
||||
s.append(TString("float cos(float angle);"));
|
||||
s.append(TString("vec2 cos(vec2 angle);"));
|
||||
s.append(TString("vec3 cos(vec3 angle);"));
|
||||
s.append(TString("vec4 cos(vec4 angle);"));
|
||||
symbolTable.insertBuiltIn(float1, "cos", float1);
|
||||
symbolTable.insertBuiltIn(float2, "cos", float2);
|
||||
symbolTable.insertBuiltIn(float3, "cos", float3);
|
||||
symbolTable.insertBuiltIn(float4, "cos", float4);
|
||||
|
||||
s.append(TString("float tan(float angle);"));
|
||||
s.append(TString("vec2 tan(vec2 angle);"));
|
||||
s.append(TString("vec3 tan(vec3 angle);"));
|
||||
s.append(TString("vec4 tan(vec4 angle);"));
|
||||
symbolTable.insertBuiltIn(float1, "tan", float1);
|
||||
symbolTable.insertBuiltIn(float2, "tan", float2);
|
||||
symbolTable.insertBuiltIn(float3, "tan", float3);
|
||||
symbolTable.insertBuiltIn(float4, "tan", float4);
|
||||
|
||||
s.append(TString("float asin(float x);"));
|
||||
s.append(TString("vec2 asin(vec2 x);"));
|
||||
s.append(TString("vec3 asin(vec3 x);"));
|
||||
s.append(TString("vec4 asin(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "asin", float1);
|
||||
symbolTable.insertBuiltIn(float2, "asin", float2);
|
||||
symbolTable.insertBuiltIn(float3, "asin", float3);
|
||||
symbolTable.insertBuiltIn(float4, "asin", float4);
|
||||
|
||||
s.append(TString("float acos(float x);"));
|
||||
s.append(TString("vec2 acos(vec2 x);"));
|
||||
s.append(TString("vec3 acos(vec3 x);"));
|
||||
s.append(TString("vec4 acos(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "acos", float1);
|
||||
symbolTable.insertBuiltIn(float2, "acos", float2);
|
||||
symbolTable.insertBuiltIn(float3, "acos", float3);
|
||||
symbolTable.insertBuiltIn(float4, "acos", float4);
|
||||
|
||||
s.append(TString("float atan(float y, float x);"));
|
||||
s.append(TString("vec2 atan(vec2 y, vec2 x);"));
|
||||
s.append(TString("vec3 atan(vec3 y, vec3 x);"));
|
||||
s.append(TString("vec4 atan(vec4 y, vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "atan", float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "atan", float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "atan", float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "atan", float4, float4);
|
||||
|
||||
s.append(TString("float atan(float y_over_x);"));
|
||||
s.append(TString("vec2 atan(vec2 y_over_x);"));
|
||||
s.append(TString("vec3 atan(vec3 y_over_x);"));
|
||||
s.append(TString("vec4 atan(vec4 y_over_x);"));
|
||||
symbolTable.insertBuiltIn(float1, "atan", float1);
|
||||
symbolTable.insertBuiltIn(float2, "atan", float2);
|
||||
symbolTable.insertBuiltIn(float3, "atan", float3);
|
||||
symbolTable.insertBuiltIn(float4, "atan", float4);
|
||||
|
||||
//
|
||||
// Exponential Functions.
|
||||
//
|
||||
s.append(TString("float pow(float x, float y);"));
|
||||
s.append(TString("vec2 pow(vec2 x, vec2 y);"));
|
||||
s.append(TString("vec3 pow(vec3 x, vec3 y);"));
|
||||
s.append(TString("vec4 pow(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(float1, "pow", float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "pow", float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "pow", float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "pow", float4, float4);
|
||||
|
||||
s.append(TString("float exp(float x);"));
|
||||
s.append(TString("vec2 exp(vec2 x);"));
|
||||
s.append(TString("vec3 exp(vec3 x);"));
|
||||
s.append(TString("vec4 exp(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "exp", float1);
|
||||
symbolTable.insertBuiltIn(float2, "exp", float2);
|
||||
symbolTable.insertBuiltIn(float3, "exp", float3);
|
||||
symbolTable.insertBuiltIn(float4, "exp", float4);
|
||||
|
||||
s.append(TString("float log(float x);"));
|
||||
s.append(TString("vec2 log(vec2 x);"));
|
||||
s.append(TString("vec3 log(vec3 x);"));
|
||||
s.append(TString("vec4 log(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "log", float1);
|
||||
symbolTable.insertBuiltIn(float2, "log", float2);
|
||||
symbolTable.insertBuiltIn(float3, "log", float3);
|
||||
symbolTable.insertBuiltIn(float4, "log", float4);
|
||||
|
||||
s.append(TString("float exp2(float x);"));
|
||||
s.append(TString("vec2 exp2(vec2 x);"));
|
||||
s.append(TString("vec3 exp2(vec3 x);"));
|
||||
s.append(TString("vec4 exp2(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "exp2", float1);
|
||||
symbolTable.insertBuiltIn(float2, "exp2", float2);
|
||||
symbolTable.insertBuiltIn(float3, "exp2", float3);
|
||||
symbolTable.insertBuiltIn(float4, "exp2", float4);
|
||||
|
||||
s.append(TString("float log2(float x);"));
|
||||
s.append(TString("vec2 log2(vec2 x);"));
|
||||
s.append(TString("vec3 log2(vec3 x);"));
|
||||
s.append(TString("vec4 log2(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "log2", float1);
|
||||
symbolTable.insertBuiltIn(float2, "log2", float2);
|
||||
symbolTable.insertBuiltIn(float3, "log2", float3);
|
||||
symbolTable.insertBuiltIn(float4, "log2", float4);
|
||||
|
||||
s.append(TString("float sqrt(float x);"));
|
||||
s.append(TString("vec2 sqrt(vec2 x);"));
|
||||
s.append(TString("vec3 sqrt(vec3 x);"));
|
||||
s.append(TString("vec4 sqrt(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "sqrt", float1);
|
||||
symbolTable.insertBuiltIn(float2, "sqrt", float2);
|
||||
symbolTable.insertBuiltIn(float3, "sqrt", float3);
|
||||
symbolTable.insertBuiltIn(float4, "sqrt", float4);
|
||||
|
||||
s.append(TString("float inversesqrt(float x);"));
|
||||
s.append(TString("vec2 inversesqrt(vec2 x);"));
|
||||
s.append(TString("vec3 inversesqrt(vec3 x);"));
|
||||
s.append(TString("vec4 inversesqrt(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "inversesqrt", float1);
|
||||
symbolTable.insertBuiltIn(float2, "inversesqrt", float2);
|
||||
symbolTable.insertBuiltIn(float3, "inversesqrt", float3);
|
||||
symbolTable.insertBuiltIn(float4, "inversesqrt", float4);
|
||||
|
||||
//
|
||||
// Common Functions.
|
||||
//
|
||||
s.append(TString("float abs(float x);"));
|
||||
s.append(TString("vec2 abs(vec2 x);"));
|
||||
s.append(TString("vec3 abs(vec3 x);"));
|
||||
s.append(TString("vec4 abs(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "abs", float1);
|
||||
symbolTable.insertBuiltIn(float2, "abs", float2);
|
||||
symbolTable.insertBuiltIn(float3, "abs", float3);
|
||||
symbolTable.insertBuiltIn(float4, "abs", float4);
|
||||
|
||||
s.append(TString("float sign(float x);"));
|
||||
s.append(TString("vec2 sign(vec2 x);"));
|
||||
s.append(TString("vec3 sign(vec3 x);"));
|
||||
s.append(TString("vec4 sign(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "sign", float1);
|
||||
symbolTable.insertBuiltIn(float2, "sign", float2);
|
||||
symbolTable.insertBuiltIn(float3, "sign", float3);
|
||||
symbolTable.insertBuiltIn(float4, "sign", float4);
|
||||
|
||||
s.append(TString("float floor(float x);"));
|
||||
s.append(TString("vec2 floor(vec2 x);"));
|
||||
s.append(TString("vec3 floor(vec3 x);"));
|
||||
s.append(TString("vec4 floor(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "floor", float1);
|
||||
symbolTable.insertBuiltIn(float2, "floor", float2);
|
||||
symbolTable.insertBuiltIn(float3, "floor", float3);
|
||||
symbolTable.insertBuiltIn(float4, "floor", float4);
|
||||
|
||||
s.append(TString("float ceil(float x);"));
|
||||
s.append(TString("vec2 ceil(vec2 x);"));
|
||||
s.append(TString("vec3 ceil(vec3 x);"));
|
||||
s.append(TString("vec4 ceil(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "ceil", float1);
|
||||
symbolTable.insertBuiltIn(float2, "ceil", float2);
|
||||
symbolTable.insertBuiltIn(float3, "ceil", float3);
|
||||
symbolTable.insertBuiltIn(float4, "ceil", float4);
|
||||
|
||||
s.append(TString("float fract(float x);"));
|
||||
s.append(TString("vec2 fract(vec2 x);"));
|
||||
s.append(TString("vec3 fract(vec3 x);"));
|
||||
s.append(TString("vec4 fract(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "fract", float1);
|
||||
symbolTable.insertBuiltIn(float2, "fract", float2);
|
||||
symbolTable.insertBuiltIn(float3, "fract", float3);
|
||||
symbolTable.insertBuiltIn(float4, "fract", float4);
|
||||
|
||||
s.append(TString("float mod(float x, float y);"));
|
||||
s.append(TString("vec2 mod(vec2 x, float y);"));
|
||||
s.append(TString("vec3 mod(vec3 x, float y);"));
|
||||
s.append(TString("vec4 mod(vec4 x, float y);"));
|
||||
s.append(TString("vec2 mod(vec2 x, vec2 y);"));
|
||||
s.append(TString("vec3 mod(vec3 x, vec3 y);"));
|
||||
s.append(TString("vec4 mod(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(float1, "mod", float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "mod", float2, float1);
|
||||
symbolTable.insertBuiltIn(float3, "mod", float3, float1);
|
||||
symbolTable.insertBuiltIn(float4, "mod", float4, float1);
|
||||
symbolTable.insertBuiltIn(float2, "mod", float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "mod", float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "mod", float4, float4);
|
||||
|
||||
s.append(TString("float min(float x, float y);"));
|
||||
s.append(TString("vec2 min(vec2 x, float y);"));
|
||||
s.append(TString("vec3 min(vec3 x, float y);"));
|
||||
s.append(TString("vec4 min(vec4 x, float y);"));
|
||||
s.append(TString("vec2 min(vec2 x, vec2 y);"));
|
||||
s.append(TString("vec3 min(vec3 x, vec3 y);"));
|
||||
s.append(TString("vec4 min(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(float1, "min", float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "min", float2, float1);
|
||||
symbolTable.insertBuiltIn(float3, "min", float3, float1);
|
||||
symbolTable.insertBuiltIn(float4, "min", float4, float1);
|
||||
symbolTable.insertBuiltIn(float2, "min", float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "min", float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "min", float4, float4);
|
||||
|
||||
s.append(TString("float max(float x, float y);"));
|
||||
s.append(TString("vec2 max(vec2 x, float y);"));
|
||||
s.append(TString("vec3 max(vec3 x, float y);"));
|
||||
s.append(TString("vec4 max(vec4 x, float y);"));
|
||||
s.append(TString("vec2 max(vec2 x, vec2 y);"));
|
||||
s.append(TString("vec3 max(vec3 x, vec3 y);"));
|
||||
s.append(TString("vec4 max(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(float1, "max", float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "max", float2, float1);
|
||||
symbolTable.insertBuiltIn(float3, "max", float3, float1);
|
||||
symbolTable.insertBuiltIn(float4, "max", float4, float1);
|
||||
symbolTable.insertBuiltIn(float2, "max", float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "max", float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "max", float4, float4);
|
||||
|
||||
s.append(TString("float clamp(float x, float minVal, float maxVal);"));
|
||||
s.append(TString("vec2 clamp(vec2 x, float minVal, float maxVal);"));
|
||||
s.append(TString("vec3 clamp(vec3 x, float minVal, float maxVal);"));
|
||||
s.append(TString("vec4 clamp(vec4 x, float minVal, float maxVal);"));
|
||||
s.append(TString("vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);"));
|
||||
s.append(TString("vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);"));
|
||||
s.append(TString("vec4 clamp(vec4 x, vec4 minVal, vec4 maxVal);"));
|
||||
symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1);
|
||||
symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1);
|
||||
symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4);
|
||||
|
||||
s.append(TString("float mix(float x, float y, float a);"));
|
||||
s.append(TString("vec2 mix(vec2 x, vec2 y, float a);"));
|
||||
s.append(TString("vec3 mix(vec3 x, vec3 y, float a);"));
|
||||
s.append(TString("vec4 mix(vec4 x, vec4 y, float a);"));
|
||||
s.append(TString("vec2 mix(vec2 x, vec2 y, vec2 a);"));
|
||||
s.append(TString("vec3 mix(vec3 x, vec3 y, vec3 a);"));
|
||||
s.append(TString("vec4 mix(vec4 x, vec4 y, vec4 a);"));
|
||||
symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1);
|
||||
symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1);
|
||||
symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1);
|
||||
symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4);
|
||||
|
||||
s.append(TString("float step(float edge, float x);"));
|
||||
s.append(TString("vec2 step(vec2 edge, vec2 x);"));
|
||||
s.append(TString("vec3 step(vec3 edge, vec3 x);"));
|
||||
s.append(TString("vec4 step(vec4 edge, vec4 x);"));
|
||||
s.append(TString("vec2 step(float edge, vec2 x);"));
|
||||
s.append(TString("vec3 step(float edge, vec3 x);"));
|
||||
s.append(TString("vec4 step(float edge, vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "step", float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "step", float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "step", float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "step", float4, float4);
|
||||
symbolTable.insertBuiltIn(float2, "step", float1, float2);
|
||||
symbolTable.insertBuiltIn(float3, "step", float1, float3);
|
||||
symbolTable.insertBuiltIn(float4, "step", float1, float4);
|
||||
|
||||
s.append(TString("float smoothstep(float edge0, float edge1, float x);"));
|
||||
s.append(TString("vec2 smoothstep(vec2 edge0, vec2 edge1, vec2 x);"));
|
||||
s.append(TString("vec3 smoothstep(vec3 edge0, vec3 edge1, vec3 x);"));
|
||||
s.append(TString("vec4 smoothstep(vec4 edge0, vec4 edge1, vec4 x);"));
|
||||
s.append(TString("vec2 smoothstep(float edge0, float edge1, vec2 x);"));
|
||||
s.append(TString("vec3 smoothstep(float edge0, float edge1, vec3 x);"));
|
||||
s.append(TString("vec4 smoothstep(float edge0, float edge1, vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4);
|
||||
symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2);
|
||||
symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3);
|
||||
symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4);
|
||||
|
||||
//
|
||||
// Geometric Functions.
|
||||
//
|
||||
s.append(TString("float length(float x);"));
|
||||
s.append(TString("float length(vec2 x);"));
|
||||
s.append(TString("float length(vec3 x);"));
|
||||
s.append(TString("float length(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "length", float1);
|
||||
symbolTable.insertBuiltIn(float1, "length", float2);
|
||||
symbolTable.insertBuiltIn(float1, "length", float3);
|
||||
symbolTable.insertBuiltIn(float1, "length", float4);
|
||||
|
||||
s.append(TString("float distance(float p0, float p1);"));
|
||||
s.append(TString("float distance(vec2 p0, vec2 p1);"));
|
||||
s.append(TString("float distance(vec3 p0, vec3 p1);"));
|
||||
s.append(TString("float distance(vec4 p0, vec4 p1);"));
|
||||
symbolTable.insertBuiltIn(float1, "distance", float1, float1);
|
||||
symbolTable.insertBuiltIn(float1, "distance", float2, float2);
|
||||
symbolTable.insertBuiltIn(float1, "distance", float3, float3);
|
||||
symbolTable.insertBuiltIn(float1, "distance", float4, float4);
|
||||
|
||||
s.append(TString("float dot(float x, float y);"));
|
||||
s.append(TString("float dot(vec2 x, vec2 y);"));
|
||||
s.append(TString("float dot(vec3 x, vec3 y);"));
|
||||
s.append(TString("float dot(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(float1, "dot", float1, float1);
|
||||
symbolTable.insertBuiltIn(float1, "dot", float2, float2);
|
||||
symbolTable.insertBuiltIn(float1, "dot", float3, float3);
|
||||
symbolTable.insertBuiltIn(float1, "dot", float4, float4);
|
||||
|
||||
s.append(TString("vec3 cross(vec3 x, vec3 y);"));
|
||||
s.append(TString("float normalize(float x);"));
|
||||
s.append(TString("vec2 normalize(vec2 x);"));
|
||||
s.append(TString("vec3 normalize(vec3 x);"));
|
||||
s.append(TString("vec4 normalize(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float3, "cross", float3, float3);
|
||||
symbolTable.insertBuiltIn(float1, "normalize", float1);
|
||||
symbolTable.insertBuiltIn(float2, "normalize", float2);
|
||||
symbolTable.insertBuiltIn(float3, "normalize", float3);
|
||||
symbolTable.insertBuiltIn(float4, "normalize", float4);
|
||||
|
||||
s.append(TString("float faceforward(float N, float I, float Nref);"));
|
||||
s.append(TString("vec2 faceforward(vec2 N, vec2 I, vec2 Nref);"));
|
||||
s.append(TString("vec3 faceforward(vec3 N, vec3 I, vec3 Nref);"));
|
||||
s.append(TString("vec4 faceforward(vec4 N, vec4 I, vec4 Nref);"));
|
||||
symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4);
|
||||
|
||||
s.append(TString("float reflect(float I, float N);"));
|
||||
s.append(TString("vec2 reflect(vec2 I, vec2 N);"));
|
||||
s.append(TString("vec3 reflect(vec3 I, vec3 N);"));
|
||||
s.append(TString("vec4 reflect(vec4 I, vec4 N);"));
|
||||
symbolTable.insertBuiltIn(float1, "reflect", float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "reflect", float2, float2);
|
||||
symbolTable.insertBuiltIn(float3, "reflect", float3, float3);
|
||||
symbolTable.insertBuiltIn(float4, "reflect", float4, float4);
|
||||
|
||||
s.append(TString("float refract(float I, float N, float eta);"));
|
||||
s.append(TString("vec2 refract(vec2 I, vec2 N, float eta);"));
|
||||
s.append(TString("vec3 refract(vec3 I, vec3 N, float eta);"));
|
||||
s.append(TString("vec4 refract(vec4 I, vec4 N, float eta);"));
|
||||
symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1);
|
||||
symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1);
|
||||
symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1);
|
||||
symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1);
|
||||
|
||||
TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true);
|
||||
TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true);
|
||||
TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true);
|
||||
|
||||
//
|
||||
// Matrix Functions.
|
||||
//
|
||||
s.append(TString("mat2 matrixCompMult(mat2 x, mat2 y);"));
|
||||
s.append(TString("mat3 matrixCompMult(mat3 x, mat3 y);"));
|
||||
s.append(TString("mat4 matrixCompMult(mat4 x, mat4 y);"));
|
||||
symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2);
|
||||
symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3);
|
||||
symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4);
|
||||
|
||||
TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1);
|
||||
TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2);
|
||||
TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3);
|
||||
TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4);
|
||||
|
||||
//
|
||||
// Vector relational functions.
|
||||
//
|
||||
s.append(TString("bvec2 lessThan(vec2 x, vec2 y);"));
|
||||
s.append(TString("bvec3 lessThan(vec3 x, vec3 y);"));
|
||||
s.append(TString("bvec4 lessThan(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2);
|
||||
symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3);
|
||||
symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4);
|
||||
|
||||
s.append(TString("bvec2 lessThan(ivec2 x, ivec2 y);"));
|
||||
s.append(TString("bvec3 lessThan(ivec3 x, ivec3 y);"));
|
||||
s.append(TString("bvec4 lessThan(ivec4 x, ivec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2);
|
||||
symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3);
|
||||
symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4);
|
||||
|
||||
s.append(TString("bvec2 lessThanEqual(vec2 x, vec2 y);"));
|
||||
s.append(TString("bvec3 lessThanEqual(vec3 x, vec3 y);"));
|
||||
s.append(TString("bvec4 lessThanEqual(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2);
|
||||
symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3);
|
||||
symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4);
|
||||
|
||||
s.append(TString("bvec2 lessThanEqual(ivec2 x, ivec2 y);"));
|
||||
s.append(TString("bvec3 lessThanEqual(ivec3 x, ivec3 y);"));
|
||||
s.append(TString("bvec4 lessThanEqual(ivec4 x, ivec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2);
|
||||
symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3);
|
||||
symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4);
|
||||
|
||||
s.append(TString("bvec2 greaterThan(vec2 x, vec2 y);"));
|
||||
s.append(TString("bvec3 greaterThan(vec3 x, vec3 y);"));
|
||||
s.append(TString("bvec4 greaterThan(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2);
|
||||
symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3);
|
||||
symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4);
|
||||
|
||||
s.append(TString("bvec2 greaterThan(ivec2 x, ivec2 y);"));
|
||||
s.append(TString("bvec3 greaterThan(ivec3 x, ivec3 y);"));
|
||||
s.append(TString("bvec4 greaterThan(ivec4 x, ivec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2);
|
||||
symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3);
|
||||
symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4);
|
||||
|
||||
s.append(TString("bvec2 greaterThanEqual(vec2 x, vec2 y);"));
|
||||
s.append(TString("bvec3 greaterThanEqual(vec3 x, vec3 y);"));
|
||||
s.append(TString("bvec4 greaterThanEqual(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2);
|
||||
symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3);
|
||||
symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4);
|
||||
|
||||
s.append(TString("bvec2 greaterThanEqual(ivec2 x, ivec2 y);"));
|
||||
s.append(TString("bvec3 greaterThanEqual(ivec3 x, ivec3 y);"));
|
||||
s.append(TString("bvec4 greaterThanEqual(ivec4 x, ivec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2);
|
||||
symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3);
|
||||
symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4);
|
||||
|
||||
s.append(TString("bvec2 equal(vec2 x, vec2 y);"));
|
||||
s.append(TString("bvec3 equal(vec3 x, vec3 y);"));
|
||||
s.append(TString("bvec4 equal(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "equal", float2, float2);
|
||||
symbolTable.insertBuiltIn(bool3, "equal", float3, float3);
|
||||
symbolTable.insertBuiltIn(bool4, "equal", float4, float4);
|
||||
|
||||
s.append(TString("bvec2 equal(ivec2 x, ivec2 y);"));
|
||||
s.append(TString("bvec3 equal(ivec3 x, ivec3 y);"));
|
||||
s.append(TString("bvec4 equal(ivec4 x, ivec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "equal", int2, int2);
|
||||
symbolTable.insertBuiltIn(bool3, "equal", int3, int3);
|
||||
symbolTable.insertBuiltIn(bool4, "equal", int4, int4);
|
||||
|
||||
s.append(TString("bvec2 equal(bvec2 x, bvec2 y);"));
|
||||
s.append(TString("bvec3 equal(bvec3 x, bvec3 y);"));
|
||||
s.append(TString("bvec4 equal(bvec4 x, bvec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2);
|
||||
symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3);
|
||||
symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4);
|
||||
|
||||
s.append(TString("bvec2 notEqual(vec2 x, vec2 y);"));
|
||||
s.append(TString("bvec3 notEqual(vec3 x, vec3 y);"));
|
||||
s.append(TString("bvec4 notEqual(vec4 x, vec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2);
|
||||
symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3);
|
||||
symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4);
|
||||
|
||||
s.append(TString("bvec2 notEqual(ivec2 x, ivec2 y);"));
|
||||
s.append(TString("bvec3 notEqual(ivec3 x, ivec3 y);"));
|
||||
s.append(TString("bvec4 notEqual(ivec4 x, ivec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2);
|
||||
symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3);
|
||||
symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4);
|
||||
|
||||
s.append(TString("bvec2 notEqual(bvec2 x, bvec2 y);"));
|
||||
s.append(TString("bvec3 notEqual(bvec3 x, bvec3 y);"));
|
||||
s.append(TString("bvec4 notEqual(bvec4 x, bvec4 y);"));
|
||||
symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2);
|
||||
symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3);
|
||||
symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4);
|
||||
|
||||
s.append(TString("bool any(bvec2 x);"));
|
||||
s.append(TString("bool any(bvec3 x);"));
|
||||
s.append(TString("bool any(bvec4 x);"));
|
||||
symbolTable.insertBuiltIn(bool1, "any", bool2);
|
||||
symbolTable.insertBuiltIn(bool1, "any", bool3);
|
||||
symbolTable.insertBuiltIn(bool1, "any", bool4);
|
||||
|
||||
s.append(TString("bool all(bvec2 x);"));
|
||||
s.append(TString("bool all(bvec3 x);"));
|
||||
s.append(TString("bool all(bvec4 x);"));
|
||||
symbolTable.insertBuiltIn(bool1, "all", bool2);
|
||||
symbolTable.insertBuiltIn(bool1, "all", bool3);
|
||||
symbolTable.insertBuiltIn(bool1, "all", bool4);
|
||||
|
||||
s.append(TString("bvec2 not(bvec2 x);"));
|
||||
s.append(TString("bvec3 not(bvec3 x);"));
|
||||
s.append(TString("bvec4 not(bvec4 x);"));
|
||||
symbolTable.insertBuiltIn(bool2, "not", bool2);
|
||||
symbolTable.insertBuiltIn(bool3, "not", bool3);
|
||||
symbolTable.insertBuiltIn(bool4, "not", bool4);
|
||||
|
||||
TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1);
|
||||
TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1);
|
||||
|
||||
//
|
||||
// Texture Functions.
|
||||
// Texture Functions for GLSL ES 1.0
|
||||
//
|
||||
s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord);"));
|
||||
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord);"));
|
||||
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord);"));
|
||||
s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord);"));
|
||||
symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4);
|
||||
symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3);
|
||||
|
||||
if (resources.OES_EGL_image_external) {
|
||||
s.append(TString("vec4 texture2D(samplerExternalOES sampler, vec2 coord);"));
|
||||
s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec3 coord);"));
|
||||
s.append(TString("vec4 texture2DProj(samplerExternalOES sampler, vec4 coord);"));
|
||||
if (resources.OES_EGL_image_external)
|
||||
{
|
||||
TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1);
|
||||
|
||||
symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4);
|
||||
}
|
||||
|
||||
if (resources.ARB_texture_rectangle) {
|
||||
s.append(TString("vec4 texture2DRect(sampler2DRect sampler, vec2 coord);"));
|
||||
s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec3 coord);"));
|
||||
s.append(TString("vec4 texture2DRectProj(sampler2DRect sampler, vec4 coord);"));
|
||||
if (resources.ARB_texture_rectangle)
|
||||
{
|
||||
TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1);
|
||||
|
||||
symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4);
|
||||
}
|
||||
|
||||
//
|
||||
// Noise functions.
|
||||
//
|
||||
//s.append(TString("float noise1(float x);"));
|
||||
//s.append(TString("float noise1(vec2 x);"));
|
||||
//s.append(TString("float noise1(vec3 x);"));
|
||||
//s.append(TString("float noise1(vec4 x);"));
|
||||
if (type == SH_FRAGMENT_SHADER)
|
||||
{
|
||||
symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1);
|
||||
symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1);
|
||||
|
||||
//s.append(TString("vec2 noise2(float x);"));
|
||||
//s.append(TString("vec2 noise2(vec2 x);"));
|
||||
//s.append(TString("vec2 noise2(vec3 x);"));
|
||||
//s.append(TString("vec2 noise2(vec4 x);"));
|
||||
if (resources.OES_standard_derivatives)
|
||||
{
|
||||
symbolTable.insertBuiltIn(float1, "dFdx", float1);
|
||||
symbolTable.insertBuiltIn(float2, "dFdx", float2);
|
||||
symbolTable.insertBuiltIn(float3, "dFdx", float3);
|
||||
symbolTable.insertBuiltIn(float4, "dFdx", float4);
|
||||
|
||||
//s.append(TString("vec3 noise3(float x);"));
|
||||
//s.append(TString("vec3 noise3(vec2 x);"));
|
||||
//s.append(TString("vec3 noise3(vec3 x);"));
|
||||
//s.append(TString("vec3 noise3(vec4 x);"));
|
||||
symbolTable.insertBuiltIn(float1, "dFdy", float1);
|
||||
symbolTable.insertBuiltIn(float2, "dFdy", float2);
|
||||
symbolTable.insertBuiltIn(float3, "dFdy", float3);
|
||||
symbolTable.insertBuiltIn(float4, "dFdy", float4);
|
||||
|
||||
//s.append(TString("vec4 noise4(float x);"));
|
||||
//s.append(TString("vec4 noise4(vec2 x);"));
|
||||
//s.append(TString("vec4 noise4(vec3 x);"));
|
||||
//s.append(TString("vec4 noise4(vec4 x);"));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Prototypes for built-in functions seen by vertex shaders only.
|
||||
//
|
||||
//============================================================================
|
||||
static TString BuiltInFunctionsVertex(const ShBuiltInResources& resources)
|
||||
{
|
||||
TString s;
|
||||
|
||||
//
|
||||
// Geometric Functions.
|
||||
//
|
||||
//s.append(TString("vec4 ftransform();"));
|
||||
|
||||
//
|
||||
// Texture Functions.
|
||||
//
|
||||
s.append(TString("vec4 texture2DLod(sampler2D sampler, vec2 coord, float lod);"));
|
||||
s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec3 coord, float lod);"));
|
||||
s.append(TString("vec4 texture2DProjLod(sampler2D sampler, vec4 coord, float lod);"));
|
||||
s.append(TString("vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod);"));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Prototypes for built-in functions seen by fragment shaders only.
|
||||
//
|
||||
//============================================================================
|
||||
static TString BuiltInFunctionsFragment(const ShBuiltInResources& resources)
|
||||
{
|
||||
TString s;
|
||||
|
||||
//
|
||||
// Texture Functions.
|
||||
//
|
||||
s.append(TString("vec4 texture2D(sampler2D sampler, vec2 coord, float bias);"));
|
||||
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias);"));
|
||||
s.append(TString("vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias);"));
|
||||
s.append(TString("vec4 textureCube(samplerCube sampler, vec3 coord, float bias);"));
|
||||
|
||||
if (resources.OES_standard_derivatives) {
|
||||
s.append(TString("float dFdx(float p);"));
|
||||
s.append(TString("vec2 dFdx(vec2 p);"));
|
||||
s.append(TString("vec3 dFdx(vec3 p);"));
|
||||
s.append(TString("vec4 dFdx(vec4 p);"));
|
||||
|
||||
s.append(TString("float dFdy(float p);"));
|
||||
s.append(TString("vec2 dFdy(vec2 p);"));
|
||||
s.append(TString("vec3 dFdy(vec3 p);"));
|
||||
s.append(TString("vec4 dFdy(vec4 p);"));
|
||||
|
||||
s.append(TString("float fwidth(float p);"));
|
||||
s.append(TString("vec2 fwidth(vec2 p);"));
|
||||
s.append(TString("vec3 fwidth(vec3 p);"));
|
||||
s.append(TString("vec4 fwidth(vec4 p);"));
|
||||
symbolTable.insertBuiltIn(float1, "fwidth", float1);
|
||||
symbolTable.insertBuiltIn(float2, "fwidth", float2);
|
||||
symbolTable.insertBuiltIn(float3, "fwidth", float3);
|
||||
symbolTable.insertBuiltIn(float4, "fwidth", float4);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Standard uniforms.
|
||||
//
|
||||
//============================================================================
|
||||
static TString StandardUniforms()
|
||||
{
|
||||
TString s;
|
||||
if(type == SH_VERTEX_SHADER)
|
||||
{
|
||||
symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1);
|
||||
symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1);
|
||||
symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1);
|
||||
}
|
||||
|
||||
//
|
||||
// Depth range in window coordinates
|
||||
//
|
||||
s.append(TString("struct gl_DepthRangeParameters {"));
|
||||
s.append(TString(" highp float near;")); // n
|
||||
s.append(TString(" highp float far;")); // f
|
||||
s.append(TString(" highp float diff;")); // f - n
|
||||
s.append(TString("};"));
|
||||
s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
|
||||
TFieldList *fields = NewPoolTFieldList();
|
||||
TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"));
|
||||
TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"));
|
||||
TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"));
|
||||
fields->push_back(near);
|
||||
fields->push_back(far);
|
||||
fields->push_back(diff);
|
||||
TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
|
||||
TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true);
|
||||
symbolTable.insert(*depthRangeParameters);
|
||||
TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
|
||||
depthRange->setQualifier(EvqUniform);
|
||||
symbolTable.insert(*depthRange);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Default precision for vertex shaders.
|
||||
//
|
||||
//============================================================================
|
||||
static TString DefaultPrecisionVertex()
|
||||
{
|
||||
TString s;
|
||||
|
||||
s.append(TString("precision highp int;"));
|
||||
s.append(TString("precision highp float;"));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Default precision for fragment shaders.
|
||||
//
|
||||
//============================================================================
|
||||
static TString DefaultPrecisionFragment()
|
||||
{
|
||||
TString s;
|
||||
|
||||
s.append(TString("precision mediump int;"));
|
||||
// No default precision for float in fragment shaders
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Implementation dependent built-in constants.
|
||||
//
|
||||
//============================================================================
|
||||
static TString BuiltInConstants(ShShaderSpec spec, const ShBuiltInResources &resources)
|
||||
{
|
||||
TStringStream s;
|
||||
|
||||
s << "const int gl_MaxVertexAttribs = " << resources.MaxVertexAttribs << ";";
|
||||
s << "const int gl_MaxVertexUniformVectors = " << resources.MaxVertexUniformVectors << ";";
|
||||
|
||||
s << "const int gl_MaxVaryingVectors = " << resources.MaxVaryingVectors << ";";
|
||||
s << "const int gl_MaxVertexTextureImageUnits = " << resources.MaxVertexTextureImageUnits << ";";
|
||||
s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";";
|
||||
s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";";
|
||||
s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";";
|
||||
//
|
||||
// Implementation dependent built-in constants.
|
||||
//
|
||||
symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs);
|
||||
symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors);
|
||||
symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors);
|
||||
symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits);
|
||||
symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits);
|
||||
symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits);
|
||||
symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors);
|
||||
|
||||
if (spec != SH_CSS_SHADERS_SPEC)
|
||||
s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec,
|
||||
const ShBuiltInResources& resources)
|
||||
{
|
||||
switch (type) {
|
||||
case SH_FRAGMENT_SHADER:
|
||||
builtInStrings.push_back(DefaultPrecisionFragment());
|
||||
builtInStrings.push_back(BuiltInFunctionsCommon(resources));
|
||||
builtInStrings.push_back(BuiltInFunctionsFragment(resources));
|
||||
builtInStrings.push_back(StandardUniforms());
|
||||
break;
|
||||
|
||||
case SH_VERTEX_SHADER:
|
||||
builtInStrings.push_back(DefaultPrecisionVertex());
|
||||
builtInStrings.push_back(BuiltInFunctionsCommon(resources));
|
||||
builtInStrings.push_back(BuiltInFunctionsVertex(resources));
|
||||
builtInStrings.push_back(StandardUniforms());
|
||||
break;
|
||||
|
||||
default: assert(false && "Language not supported");
|
||||
{
|
||||
symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers);
|
||||
}
|
||||
|
||||
builtInStrings.push_back(BuiltInConstants(spec, resources));
|
||||
}
|
||||
|
||||
void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
|
||||
const ShBuiltInResources& resources,
|
||||
TSymbolTable& symbolTable)
|
||||
const ShBuiltInResources &resources,
|
||||
TSymbolTable &symbolTable)
|
||||
{
|
||||
//
|
||||
// First, insert some special built-in variables that are not in
|
||||
|
|
@ -539,6 +439,10 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
|
|||
if (spec != SH_CSS_SHADERS_SPEC) {
|
||||
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
|
||||
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
|
||||
if (resources.EXT_frag_depth) {
|
||||
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
|
||||
symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth");
|
||||
}
|
||||
} else {
|
||||
symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
|
||||
symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true)));
|
||||
|
|
@ -560,8 +464,6 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
|
|||
// expected to be resolved through a library of functions, versus as
|
||||
// operations.
|
||||
//
|
||||
symbolTable.relateToOperator("not", EOpVectorLogicalNot);
|
||||
|
||||
symbolTable.relateToOperator("matrixCompMult", EOpMul);
|
||||
|
||||
symbolTable.relateToOperator("equal", EOpVectorEqual);
|
||||
|
|
@ -612,6 +514,7 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
|
|||
|
||||
symbolTable.relateToOperator("any", EOpAny);
|
||||
symbolTable.relateToOperator("all", EOpAll);
|
||||
symbolTable.relateToOperator("not", EOpVectorLogicalNot);
|
||||
|
||||
// Map language-specific operators.
|
||||
switch(type) {
|
||||
|
|
@ -656,4 +559,6 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
|
|||
extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
|
||||
if (resources.EXT_draw_buffers)
|
||||
extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
|
||||
if (resources.EXT_frag_depth)
|
||||
extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
|
@ -11,19 +11,7 @@
|
|||
#include "compiler/ShHandle.h"
|
||||
#include "compiler/SymbolTable.h"
|
||||
|
||||
typedef TVector<TString> TBuiltInStrings;
|
||||
|
||||
class TBuiltIns {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||
|
||||
void initialize(ShShaderType type, ShShaderSpec spec,
|
||||
const ShBuiltInResources& resources);
|
||||
const TBuiltInStrings& getBuiltInStrings() { return builtInStrings; }
|
||||
|
||||
protected:
|
||||
TBuiltInStrings builtInStrings;
|
||||
};
|
||||
void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table);
|
||||
|
||||
void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
|
||||
const ShBuiltInResources& resources,
|
||||
|
|
|
|||
|
|
@ -10,25 +10,8 @@
|
|||
#include "compiler/InitializeParseContext.h"
|
||||
#include "compiler/osinclude.h"
|
||||
|
||||
OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
|
||||
|
||||
bool InitProcess()
|
||||
{
|
||||
if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
|
||||
//
|
||||
// Function is re-entrant.
|
||||
//
|
||||
return true;
|
||||
}
|
||||
|
||||
ThreadInitializeIndex = OS_AllocTLSIndex();
|
||||
|
||||
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!InitializePoolIndex()) {
|
||||
assert(0 && "InitProcess(): Failed to initalize global pool");
|
||||
return false;
|
||||
|
|
@ -39,77 +22,11 @@ bool InitProcess()
|
|||
return false;
|
||||
}
|
||||
|
||||
return InitThread();
|
||||
}
|
||||
|
||||
bool DetachProcess()
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
|
||||
return true;
|
||||
|
||||
success = DetachThread();
|
||||
|
||||
if (!FreeParseContextIndex())
|
||||
success = false;
|
||||
|
||||
FreePoolIndex();
|
||||
|
||||
OS_FreeTLSIndex(ThreadInitializeIndex);
|
||||
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool InitThread()
|
||||
{
|
||||
//
|
||||
// This function is re-entrant
|
||||
//
|
||||
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "InitThread(): Process hasn't been initalised.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
|
||||
return true;
|
||||
|
||||
InitializeGlobalPools();
|
||||
|
||||
if (!InitializeGlobalParseContext())
|
||||
return false;
|
||||
|
||||
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
|
||||
assert(0 && "InitThread(): Unable to set init flag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DetachThread()
|
||||
void DetachProcess()
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
|
||||
return true;
|
||||
|
||||
//
|
||||
// Function is re-entrant and this thread may not have been initalised.
|
||||
//
|
||||
if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
|
||||
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
|
||||
assert(0 && "DetachThread(): Unable to clear init flag.");
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!FreeParseContext())
|
||||
success = false;
|
||||
|
||||
FreeGlobalPools();
|
||||
}
|
||||
|
||||
return success;
|
||||
FreeParseContextIndex();
|
||||
FreePoolIndex();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@
|
|||
#define __INITIALIZEDLL_H
|
||||
|
||||
bool InitProcess();
|
||||
bool DetachProcess();
|
||||
|
||||
bool InitThread();
|
||||
bool DetachThread();
|
||||
void DetachProcess();
|
||||
|
||||
#endif // __INITIALIZEDLL_H
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#include "compiler/InitializeGLPosition.h"
|
||||
#include "compiler/debug.h"
|
||||
|
||||
bool InitializeGLPosition::visitAggregate(Visit visit, TIntermAggregate* node)
|
||||
{
|
||||
bool visitChildren = !mCodeInserted;
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpSequence: break;
|
||||
case EOpFunction:
|
||||
{
|
||||
// Function definition.
|
||||
ASSERT(visit == PreVisit);
|
||||
if (node->getName() == "main(")
|
||||
{
|
||||
TIntermSequence &sequence = node->getSequence();
|
||||
ASSERT((sequence.size() == 1) || (sequence.size() == 2));
|
||||
TIntermAggregate *body = NULL;
|
||||
if (sequence.size() == 1)
|
||||
{
|
||||
body = new TIntermAggregate(EOpSequence);
|
||||
sequence.push_back(body);
|
||||
}
|
||||
else
|
||||
{
|
||||
body = sequence[1]->getAsAggregate();
|
||||
}
|
||||
ASSERT(body);
|
||||
insertCode(body->getSequence());
|
||||
mCodeInserted = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: visitChildren = false; break;
|
||||
}
|
||||
return visitChildren;
|
||||
}
|
||||
|
||||
void InitializeGLPosition::insertCode(TIntermSequence& sequence)
|
||||
{
|
||||
TIntermBinary *binary = new TIntermBinary(EOpAssign);
|
||||
sequence.insert(sequence.begin(), binary);
|
||||
|
||||
TIntermSymbol *left = new TIntermSymbol(
|
||||
0, "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4));
|
||||
binary->setLeft(left);
|
||||
|
||||
ConstantUnion *u = new ConstantUnion[4];
|
||||
for (int ii = 0; ii < 3; ++ii)
|
||||
u[ii].setFConst(0.0f);
|
||||
u[3].setFConst(1.0f);
|
||||
TIntermConstantUnion *right = new TIntermConstantUnion(
|
||||
u, TType(EbtFloat, EbpUndefined, EvqConst, 4));
|
||||
binary->setRight(right);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#ifndef COMPILER_INITIALIZE_GL_POSITION_H_
|
||||
#define COMPILER_INITIALIZE_GL_POSITION_H_
|
||||
|
||||
#include "compiler/intermediate.h"
|
||||
|
||||
class InitializeGLPosition : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
InitializeGLPosition() : mCodeInserted(false) { }
|
||||
|
||||
protected:
|
||||
virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; }
|
||||
virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; }
|
||||
virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; }
|
||||
virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; }
|
||||
virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; }
|
||||
|
||||
virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
|
||||
|
||||
private:
|
||||
// Insert AST node in the beginning of main() for "gl_Position = vec4(0.0, 0.0, 0.0, 1.0);".
|
||||
void insertCode(TIntermSequence& sequence);
|
||||
|
||||
bool mCodeInserted;
|
||||
};
|
||||
|
||||
#endif // COMPILER_INITIALIZE_GL_POSITION_H_
|
||||
|
|
@ -7,8 +7,6 @@
|
|||
#ifndef __INITIALIZE_GLOBALS_INCLUDED_
|
||||
#define __INITIALIZE_GLOBALS_INCLUDED_
|
||||
|
||||
void InitializeGlobalPools();
|
||||
void FreeGlobalPools();
|
||||
bool InitializePoolIndex();
|
||||
void FreePoolIndex();
|
||||
|
||||
|
|
|
|||
|
|
@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
|
|||
|
||||
bool InitializeParseContextIndex()
|
||||
{
|
||||
if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
|
||||
return false;
|
||||
}
|
||||
assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX);
|
||||
|
||||
//
|
||||
// Allocate a TLS index.
|
||||
//
|
||||
GlobalParseContextIndex = OS_AllocTLSIndex();
|
||||
|
||||
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return GlobalParseContextIndex != OS_INVALID_TLS_INDEX;
|
||||
}
|
||||
|
||||
bool FreeParseContextIndex()
|
||||
void FreeParseContextIndex()
|
||||
{
|
||||
OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
|
||||
|
||||
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "FreeParseContextIndex(): Parse Context index not initalized");
|
||||
return false;
|
||||
}
|
||||
assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
|
||||
|
||||
OS_FreeTLSIndex(GlobalParseContextIndex);
|
||||
GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
|
||||
|
||||
return OS_FreeTLSIndex(tlsiIndex);
|
||||
}
|
||||
|
||||
bool InitializeGlobalParseContext()
|
||||
void SetGlobalParseContext(TParseContext* context)
|
||||
{
|
||||
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized");
|
||||
return false;
|
||||
}
|
||||
|
||||
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
|
||||
if (lpParseContext != 0) {
|
||||
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
|
||||
return false;
|
||||
}
|
||||
|
||||
TThreadParseContext *lpThreadData = new TThreadParseContext();
|
||||
if (lpThreadData == 0) {
|
||||
assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
|
||||
return false;
|
||||
}
|
||||
|
||||
lpThreadData->lpGlobalParseContext = 0;
|
||||
OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
|
||||
|
||||
return true;
|
||||
assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
|
||||
OS_SetTLSValue(GlobalParseContextIndex, context);
|
||||
}
|
||||
|
||||
bool FreeParseContext()
|
||||
TParseContext* GetGlobalParseContext()
|
||||
{
|
||||
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "FreeParseContext(): Parse Context index not initalized");
|
||||
return false;
|
||||
}
|
||||
|
||||
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
|
||||
if (lpParseContext)
|
||||
delete lpParseContext;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TParseContextPointer& GetGlobalParseContext()
|
||||
{
|
||||
//
|
||||
// Minimal error checking for speed
|
||||
//
|
||||
|
||||
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
|
||||
|
||||
return lpParseContext->lpGlobalParseContext;
|
||||
assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
|
||||
return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,19 +8,10 @@
|
|||
#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
|
||||
|
||||
bool InitializeParseContextIndex();
|
||||
bool FreeParseContextIndex();
|
||||
|
||||
bool InitializeGlobalParseContext();
|
||||
bool FreeParseContext();
|
||||
void FreeParseContextIndex();
|
||||
|
||||
struct TParseContext;
|
||||
typedef TParseContext* TParseContextPointer;
|
||||
extern TParseContextPointer& GetGlobalParseContext();
|
||||
#define GlobalParseContext GetGlobalParseContext()
|
||||
|
||||
typedef struct TThreadParseContextRec
|
||||
{
|
||||
TParseContext *lpGlobalParseContext;
|
||||
} TThreadParseContext;
|
||||
extern void SetGlobalParseContext(TParseContext* context);
|
||||
extern TParseContext* GetGlobalParseContext();
|
||||
|
||||
#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ const char* getOperatorString(TOperator op) {
|
|||
//
|
||||
// Returns the added node.
|
||||
//
|
||||
TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
|
||||
TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line)
|
||||
{
|
||||
TIntermSymbol* node = new TIntermSymbol(id, name, type);
|
||||
node->setLine(line);
|
||||
|
|
@ -144,7 +144,7 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType
|
|||
//
|
||||
// Returns the added node.
|
||||
//
|
||||
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
|
||||
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable)
|
||||
{
|
||||
switch (op) {
|
||||
case EOpEqual:
|
||||
|
|
@ -200,8 +200,6 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
|
|||
// one and promote it to the right type.
|
||||
//
|
||||
TIntermBinary* node = new TIntermBinary(op);
|
||||
if (line == 0)
|
||||
line = right->getLine();
|
||||
node->setLine(line);
|
||||
|
||||
node->setLeft(left);
|
||||
|
|
@ -230,15 +228,13 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
|
|||
//
|
||||
// Returns the added node.
|
||||
//
|
||||
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
|
||||
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
|
||||
{
|
||||
//
|
||||
// Like adding binary math, except the conversion can only go
|
||||
// from right to left.
|
||||
//
|
||||
TIntermBinary* node = new TIntermBinary(op);
|
||||
if (line == 0)
|
||||
line = left->getLine();
|
||||
node->setLine(line);
|
||||
|
||||
TIntermTyped* child = addConversion(op, left->getType(), right);
|
||||
|
|
@ -260,11 +256,9 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
|
|||
// Returns the added node.
|
||||
// The caller should set the type of the returned node.
|
||||
//
|
||||
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
|
||||
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line)
|
||||
{
|
||||
TIntermBinary* node = new TIntermBinary(op);
|
||||
if (line == 0)
|
||||
line = index->getLine();
|
||||
node->setLine(line);
|
||||
node->setLeft(base);
|
||||
node->setRight(index);
|
||||
|
|
@ -279,13 +273,13 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
|
|||
//
|
||||
// Returns the added node.
|
||||
//
|
||||
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
|
||||
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable)
|
||||
{
|
||||
TIntermUnary* node;
|
||||
TIntermTyped* child = childNode->getAsTyped();
|
||||
|
||||
if (child == 0) {
|
||||
infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
|
||||
infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -348,8 +342,6 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
|
|||
// Make a new node for the operator.
|
||||
//
|
||||
node = new TIntermUnary(op);
|
||||
if (line == 0)
|
||||
line = child->getLine();
|
||||
node->setLine(line);
|
||||
node->setOperand(child);
|
||||
|
||||
|
|
@ -376,7 +368,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
|
|||
// Returns an aggregate node, which could be the one passed in if
|
||||
// it was already an aggregate but no operator was set.
|
||||
//
|
||||
TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
|
||||
TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line)
|
||||
{
|
||||
TIntermAggregate* aggNode;
|
||||
|
||||
|
|
@ -391,8 +383,6 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat
|
|||
//
|
||||
aggNode = new TIntermAggregate();
|
||||
aggNode->getSequence().push_back(node);
|
||||
if (line == 0)
|
||||
line = node->getLine();
|
||||
}
|
||||
} else
|
||||
aggNode = new TIntermAggregate();
|
||||
|
|
@ -401,8 +391,7 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat
|
|||
// Set the operator.
|
||||
//
|
||||
aggNode->setOp(op);
|
||||
if (line != 0)
|
||||
aggNode->setLine(line);
|
||||
aggNode->setLine(line);
|
||||
|
||||
return aggNode;
|
||||
}
|
||||
|
|
@ -491,7 +480,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||
case EbtInt: newOp = EOpConvIntToFloat; break;
|
||||
case EbtBool: newOp = EOpConvBoolToFloat; break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
|
@ -500,7 +489,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||
case EbtInt: newOp = EOpConvIntToBool; break;
|
||||
case EbtFloat: newOp = EOpConvFloatToBool; break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
|
@ -509,12 +498,12 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||
case EbtBool: newOp = EOpConvBoolToInt; break;
|
||||
case EbtFloat: newOp = EOpConvFloatToInt; break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Bad promotion type", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -534,7 +523,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||
// Returns the resulting aggregate, unless 0 was passed in for
|
||||
// both existing nodes.
|
||||
//
|
||||
TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
|
||||
TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line)
|
||||
{
|
||||
if (left == 0 && right == 0)
|
||||
return 0;
|
||||
|
|
@ -551,8 +540,7 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
|
|||
if (right)
|
||||
aggNode->getSequence().push_back(right);
|
||||
|
||||
if (line != 0)
|
||||
aggNode->setLine(line);
|
||||
aggNode->setLine(line);
|
||||
|
||||
return aggNode;
|
||||
}
|
||||
|
|
@ -562,18 +550,14 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
|
|||
//
|
||||
// Returns an aggregate, unless 0 was passed in for the existing node.
|
||||
//
|
||||
TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
|
||||
TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line)
|
||||
{
|
||||
if (node == 0)
|
||||
return 0;
|
||||
|
||||
TIntermAggregate* aggNode = new TIntermAggregate;
|
||||
aggNode->getSequence().push_back(node);
|
||||
|
||||
if (line != 0)
|
||||
aggNode->setLine(line);
|
||||
else
|
||||
aggNode->setLine(node->getLine());
|
||||
aggNode->setLine(line);
|
||||
|
||||
return aggNode;
|
||||
}
|
||||
|
|
@ -585,7 +569,7 @@ TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc lin
|
|||
//
|
||||
// Returns the selection node created.
|
||||
//
|
||||
TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
|
||||
TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line)
|
||||
{
|
||||
//
|
||||
// For compile time constant selections, prune the code and
|
||||
|
|
@ -606,7 +590,7 @@ TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nod
|
|||
}
|
||||
|
||||
|
||||
TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
|
||||
TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
|
||||
{
|
||||
if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
|
||||
return right;
|
||||
|
|
@ -626,7 +610,7 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T
|
|||
//
|
||||
// Returns the selection node created, or 0 if one could not be.
|
||||
//
|
||||
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
|
||||
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line)
|
||||
{
|
||||
//
|
||||
// Get compatible types.
|
||||
|
|
@ -669,7 +653,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
|
|||
// Returns the constant union node created.
|
||||
//
|
||||
|
||||
TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
|
||||
TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line)
|
||||
{
|
||||
TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
|
||||
node->setLine(line);
|
||||
|
|
@ -677,7 +661,7 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayP
|
|||
return node;
|
||||
}
|
||||
|
||||
TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
|
||||
TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line)
|
||||
{
|
||||
|
||||
TIntermAggregate* node = new TIntermAggregate(EOpSequence);
|
||||
|
|
@ -700,7 +684,7 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
|
|||
//
|
||||
// Create loop nodes.
|
||||
//
|
||||
TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
|
||||
TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line)
|
||||
{
|
||||
TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
|
||||
node->setLine(line);
|
||||
|
|
@ -711,12 +695,12 @@ TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTy
|
|||
//
|
||||
// Add branches.
|
||||
//
|
||||
TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
|
||||
TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line)
|
||||
{
|
||||
return addBranch(branchOp, 0, line);
|
||||
}
|
||||
|
||||
TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
|
||||
TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line)
|
||||
{
|
||||
TIntermBranch* node = new TIntermBranch(branchOp, expression);
|
||||
node->setLine(line);
|
||||
|
|
@ -861,7 +845,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
|
|||
{
|
||||
// This function only handles scalars, vectors, and matrices.
|
||||
if (left->isArray() || right->isArray()) {
|
||||
infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -966,7 +950,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
|
|||
setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
|
||||
}
|
||||
} else {
|
||||
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -995,7 +979,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
|
|||
setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
|
||||
}
|
||||
} else {
|
||||
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1035,23 +1019,22 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
|
|||
|
||||
bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
|
||||
{
|
||||
const TTypeList* fields = leftNodeType.getStruct();
|
||||
const TFieldList& fields = leftNodeType.getStruct()->fields();
|
||||
|
||||
size_t structSize = fields->size();
|
||||
int index = 0;
|
||||
size_t structSize = fields.size();
|
||||
size_t index = 0;
|
||||
|
||||
for (size_t j = 0; j < structSize; j++) {
|
||||
int size = (*fields)[j].type->getObjectSize();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if ((*fields)[j].type->getBasicType() == EbtStruct) {
|
||||
if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
|
||||
size_t size = fields[j]->type()->getObjectSize();
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (fields[j]->type()->getBasicType() == EbtStruct) {
|
||||
if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
|
||||
return false;
|
||||
} else {
|
||||
if (leftUnionArray[index] != rightUnionArray[index])
|
||||
return false;
|
||||
index++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -1063,10 +1046,10 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray,
|
|||
TType typeWithoutArrayness = leftNodeType;
|
||||
typeWithoutArrayness.clearArrayness();
|
||||
|
||||
int arraySize = leftNodeType.getArraySize();
|
||||
size_t arraySize = leftNodeType.getArraySize();
|
||||
|
||||
for (int i = 0; i < arraySize; ++i) {
|
||||
int offset = typeWithoutArrayness.getObjectSize() * i;
|
||||
for (size_t i = 0; i < arraySize; ++i) {
|
||||
size_t offset = typeWithoutArrayness.getObjectSize() * i;
|
||||
if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1086,7 +1069,7 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray,
|
|||
TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
|
||||
{
|
||||
ConstantUnion *unionArray = getUnionArrayPointer();
|
||||
int objectSize = getType().getObjectSize();
|
||||
size_t objectSize = getType().getObjectSize();
|
||||
|
||||
if (constantNode) { // binary operations
|
||||
TIntermConstantUnion *node = constantNode->getAsConstantUnion();
|
||||
|
|
@ -1096,13 +1079,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
// for a case like float f = 1.2 + vec4(2,3,4,5);
|
||||
if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
|
||||
rightUnionArray = new ConstantUnion[objectSize];
|
||||
for (int i = 0; i < objectSize; ++i)
|
||||
for (size_t i = 0; i < objectSize; ++i)
|
||||
rightUnionArray[i] = *node->getUnionArrayPointer();
|
||||
returnType = getType();
|
||||
} else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
|
||||
// for a case like float f = vec4(2,3,4,5) + 1.2;
|
||||
unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
|
||||
for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
|
||||
for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
|
||||
unionArray[i] = *getUnionArrayPointer();
|
||||
returnType = node->getType();
|
||||
objectSize = constantNode->getType().getObjectSize();
|
||||
|
|
@ -1116,14 +1099,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
case EOpAdd:
|
||||
tempConstArray = new ConstantUnion[objectSize];
|
||||
{// support MSVC++6.0
|
||||
for (int i = 0; i < objectSize; i++)
|
||||
for (size_t i = 0; i < objectSize; i++)
|
||||
tempConstArray[i] = unionArray[i] + rightUnionArray[i];
|
||||
}
|
||||
break;
|
||||
case EOpSub:
|
||||
tempConstArray = new ConstantUnion[objectSize];
|
||||
{// support MSVC++6.0
|
||||
for (int i = 0; i < objectSize; i++)
|
||||
for (size_t i = 0; i < objectSize; i++)
|
||||
tempConstArray[i] = unionArray[i] - rightUnionArray[i];
|
||||
}
|
||||
break;
|
||||
|
|
@ -1133,13 +1116,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
case EOpMatrixTimesScalar:
|
||||
tempConstArray = new ConstantUnion[objectSize];
|
||||
{// support MSVC++6.0
|
||||
for (int i = 0; i < objectSize; i++)
|
||||
for (size_t i = 0; i < objectSize; i++)
|
||||
tempConstArray[i] = unionArray[i] * rightUnionArray[i];
|
||||
}
|
||||
break;
|
||||
case EOpMatrixTimesMatrix:
|
||||
if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
|
||||
infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply");
|
||||
return 0;
|
||||
}
|
||||
{// support MSVC++6.0
|
||||
|
|
@ -1158,11 +1141,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
case EOpDiv:
|
||||
tempConstArray = new ConstantUnion[objectSize];
|
||||
{// support MSVC++6.0
|
||||
for (int i = 0; i < objectSize; i++) {
|
||||
for (size_t i = 0; i < objectSize; i++) {
|
||||
switch (getType().getBasicType()) {
|
||||
case EbtFloat:
|
||||
if (rightUnionArray[i] == 0.0f) {
|
||||
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
|
||||
infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
|
||||
tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
|
||||
} else
|
||||
tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
|
||||
|
|
@ -1170,13 +1153,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
|
||||
case EbtInt:
|
||||
if (rightUnionArray[i] == 0) {
|
||||
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
|
||||
infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
|
||||
tempConstArray[i].setIConst(INT_MAX);
|
||||
} else
|
||||
tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
|
||||
break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\"");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1185,7 +1168,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
|
||||
case EOpMatrixTimesVector:
|
||||
if (node->getBasicType() != EbtFloat) {
|
||||
infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector");
|
||||
return 0;
|
||||
}
|
||||
tempConstArray = new ConstantUnion[getNominalSize()];
|
||||
|
|
@ -1206,7 +1189,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
|
||||
case EOpVectorTimesMatrix:
|
||||
if (getType().getBasicType() != EbtFloat) {
|
||||
infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1224,7 +1207,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
|
||||
tempConstArray = new ConstantUnion[objectSize];
|
||||
{// support MSVC++6.0
|
||||
for (int i = 0; i < objectSize; i++)
|
||||
for (size_t i = 0; i < objectSize; i++)
|
||||
tempConstArray[i] = unionArray[i] && rightUnionArray[i];
|
||||
}
|
||||
break;
|
||||
|
|
@ -1232,7 +1215,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
|
||||
tempConstArray = new ConstantUnion[objectSize];
|
||||
{// support MSVC++6.0
|
||||
for (int i = 0; i < objectSize; i++)
|
||||
for (size_t i = 0; i < objectSize; i++)
|
||||
tempConstArray[i] = unionArray[i] || rightUnionArray[i];
|
||||
}
|
||||
break;
|
||||
|
|
@ -1240,7 +1223,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
case EOpLogicalXor:
|
||||
tempConstArray = new ConstantUnion[objectSize];
|
||||
{// support MSVC++6.0
|
||||
for (int i = 0; i < objectSize; i++)
|
||||
for (size_t i = 0; i < objectSize; i++)
|
||||
switch (getType().getBasicType()) {
|
||||
case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
|
||||
default: assert(false && "Default missing");
|
||||
|
|
@ -1286,7 +1269,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
|
||||
boolNodeFlag = true;
|
||||
} else {
|
||||
for (int i = 0; i < objectSize; i++) {
|
||||
for (size_t i = 0; i < objectSize; i++) {
|
||||
if (unionArray[i] != rightUnionArray[i]) {
|
||||
boolNodeFlag = true;
|
||||
break; // break out of for loop
|
||||
|
|
@ -1312,7 +1295,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
|
||||
boolNodeFlag = true;
|
||||
} else {
|
||||
for (int i = 0; i < objectSize; i++) {
|
||||
for (size_t i = 0; i < objectSize; i++) {
|
||||
if (unionArray[i] == rightUnionArray[i]) {
|
||||
boolNodeFlag = true;
|
||||
break; // break out of for loop
|
||||
|
|
@ -1334,7 +1317,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
return tempNode;
|
||||
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding");
|
||||
return 0;
|
||||
}
|
||||
tempNode = new TIntermConstantUnion(tempConstArray, returnType);
|
||||
|
|
@ -1347,14 +1330,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
//
|
||||
TIntermConstantUnion *newNode = 0;
|
||||
ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
|
||||
for (int i = 0; i < objectSize; i++) {
|
||||
for (size_t i = 0; i < objectSize; i++) {
|
||||
switch(op) {
|
||||
case EOpNegative:
|
||||
switch (getType().getBasicType()) {
|
||||
case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
|
||||
case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1362,7 +1345,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
switch (getType().getBasicType()) {
|
||||
case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
|
||||
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1378,11 +1361,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
|
|||
|
||||
TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
|
||||
{
|
||||
int size = node->getType().getObjectSize();
|
||||
size_t size = node->getType().getObjectSize();
|
||||
|
||||
ConstantUnion *leftUnionArray = new ConstantUnion[size];
|
||||
|
||||
for (int i=0; i < size; i++) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
|
||||
switch (promoteTo) {
|
||||
case EbtFloat:
|
||||
|
|
@ -1397,7 +1380,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
|
|||
leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
|
||||
break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1413,7 +1396,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
|
|||
leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
|
||||
break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1429,13 +1412,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
|
|||
leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
|
||||
break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,3 +19,17 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void TOutputGLSL::visitSymbol(TIntermSymbol* node)
|
||||
{
|
||||
TInfoSinkBase& out = objSink();
|
||||
|
||||
if (node->getSymbol() == "gl_FragDepthEXT")
|
||||
{
|
||||
out << "gl_FragDepth";
|
||||
}
|
||||
else
|
||||
{
|
||||
TOutputGLSLBase::visitSymbol(node);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual bool writeVariablePrecision(TPrecision);
|
||||
virtual void visitSymbol(TIntermSymbol* node);
|
||||
};
|
||||
|
||||
#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
|
||||
|
|
|
|||
|
|
@ -79,25 +79,9 @@ void TOutputGLSLBase::writeVariableType(const TType& type)
|
|||
if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
|
||||
out << type.getQualifierString() << " ";
|
||||
// Declare the struct if we have not done so already.
|
||||
if ((type.getBasicType() == EbtStruct) &&
|
||||
(mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
|
||||
if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
|
||||
{
|
||||
out << "struct " << hashName(type.getTypeName()) << "{\n";
|
||||
const TTypeList* structure = type.getStruct();
|
||||
ASSERT(structure != NULL);
|
||||
for (size_t i = 0; i < structure->size(); ++i)
|
||||
{
|
||||
const TType* fieldType = (*structure)[i].type;
|
||||
ASSERT(fieldType != NULL);
|
||||
if (writeVariablePrecision(fieldType->getPrecision()))
|
||||
out << " ";
|
||||
out << getTypeName(*fieldType) << " " << hashName(fieldType->getFieldName());
|
||||
if (fieldType->isArray())
|
||||
out << arrayBrackets(*fieldType);
|
||||
out << ";\n";
|
||||
}
|
||||
out << "}";
|
||||
mDeclaredStructs.insert(type.getTypeName());
|
||||
declareStruct(type.getStruct());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -138,24 +122,25 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
|
|||
|
||||
if (type.getBasicType() == EbtStruct)
|
||||
{
|
||||
out << hashName(type.getTypeName()) << "(";
|
||||
const TTypeList* structure = type.getStruct();
|
||||
ASSERT(structure != NULL);
|
||||
for (size_t i = 0; i < structure->size(); ++i)
|
||||
const TStructure* structure = type.getStruct();
|
||||
out << hashName(structure->name()) << "(";
|
||||
|
||||
const TFieldList& fields = structure->fields();
|
||||
for (size_t i = 0; i < fields.size(); ++i)
|
||||
{
|
||||
const TType* fieldType = (*structure)[i].type;
|
||||
const TType* fieldType = fields[i]->type();
|
||||
ASSERT(fieldType != NULL);
|
||||
pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
|
||||
if (i != structure->size() - 1) out << ", ";
|
||||
if (i != fields.size() - 1) out << ", ";
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
int size = type.getObjectSize();
|
||||
size_t size = type.getObjectSize();
|
||||
bool writeType = size > 1;
|
||||
if (writeType) out << getTypeName(type) << "(";
|
||||
for (int i = 0; i < size; ++i, ++pConstUnion)
|
||||
for (size_t i = 0; i < size; ++i, ++pConstUnion)
|
||||
{
|
||||
switch (pConstUnion->getType())
|
||||
{
|
||||
|
|
@ -260,12 +245,18 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
|
|||
case EOpIndexDirectStruct:
|
||||
if (visit == InVisit)
|
||||
{
|
||||
// Here we are writing out "foo.bar", where "foo" is struct
|
||||
// and "bar" is field. In AST, it is represented as a binary
|
||||
// node, where left child represents "foo" and right child "bar".
|
||||
// The node itself represents ".". The struct field "bar" is
|
||||
// actually stored as an index into TStructure::fields.
|
||||
out << ".";
|
||||
// TODO(alokp): ASSERT
|
||||
TString fieldName = node->getType().getFieldName();
|
||||
const TStructure* structure = node->getLeft()->getType().getStruct();
|
||||
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
|
||||
const TField* field = structure->fields()[index->getIConst(0)];
|
||||
|
||||
const TType& structType = node->getLeft()->getType();
|
||||
if (!mSymbolTable.findBuiltIn(structType.getTypeName()))
|
||||
TString fieldName = field->name();
|
||||
if (!mSymbolTable.findBuiltIn(structure->name()))
|
||||
fieldName = hashName(fieldName);
|
||||
|
||||
out << fieldName;
|
||||
|
|
@ -596,7 +587,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
|
|||
{
|
||||
const TType& type = node->getType();
|
||||
ASSERT(type.getBasicType() == EbtStruct);
|
||||
out << hashName(type.getTypeName()) << "(";
|
||||
out << hashName(type.getStruct()->name()) << "(";
|
||||
}
|
||||
else if (visit == InVisit)
|
||||
{
|
||||
|
|
@ -765,7 +756,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type)
|
|||
else
|
||||
{
|
||||
if (type.getBasicType() == EbtStruct)
|
||||
out << hashName(type.getTypeName());
|
||||
out << hashName(type.getStruct()->name());
|
||||
else
|
||||
out << type.getBasicString();
|
||||
}
|
||||
|
|
@ -798,3 +789,29 @@ TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
|
|||
return name;
|
||||
return hashName(name);
|
||||
}
|
||||
|
||||
bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
|
||||
{
|
||||
return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end();
|
||||
}
|
||||
|
||||
void TOutputGLSLBase::declareStruct(const TStructure* structure)
|
||||
{
|
||||
TInfoSinkBase& out = objSink();
|
||||
|
||||
out << "struct " << hashName(structure->name()) << "{\n";
|
||||
const TFieldList& fields = structure->fields();
|
||||
for (size_t i = 0; i < fields.size(); ++i)
|
||||
{
|
||||
const TField* field = fields[i];
|
||||
if (writeVariablePrecision(field->type()->getPrecision()))
|
||||
out << " ";
|
||||
out << getTypeName(*field->type()) << " " << hashName(field->name());
|
||||
if (field->type()->isArray())
|
||||
out << arrayBrackets(*field->type());
|
||||
out << ";\n";
|
||||
}
|
||||
out << "}";
|
||||
|
||||
mDeclaredStructs.insert(structure->name());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ protected:
|
|||
TString hashFunctionName(const TString& mangled_name);
|
||||
|
||||
private:
|
||||
bool structDeclared(const TStructure* structure) const;
|
||||
void declareStruct(const TStructure* structure);
|
||||
|
||||
TInfoSinkBase& mObjSink;
|
||||
bool mDeclaringVariables;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc
|
|||
mUsesPointCoord = false;
|
||||
mUsesFrontFacing = false;
|
||||
mUsesPointSize = false;
|
||||
mUsesFragDepth = false;
|
||||
mUsesXor = false;
|
||||
mUsesMod1 = false;
|
||||
mUsesMod2v = false;
|
||||
|
|
@ -67,18 +68,6 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc
|
|||
mUsesFaceforward2 = false;
|
||||
mUsesFaceforward3 = false;
|
||||
mUsesFaceforward4 = false;
|
||||
mUsesEqualMat2 = false;
|
||||
mUsesEqualMat3 = false;
|
||||
mUsesEqualMat4 = false;
|
||||
mUsesEqualVec2 = false;
|
||||
mUsesEqualVec3 = false;
|
||||
mUsesEqualVec4 = false;
|
||||
mUsesEqualIVec2 = false;
|
||||
mUsesEqualIVec3 = false;
|
||||
mUsesEqualIVec4 = false;
|
||||
mUsesEqualBVec2 = false;
|
||||
mUsesEqualBVec3 = false;
|
||||
mUsesEqualBVec4 = false;
|
||||
mUsesAtan2_1 = false;
|
||||
mUsesAtan2_2 = false;
|
||||
mUsesAtan2_3 = false;
|
||||
|
|
@ -210,9 +199,9 @@ void OutputHLSL::header()
|
|||
if (shaderType == SH_FRAGMENT_SHADER)
|
||||
{
|
||||
TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
|
||||
bool usingMRTExtension = iter != mContext.extensionBehavior().end() && iter->second == EBhEnable;
|
||||
const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
|
||||
|
||||
unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
|
||||
const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
|
||||
|
||||
out << "// Varyings\n";
|
||||
out << varyings;
|
||||
|
|
@ -230,6 +219,11 @@ void OutputHLSL::header()
|
|||
}
|
||||
out << "};\n";
|
||||
|
||||
if (mUsesFragDepth)
|
||||
{
|
||||
out << "static float gl_Depth = 0.0;\n";
|
||||
}
|
||||
|
||||
if (mUsesFragCoord)
|
||||
{
|
||||
out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
|
||||
|
|
@ -844,6 +838,16 @@ void OutputHLSL::header()
|
|||
out << "#define GL_USES_POINT_SIZE\n";
|
||||
}
|
||||
|
||||
if (mUsesFragDepth)
|
||||
{
|
||||
out << "#define GL_USES_FRAG_DEPTH\n";
|
||||
}
|
||||
|
||||
if (mUsesDepthRange)
|
||||
{
|
||||
out << "#define GL_USES_DEPTH_RANGE\n";
|
||||
}
|
||||
|
||||
if (mUsesXor)
|
||||
{
|
||||
out << "bool xor(bool p, bool q)\n"
|
||||
|
|
@ -980,108 +984,6 @@ void OutputHLSL::header()
|
|||
"\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualMat2)
|
||||
{
|
||||
out << "bool equal(float2x2 m, float2x2 n)\n"
|
||||
"{\n"
|
||||
" return m[0][0] == n[0][0] && m[0][1] == n[0][1] &&\n"
|
||||
" m[1][0] == n[1][0] && m[1][1] == n[1][1];\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualMat3)
|
||||
{
|
||||
out << "bool equal(float3x3 m, float3x3 n)\n"
|
||||
"{\n"
|
||||
" return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] &&\n"
|
||||
" m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] &&\n"
|
||||
" m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2];\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualMat4)
|
||||
{
|
||||
out << "bool equal(float4x4 m, float4x4 n)\n"
|
||||
"{\n"
|
||||
" return m[0][0] == n[0][0] && m[0][1] == n[0][1] && m[0][2] == n[0][2] && m[0][3] == n[0][3] &&\n"
|
||||
" m[1][0] == n[1][0] && m[1][1] == n[1][1] && m[1][2] == n[1][2] && m[1][3] == n[1][3] &&\n"
|
||||
" m[2][0] == n[2][0] && m[2][1] == n[2][1] && m[2][2] == n[2][2] && m[2][3] == n[2][3] &&\n"
|
||||
" m[3][0] == n[3][0] && m[3][1] == n[3][1] && m[3][2] == n[3][2] && m[3][3] == n[3][3];\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualVec2)
|
||||
{
|
||||
out << "bool equal(float2 v, float2 u)\n"
|
||||
"{\n"
|
||||
" return v.x == u.x && v.y == u.y;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualVec3)
|
||||
{
|
||||
out << "bool equal(float3 v, float3 u)\n"
|
||||
"{\n"
|
||||
" return v.x == u.x && v.y == u.y && v.z == u.z;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualVec4)
|
||||
{
|
||||
out << "bool equal(float4 v, float4 u)\n"
|
||||
"{\n"
|
||||
" return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualIVec2)
|
||||
{
|
||||
out << "bool equal(int2 v, int2 u)\n"
|
||||
"{\n"
|
||||
" return v.x == u.x && v.y == u.y;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualIVec3)
|
||||
{
|
||||
out << "bool equal(int3 v, int3 u)\n"
|
||||
"{\n"
|
||||
" return v.x == u.x && v.y == u.y && v.z == u.z;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualIVec4)
|
||||
{
|
||||
out << "bool equal(int4 v, int4 u)\n"
|
||||
"{\n"
|
||||
" return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualBVec2)
|
||||
{
|
||||
out << "bool equal(bool2 v, bool2 u)\n"
|
||||
"{\n"
|
||||
" return v.x == u.x && v.y == u.y;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualBVec3)
|
||||
{
|
||||
out << "bool equal(bool3 v, bool3 u)\n"
|
||||
"{\n"
|
||||
" return v.x == u.x && v.y == u.y && v.z == u.z;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesEqualBVec4)
|
||||
{
|
||||
out << "bool equal(bool4 v, bool4 u)\n"
|
||||
"{\n"
|
||||
" return v.x == u.x && v.y == u.y && v.z == u.z && v.w == u.w;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
if (mUsesAtan2_1)
|
||||
{
|
||||
out << "float atanyx(float y, float x)\n"
|
||||
|
|
@ -1166,6 +1068,11 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
|
|||
mUsesPointSize = true;
|
||||
out << name;
|
||||
}
|
||||
else if (name == "gl_FragDepthEXT")
|
||||
{
|
||||
mUsesFragDepth = true;
|
||||
out << "gl_Depth";
|
||||
}
|
||||
else
|
||||
{
|
||||
TQualifier qualifier = node->getQualifier();
|
||||
|
|
@ -1275,7 +1182,10 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
|
|||
case EOpIndexDirectStruct:
|
||||
if (visit == InVisit)
|
||||
{
|
||||
out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType());
|
||||
const TStructure* structure = node->getLeft()->getType().getStruct();
|
||||
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
|
||||
const TField* field = structure->fields()[index->getIConst(0)];
|
||||
out << "." + decorateField(field->name(), node->getLeft()->getType());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1344,18 +1254,18 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
|
|||
out << "!(";
|
||||
}
|
||||
|
||||
const TTypeList *fields = node->getLeft()->getType().getStruct();
|
||||
const TFieldList &fields = node->getLeft()->getType().getStruct()->fields();
|
||||
|
||||
for (size_t i = 0; i < fields->size(); i++)
|
||||
for (size_t i = 0; i < fields.size(); i++)
|
||||
{
|
||||
const TType *fieldType = (*fields)[i].type;
|
||||
const TField *field = fields[i];
|
||||
|
||||
node->getLeft()->traverse(this);
|
||||
out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == ";
|
||||
out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == ";
|
||||
node->getRight()->traverse(this);
|
||||
out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType());
|
||||
out << "." + decorateField(field->name(), node->getLeft()->getType());
|
||||
|
||||
if (i < fields->size() - 1)
|
||||
if (i < fields.size() - 1)
|
||||
{
|
||||
out << " && ";
|
||||
}
|
||||
|
|
@ -1367,59 +1277,15 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (node->getLeft()->isMatrix())
|
||||
{
|
||||
switch (node->getLeft()->getNominalSize())
|
||||
{
|
||||
case 2: mUsesEqualMat2 = true; break;
|
||||
case 3: mUsesEqualMat3 = true; break;
|
||||
case 4: mUsesEqualMat4 = true; break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
else if (node->getLeft()->isVector())
|
||||
{
|
||||
switch (node->getLeft()->getBasicType())
|
||||
{
|
||||
case EbtFloat:
|
||||
switch (node->getLeft()->getNominalSize())
|
||||
{
|
||||
case 2: mUsesEqualVec2 = true; break;
|
||||
case 3: mUsesEqualVec3 = true; break;
|
||||
case 4: mUsesEqualVec4 = true; break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
case EbtInt:
|
||||
switch (node->getLeft()->getNominalSize())
|
||||
{
|
||||
case 2: mUsesEqualIVec2 = true; break;
|
||||
case 3: mUsesEqualIVec3 = true; break;
|
||||
case 4: mUsesEqualIVec4 = true; break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
case EbtBool:
|
||||
switch (node->getLeft()->getNominalSize())
|
||||
{
|
||||
case 2: mUsesEqualBVec2 = true; break;
|
||||
case 3: mUsesEqualBVec3 = true; break;
|
||||
case 4: mUsesEqualBVec4 = true; break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
else UNREACHABLE();
|
||||
ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector());
|
||||
|
||||
if (node->getOp() == EOpEqual)
|
||||
{
|
||||
outputTriplet(visit, "equal(", ", ", ")");
|
||||
outputTriplet(visit, "all(", " == ", ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
outputTriplet(visit, "!equal(", ", ", ")");
|
||||
outputTriplet(visit, "!all(", " == ", ")");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -1561,7 +1427,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
|
|||
{
|
||||
if (mInsideFunction)
|
||||
{
|
||||
outputLineDirective(node->getLine());
|
||||
outputLineDirective(node->getLine().first_line);
|
||||
out << "{\n";
|
||||
|
||||
mScopeDepth++;
|
||||
|
|
@ -1578,7 +1444,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
|
|||
|
||||
for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
|
||||
{
|
||||
outputLineDirective((*sit)->getLine());
|
||||
outputLineDirective((*sit)->getLine().first_line);
|
||||
|
||||
traverseStatements(*sit);
|
||||
|
||||
|
|
@ -1587,7 +1453,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
|
|||
|
||||
if (mInsideFunction)
|
||||
{
|
||||
outputLineDirective(node->getEndLine());
|
||||
outputLineDirective(node->getLine().last_line);
|
||||
out << "}\n";
|
||||
|
||||
mScopeDepth--;
|
||||
|
|
@ -1605,7 +1471,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
|
|||
{
|
||||
if (variable->getType().getStruct())
|
||||
{
|
||||
addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
|
||||
addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL);
|
||||
}
|
||||
|
||||
if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
|
||||
|
|
@ -1732,7 +1598,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
|
|||
{
|
||||
if (symbol->getType().getStruct())
|
||||
{
|
||||
addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL);
|
||||
addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL);
|
||||
}
|
||||
|
||||
out << argumentString(symbol);
|
||||
|
|
@ -1993,8 +1859,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
|
|||
outputTriplet(visit, "mat4(", ", ", ")");
|
||||
break;
|
||||
case EOpConstructStruct:
|
||||
addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
|
||||
outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
|
||||
addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence());
|
||||
outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")");
|
||||
break;
|
||||
case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
|
||||
case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
|
||||
|
|
@ -2084,7 +1950,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
|
|||
|
||||
out << ")\n";
|
||||
|
||||
outputLineDirective(node->getLine());
|
||||
outputLineDirective(node->getLine().first_line);
|
||||
out << "{\n";
|
||||
|
||||
if (node->getTrueBlock())
|
||||
|
|
@ -2092,20 +1958,20 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
|
|||
traverseStatements(node->getTrueBlock());
|
||||
}
|
||||
|
||||
outputLineDirective(node->getLine());
|
||||
outputLineDirective(node->getLine().first_line);
|
||||
out << ";\n}\n";
|
||||
|
||||
if (node->getFalseBlock())
|
||||
{
|
||||
out << "else\n";
|
||||
|
||||
outputLineDirective(node->getFalseBlock()->getLine());
|
||||
outputLineDirective(node->getFalseBlock()->getLine().first_line);
|
||||
out << "{\n";
|
||||
|
||||
outputLineDirective(node->getFalseBlock()->getLine());
|
||||
outputLineDirective(node->getFalseBlock()->getLine().first_line);
|
||||
traverseStatements(node->getFalseBlock());
|
||||
|
||||
outputLineDirective(node->getFalseBlock()->getLine());
|
||||
outputLineDirective(node->getFalseBlock()->getLine().first_line);
|
||||
out << ";\n}\n";
|
||||
}
|
||||
}
|
||||
|
|
@ -2141,7 +2007,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
|
|||
{
|
||||
out << "{do\n";
|
||||
|
||||
outputLineDirective(node->getLine());
|
||||
outputLineDirective(node->getLine().first_line);
|
||||
out << "{\n";
|
||||
}
|
||||
else
|
||||
|
|
@ -2169,7 +2035,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
|
|||
|
||||
out << ")\n";
|
||||
|
||||
outputLineDirective(node->getLine());
|
||||
outputLineDirective(node->getLine().first_line);
|
||||
out << "{\n";
|
||||
}
|
||||
|
||||
|
|
@ -2178,12 +2044,12 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
|
|||
traverseStatements(node->getBody());
|
||||
}
|
||||
|
||||
outputLineDirective(node->getLine());
|
||||
outputLineDirective(node->getLine().first_line);
|
||||
out << ";}\n";
|
||||
|
||||
if (node->getType() == ELoopDoWhile)
|
||||
{
|
||||
outputLineDirective(node->getCondition()->getLine());
|
||||
outputLineDirective(node->getCondition()->getLine().first_line);
|
||||
out << "while(\n";
|
||||
|
||||
node->getCondition()->traverse(this);
|
||||
|
|
@ -2455,7 +2321,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
|
|||
out << increment;
|
||||
out << ")\n";
|
||||
|
||||
outputLineDirective(node->getLine());
|
||||
outputLineDirective(node->getLine().first_line);
|
||||
out << "{\n";
|
||||
|
||||
if (node->getBody())
|
||||
|
|
@ -2463,7 +2329,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
|
|||
node->getBody()->traverse(this);
|
||||
}
|
||||
|
||||
outputLineDirective(node->getLine());
|
||||
outputLineDirective(node->getLine().first_line);
|
||||
out << ";}\n";
|
||||
|
||||
if (!firstLoopFragment)
|
||||
|
|
@ -2565,22 +2431,23 @@ TString OutputHLSL::typeString(const TType &type)
|
|||
{
|
||||
if (type.getBasicType() == EbtStruct)
|
||||
{
|
||||
if (type.getTypeName() != "")
|
||||
const TString& typeName = type.getStruct()->name();
|
||||
if (typeName != "")
|
||||
{
|
||||
return structLookup(type.getTypeName());
|
||||
return structLookup(typeName);
|
||||
}
|
||||
else // Nameless structure, define in place
|
||||
{
|
||||
const TTypeList &fields = *type.getStruct();
|
||||
const TFieldList &fields = type.getStruct()->fields();
|
||||
|
||||
TString string = "struct\n"
|
||||
"{\n";
|
||||
|
||||
for (unsigned int i = 0; i < fields.size(); i++)
|
||||
{
|
||||
const TType &field = *fields[i].type;
|
||||
const TField *field = fields[i];
|
||||
|
||||
string += " " + typeString(field) + " " + decorate(field.getFieldName()) + arrayString(field) + ";\n";
|
||||
string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n";
|
||||
}
|
||||
|
||||
string += "} ";
|
||||
|
|
@ -2674,11 +2541,12 @@ TString OutputHLSL::initializer(const TType &type)
|
|||
{
|
||||
TString string;
|
||||
|
||||
for (int component = 0; component < type.getObjectSize(); component++)
|
||||
size_t size = type.getObjectSize();
|
||||
for (size_t component = 0; component < size; component++)
|
||||
{
|
||||
string += "0";
|
||||
|
||||
if (component < type.getObjectSize() - 1)
|
||||
if (component + 1 < size)
|
||||
{
|
||||
string += ", ";
|
||||
}
|
||||
|
|
@ -2717,13 +2585,13 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
|
|||
structure += "struct " + decorate(name) + "\n"
|
||||
"{\n";
|
||||
|
||||
const TTypeList &fields = *type.getStruct();
|
||||
const TFieldList &fields = type.getStruct()->fields();
|
||||
|
||||
for (unsigned int i = 0; i < fields.size(); i++)
|
||||
{
|
||||
const TType &field = *fields[i].type;
|
||||
const TField *field = fields[i];
|
||||
|
||||
structure += " " + typeString(field) + " " + decorateField(field.getFieldName(), type) + arrayString(field) + ";\n";
|
||||
structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n";
|
||||
}
|
||||
|
||||
structure += "};\n";
|
||||
|
|
@ -2735,7 +2603,7 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
|
|||
|
||||
for (unsigned int i = 0; i < fields.size(); i++)
|
||||
{
|
||||
ctorParameters.push_back(*fields[i].type);
|
||||
ctorParameters.push_back(*fields[i]->type());
|
||||
}
|
||||
}
|
||||
else if (parameters)
|
||||
|
|
@ -2828,27 +2696,30 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
|
|||
}
|
||||
else
|
||||
{
|
||||
int remainingComponents = ctorType.getObjectSize();
|
||||
int parameterIndex = 0;
|
||||
size_t remainingComponents = ctorType.getObjectSize();
|
||||
size_t parameterIndex = 0;
|
||||
|
||||
while (remainingComponents > 0)
|
||||
{
|
||||
const TType ¶meter = ctorParameters[parameterIndex];
|
||||
bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1;
|
||||
const size_t parameterSize = parameter.getObjectSize();
|
||||
bool moreParameters = parameterIndex + 1 < ctorParameters.size();
|
||||
|
||||
constructor += "x" + str(parameterIndex);
|
||||
|
||||
if (parameter.isScalar())
|
||||
{
|
||||
remainingComponents -= parameter.getObjectSize();
|
||||
ASSERT(parameterSize <= remainingComponents);
|
||||
remainingComponents -= parameterSize;
|
||||
}
|
||||
else if (parameter.isVector())
|
||||
{
|
||||
if (remainingComponents == parameter.getObjectSize() || moreParameters)
|
||||
if (remainingComponents == parameterSize || moreParameters)
|
||||
{
|
||||
remainingComponents -= parameter.getObjectSize();
|
||||
ASSERT(parameterSize <= remainingComponents);
|
||||
remainingComponents -= parameterSize;
|
||||
}
|
||||
else if (remainingComponents < parameter.getNominalSize())
|
||||
else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
|
||||
{
|
||||
switch (remainingComponents)
|
||||
{
|
||||
|
|
@ -2865,9 +2736,10 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
|
|||
}
|
||||
else if (parameter.isMatrix() || parameter.getStruct())
|
||||
{
|
||||
ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters);
|
||||
ASSERT(remainingComponents == parameterSize || moreParameters);
|
||||
ASSERT(parameterSize <= remainingComponents);
|
||||
|
||||
remainingComponents -= parameter.getObjectSize();
|
||||
remainingComponents -= parameterSize;
|
||||
}
|
||||
else UNREACHABLE();
|
||||
|
||||
|
|
@ -2904,17 +2776,17 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
|
|||
|
||||
if (type.getBasicType() == EbtStruct)
|
||||
{
|
||||
out << structLookup(type.getTypeName()) + "_ctor(";
|
||||
out << structLookup(type.getStruct()->name()) + "_ctor(";
|
||||
|
||||
const TTypeList *structure = type.getStruct();
|
||||
const TFieldList &fields = type.getStruct()->fields();
|
||||
|
||||
for (size_t i = 0; i < structure->size(); i++)
|
||||
for (size_t i = 0; i < fields.size(); i++)
|
||||
{
|
||||
const TType *fieldType = (*structure)[i].type;
|
||||
const TType *fieldType = fields[i]->type();
|
||||
|
||||
constUnion = writeConstantUnion(*fieldType, constUnion);
|
||||
|
||||
if (i != structure->size() - 1)
|
||||
if (i != fields.size() - 1)
|
||||
{
|
||||
out << ", ";
|
||||
}
|
||||
|
|
@ -2924,7 +2796,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
|
|||
}
|
||||
else
|
||||
{
|
||||
int size = type.getObjectSize();
|
||||
size_t size = type.getObjectSize();
|
||||
bool writeType = size > 1;
|
||||
|
||||
if (writeType)
|
||||
|
|
@ -2932,7 +2804,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
|
|||
out << typeString(type) << "(";
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++, constUnion++)
|
||||
for (size_t i = 0; i < size; i++, constUnion++)
|
||||
{
|
||||
switch (constUnion->getType())
|
||||
{
|
||||
|
|
@ -3021,7 +2893,7 @@ TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
|
|||
|
||||
TString OutputHLSL::decorateField(const TString &string, const TType &structure)
|
||||
{
|
||||
if (structure.getTypeName().compare(0, 3, "gl_") != 0)
|
||||
if (structure.getStruct()->name().compare(0, 3, "gl_") != 0)
|
||||
{
|
||||
return decorate(string);
|
||||
}
|
||||
|
|
@ -3069,7 +2941,7 @@ int OutputHLSL::uniformRegister(TIntermSymbol *uniform)
|
|||
|
||||
void OutputHLSL::declareUniform(const TType &type, const TString &name, int index)
|
||||
{
|
||||
const TTypeList *structure = type.getStruct();
|
||||
TStructure *structure = type.getStruct();
|
||||
|
||||
if (!structure)
|
||||
{
|
||||
|
|
@ -3077,18 +2949,18 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde
|
|||
}
|
||||
else
|
||||
{
|
||||
const TFieldList &fields = structure->fields();
|
||||
|
||||
if (type.isArray())
|
||||
{
|
||||
int elementIndex = index;
|
||||
|
||||
for (int i = 0; i < type.getArraySize(); i++)
|
||||
{
|
||||
for (size_t j = 0; j < structure->size(); j++)
|
||||
for (size_t j = 0; j < fields.size(); j++)
|
||||
{
|
||||
const TType &fieldType = *(*structure)[j].type;
|
||||
const TString &fieldName = fieldType.getFieldName();
|
||||
|
||||
const TString uniformName = name + "[" + str(i) + "]." + fieldName;
|
||||
const TType &fieldType = *fields[j]->type();
|
||||
const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name();
|
||||
declareUniform(fieldType, uniformName, elementIndex);
|
||||
elementIndex += fieldType.totalRegisterCount();
|
||||
}
|
||||
|
|
@ -3098,12 +2970,10 @@ void OutputHLSL::declareUniform(const TType &type, const TString &name, int inde
|
|||
{
|
||||
int fieldIndex = index;
|
||||
|
||||
for (size_t i = 0; i < structure->size(); i++)
|
||||
for (size_t i = 0; i < fields.size(); i++)
|
||||
{
|
||||
const TType &fieldType = *(*structure)[i].type;
|
||||
const TString &fieldName = fieldType.getFieldName();
|
||||
|
||||
const TString uniformName = name + "." + fieldName;
|
||||
const TType &fieldType = *fields[i]->type();
|
||||
const TString uniformName = name + "." + fields[i]->name();
|
||||
declareUniform(fieldType, uniformName, fieldIndex);
|
||||
fieldIndex += fieldType.totalRegisterCount();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ class OutputHLSL : public TIntermTraverser
|
|||
bool mUsesPointCoord;
|
||||
bool mUsesFrontFacing;
|
||||
bool mUsesPointSize;
|
||||
bool mUsesFragDepth;
|
||||
bool mUsesXor;
|
||||
bool mUsesMod1;
|
||||
bool mUsesMod2v;
|
||||
|
|
@ -120,18 +121,6 @@ class OutputHLSL : public TIntermTraverser
|
|||
bool mUsesFaceforward2;
|
||||
bool mUsesFaceforward3;
|
||||
bool mUsesFaceforward4;
|
||||
bool mUsesEqualMat2;
|
||||
bool mUsesEqualMat3;
|
||||
bool mUsesEqualMat4;
|
||||
bool mUsesEqualVec2;
|
||||
bool mUsesEqualVec3;
|
||||
bool mUsesEqualVec4;
|
||||
bool mUsesEqualIVec2;
|
||||
bool mUsesEqualIVec3;
|
||||
bool mUsesEqualIVec4;
|
||||
bool mUsesEqualBVec2;
|
||||
bool mUsesEqualBVec3;
|
||||
bool mUsesEqualBVec4;
|
||||
bool mUsesAtan2_1;
|
||||
bool mUsesAtan2_2;
|
||||
bool mUsesAtan2_3;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
// Look at a '.' field selector string and change it into offsets
|
||||
// for a vector.
|
||||
//
|
||||
bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
|
||||
bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line)
|
||||
{
|
||||
fields.num = (int) compString.size();
|
||||
if (fields.num > 4) {
|
||||
|
|
@ -115,7 +115,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
|
|||
// Look at a '.' field selector string and change it into offsets
|
||||
// for a matrix.
|
||||
//
|
||||
bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
|
||||
bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line)
|
||||
{
|
||||
fields.wholeRow = false;
|
||||
fields.wholeCol = false;
|
||||
|
|
@ -175,22 +175,24 @@ void TParseContext::recover()
|
|||
//
|
||||
// Used by flex/bison to output all syntax and parsing errors.
|
||||
//
|
||||
void TParseContext::error(TSourceLoc loc,
|
||||
void TParseContext::error(const TSourceLoc& loc,
|
||||
const char* reason, const char* token,
|
||||
const char* extraInfo)
|
||||
{
|
||||
pp::SourceLocation srcLoc;
|
||||
DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
|
||||
srcLoc.file = loc.first_file;
|
||||
srcLoc.line = loc.first_line;
|
||||
diagnostics.writeInfo(pp::Diagnostics::ERROR,
|
||||
srcLoc, reason, token, extraInfo);
|
||||
|
||||
}
|
||||
|
||||
void TParseContext::warning(TSourceLoc loc,
|
||||
void TParseContext::warning(const TSourceLoc& loc,
|
||||
const char* reason, const char* token,
|
||||
const char* extraInfo) {
|
||||
pp::SourceLocation srcLoc;
|
||||
DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
|
||||
srcLoc.file = loc.first_file;
|
||||
srcLoc.line = loc.first_line;
|
||||
diagnostics.writeInfo(pp::Diagnostics::WARNING,
|
||||
srcLoc, reason, token, extraInfo);
|
||||
}
|
||||
|
|
@ -203,7 +205,7 @@ void TParseContext::trace(const char* str)
|
|||
//
|
||||
// Same error message for all places assignments don't work.
|
||||
//
|
||||
void TParseContext::assignError(int line, const char* op, TString left, TString right)
|
||||
void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right)
|
||||
{
|
||||
std::stringstream extraInfoStream;
|
||||
extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
|
||||
|
|
@ -214,7 +216,7 @@ void TParseContext::assignError(int line, const char* op, TString left, TString
|
|||
//
|
||||
// Same error message for all places unary operations don't work.
|
||||
//
|
||||
void TParseContext::unaryOpError(int line, const char* op, TString operand)
|
||||
void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand)
|
||||
{
|
||||
std::stringstream extraInfoStream;
|
||||
extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
|
||||
|
|
@ -226,7 +228,7 @@ void TParseContext::unaryOpError(int line, const char* op, TString operand)
|
|||
//
|
||||
// Same error message for all binary operations don't work.
|
||||
//
|
||||
void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
|
||||
void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right)
|
||||
{
|
||||
std::stringstream extraInfoStream;
|
||||
extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
|
||||
|
|
@ -235,7 +237,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin
|
|||
error(line, " wrong operand types ", op, extraInfo.c_str());
|
||||
}
|
||||
|
||||
bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
|
||||
bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){
|
||||
if (!checksPrecisionErrors)
|
||||
return false;
|
||||
switch( type ){
|
||||
|
|
@ -263,7 +265,7 @@ bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicTy
|
|||
//
|
||||
// Returns true if the was an error.
|
||||
//
|
||||
bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
|
||||
bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node)
|
||||
{
|
||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
||||
|
|
@ -317,7 +319,6 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
|
|||
case EvqAttribute: message = "can't modify an attribute"; break;
|
||||
case EvqUniform: message = "can't modify a uniform"; break;
|
||||
case EvqVaryingIn: message = "can't modify a varying"; break;
|
||||
case EvqInput: message = "can't modify an input"; break;
|
||||
case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
|
||||
case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break;
|
||||
case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
|
||||
|
|
@ -409,7 +410,7 @@ bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
|
|||
//
|
||||
// Returns true if the was an error.
|
||||
//
|
||||
bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
|
||||
bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token)
|
||||
{
|
||||
if (global)
|
||||
return false;
|
||||
|
|
@ -428,7 +429,7 @@ bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
|
|||
//
|
||||
// Returns true if there was an error.
|
||||
//
|
||||
bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
|
||||
bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier)
|
||||
{
|
||||
static const char* reservedErrMsg = "reserved built-in name";
|
||||
if (!symbolTable.atBuiltInLevel()) {
|
||||
|
|
@ -466,7 +467,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
|
|||
//
|
||||
// Returns true if there was an error in construction.
|
||||
//
|
||||
bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
|
||||
bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
|
||||
{
|
||||
*type = function.getReturnType();
|
||||
|
||||
|
|
@ -487,7 +488,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
|
|||
// again, there is an extra argument, so 'overfull' will become true.
|
||||
//
|
||||
|
||||
int size = 0;
|
||||
size_t size = 0;
|
||||
bool constType = true;
|
||||
bool full = false;
|
||||
bool overFull = false;
|
||||
|
|
@ -534,7 +535,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
|
|||
return true;
|
||||
}
|
||||
|
||||
if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
|
||||
if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
|
||||
error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
|
||||
return true;
|
||||
}
|
||||
|
|
@ -568,7 +569,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction
|
|||
//
|
||||
// returns true in case of an error
|
||||
//
|
||||
bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
|
||||
bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType)
|
||||
{
|
||||
if (pubType.type == EbtVoid) {
|
||||
error(line, "illegal use of type 'void'", identifier.c_str());
|
||||
|
|
@ -582,7 +583,7 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP
|
|||
//
|
||||
// returns true in case of an error
|
||||
//
|
||||
bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
|
||||
bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type)
|
||||
{
|
||||
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
|
||||
error(line, "boolean expression expected", "");
|
||||
|
|
@ -596,7 +597,7 @@ bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
|
|||
//
|
||||
// returns true in case of an error
|
||||
//
|
||||
bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
|
||||
bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType)
|
||||
{
|
||||
if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
|
||||
error(line, "boolean expression expected", "");
|
||||
|
|
@ -606,7 +607,7 @@ bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
|
||||
bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason)
|
||||
{
|
||||
if (pType.type == EbtStruct) {
|
||||
if (containsSampler(*pType.userDef)) {
|
||||
|
|
@ -625,7 +626,7 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
|
||||
bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType)
|
||||
{
|
||||
if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
|
||||
pType.type == EbtStruct) {
|
||||
|
|
@ -640,7 +641,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
|
||||
bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type)
|
||||
{
|
||||
if ((qualifier == EvqOut || qualifier == EvqInOut) &&
|
||||
type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
|
||||
|
|
@ -657,9 +658,9 @@ bool TParseContext::containsSampler(TType& type)
|
|||
return true;
|
||||
|
||||
if (type.getBasicType() == EbtStruct) {
|
||||
TTypeList& structure = *type.getStruct();
|
||||
for (unsigned int i = 0; i < structure.size(); ++i) {
|
||||
if (containsSampler(*structure[i].type))
|
||||
const TFieldList& fields = type.getStruct()->fields();
|
||||
for (unsigned int i = 0; i < fields.size(); ++i) {
|
||||
if (containsSampler(*fields[i]->type()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -672,7 +673,7 @@ bool TParseContext::containsSampler(TType& type)
|
|||
//
|
||||
// Returns true if there was an error.
|
||||
//
|
||||
bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
|
||||
bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size)
|
||||
{
|
||||
TIntermConstantUnion* constant = expr->getAsConstantUnion();
|
||||
if (constant == 0 || constant->getBasicType() != EbtInt) {
|
||||
|
|
@ -696,7 +697,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
|
|||
//
|
||||
// Returns true if there is an error.
|
||||
//
|
||||
bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
|
||||
bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type)
|
||||
{
|
||||
if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
|
||||
error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
|
||||
|
|
@ -711,7 +712,7 @@ bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
|
|||
//
|
||||
// Returns true if there is an error.
|
||||
//
|
||||
bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
|
||||
bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type)
|
||||
{
|
||||
//
|
||||
// Can the type be an array?
|
||||
|
|
@ -732,7 +733,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
|
|||
//
|
||||
// Returns true if there was an error.
|
||||
//
|
||||
bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
|
||||
bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable)
|
||||
{
|
||||
//
|
||||
// Don't check for reserved word use until after we know it's not in the symbol table,
|
||||
|
|
@ -777,16 +778,6 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
|
|||
return true;
|
||||
}
|
||||
|
||||
TType* t = variable->getArrayInformationType();
|
||||
while (t != 0) {
|
||||
if (t->getMaxArraySize() > type.arraySize) {
|
||||
error(line, "higher index value already used for the array", identifier.c_str());
|
||||
return true;
|
||||
}
|
||||
t->setArraySize(type.arraySize);
|
||||
t = t->getArrayInformationType();
|
||||
}
|
||||
|
||||
if (type.arraySize)
|
||||
variable->getType().setArraySize(type.arraySize);
|
||||
}
|
||||
|
|
@ -797,56 +788,12 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
|
||||
{
|
||||
bool builtIn = false;
|
||||
TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
|
||||
if (symbol == 0) {
|
||||
error(line, " undeclared identifier", node->getSymbol().c_str());
|
||||
return true;
|
||||
}
|
||||
TVariable* variable = static_cast<TVariable*>(symbol);
|
||||
|
||||
type->setArrayInformationType(variable->getArrayInformationType());
|
||||
variable->updateArrayInformationType(type);
|
||||
|
||||
// special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
|
||||
// its an error
|
||||
if (node->getSymbol() == "gl_FragData") {
|
||||
TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
|
||||
ASSERT(fragData);
|
||||
|
||||
int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
|
||||
if (fragDataValue <= size) {
|
||||
error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// we dont want to update the maxArraySize when this flag is not set, we just want to include this
|
||||
// node type in the chain of node types so that its updated when a higher maxArraySize comes in.
|
||||
if (!updateFlag)
|
||||
return false;
|
||||
|
||||
size++;
|
||||
variable->getType().setMaxArraySize(size);
|
||||
type->setMaxArraySize(size);
|
||||
TType* tt = type;
|
||||
|
||||
while(tt->getArrayInformationType() != 0) {
|
||||
tt = tt->getArrayInformationType();
|
||||
tt->setMaxArraySize(size);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Enforce non-initializer type/qualifier rules.
|
||||
//
|
||||
// Returns true if there was an error.
|
||||
//
|
||||
bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array)
|
||||
bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array)
|
||||
{
|
||||
if (type.qualifier == EvqConst)
|
||||
{
|
||||
|
|
@ -878,7 +825,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
|
|||
//
|
||||
// Returns true if there was an error.
|
||||
//
|
||||
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable)
|
||||
bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable)
|
||||
{
|
||||
if (reservedErrorCheck(line, identifier))
|
||||
recover();
|
||||
|
|
@ -898,7 +845,7 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
|
||||
bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
|
||||
{
|
||||
if (qualifier != EvqConst && qualifier != EvqTemporary) {
|
||||
error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
|
||||
|
|
@ -917,7 +864,7 @@ bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier p
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TParseContext::extensionErrorCheck(int line, const TString& extension)
|
||||
bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension)
|
||||
{
|
||||
const TExtensionBehavior& extBehavior = extensionBehavior();
|
||||
TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
|
||||
|
|
@ -945,18 +892,17 @@ bool TParseContext::supportsExtension(const char* extension)
|
|||
return (iter != extbehavior.end());
|
||||
}
|
||||
|
||||
void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior)
|
||||
bool TParseContext::isExtensionEnabled(const char* extension) const
|
||||
{
|
||||
pp::SourceLocation loc;
|
||||
DecodeSourceLoc(line, &loc.file, &loc.line);
|
||||
directiveHandler.handleExtension(loc, extName, behavior);
|
||||
}
|
||||
const TExtensionBehavior& extbehavior = extensionBehavior();
|
||||
TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
|
||||
|
||||
void TParseContext::handlePragmaDirective(int line, const char* name, const char* value)
|
||||
{
|
||||
pp::SourceLocation loc;
|
||||
DecodeSourceLoc(line, &loc.file, &loc.line);
|
||||
directiveHandler.handlePragma(loc, name, value);
|
||||
if (iter == extbehavior.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (iter->second == EBhEnable || iter->second == EBhRequire);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -970,12 +916,13 @@ void TParseContext::handlePragmaDirective(int line, const char* name, const char
|
|||
//
|
||||
// Return the function symbol if found, otherwise 0.
|
||||
//
|
||||
const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
|
||||
const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn)
|
||||
{
|
||||
// First find by unmangled name to check whether the function name has been
|
||||
// hidden by a variable name or struct typename.
|
||||
// If a function is found, check for one with a matching argument list.
|
||||
const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
|
||||
if (symbol == 0) {
|
||||
if (symbol == 0 || symbol->isFunction()) {
|
||||
symbol = symbolTable.find(call->getMangledName(), builtIn);
|
||||
}
|
||||
|
||||
|
|
@ -996,7 +943,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu
|
|||
// Initializers show up in several places in the grammar. Have one set of
|
||||
// code to handle them here.
|
||||
//
|
||||
bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
|
||||
bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
|
||||
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
|
||||
{
|
||||
TType type = TType(pType);
|
||||
|
|
@ -1048,13 +995,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu
|
|||
return true;
|
||||
}
|
||||
if (initializer->getAsConstantUnion()) {
|
||||
ConstantUnion* unionArray = variable->getConstPointer();
|
||||
|
||||
if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
|
||||
*unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
|
||||
} else {
|
||||
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
|
||||
}
|
||||
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
|
||||
} else if (initializer->getAsSymbolNode()) {
|
||||
const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
|
||||
const TVariable* tVar = static_cast<const TVariable*>(symbol);
|
||||
|
|
@ -1108,16 +1049,16 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
|
|||
//
|
||||
// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
|
||||
//
|
||||
TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
|
||||
TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line)
|
||||
{
|
||||
if (node == 0)
|
||||
return 0;
|
||||
|
||||
TIntermAggregate* aggrNode = node->getAsAggregate();
|
||||
|
||||
TTypeList::const_iterator memberTypes;
|
||||
TFieldList::const_iterator memberFields;
|
||||
if (op == EOpConstructStruct)
|
||||
memberTypes = type->getStruct()->begin();
|
||||
memberFields = type->getStruct()->fields().begin();
|
||||
|
||||
TType elementType = *type;
|
||||
if (type->isArray())
|
||||
|
|
@ -1139,7 +1080,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
|
|||
if (type->isArray())
|
||||
newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
|
||||
else if (op == EOpConstructStruct)
|
||||
newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
|
||||
newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false);
|
||||
else
|
||||
newNode = constructBuiltIn(type, op, node, node->getLine(), false);
|
||||
|
||||
|
|
@ -1170,7 +1111,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
|
|||
if (type->isArray())
|
||||
newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
|
||||
else if (op == EOpConstructStruct)
|
||||
newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
|
||||
newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true);
|
||||
else
|
||||
newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
|
||||
|
||||
|
|
@ -1216,7 +1157,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co
|
|||
//
|
||||
// Returns 0 for an error or the constructed node.
|
||||
//
|
||||
TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
|
||||
TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset)
|
||||
{
|
||||
TIntermTyped* newNode;
|
||||
TOperator basicOp;
|
||||
|
|
@ -1278,7 +1219,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T
|
|||
//
|
||||
// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
|
||||
//
|
||||
TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
|
||||
TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset)
|
||||
{
|
||||
if (*type == node->getAsTyped()->getType()) {
|
||||
if (subset)
|
||||
|
|
@ -1305,7 +1246,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int
|
|||
// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
|
||||
// a constant matrix.
|
||||
//
|
||||
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
|
||||
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line)
|
||||
{
|
||||
TIntermTyped* typedNode;
|
||||
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
|
||||
|
|
@ -1327,7 +1268,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
|
|||
ConstantUnion* constArray = new ConstantUnion[fields.num];
|
||||
|
||||
for (int i = 0; i < fields.num; i++) {
|
||||
if (fields.offsets[i] >= node->getType().getObjectSize()) {
|
||||
if (fields.offsets[i] >= node->getType().getNominalSize()) {
|
||||
std::stringstream extraInfoStream;
|
||||
extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
|
||||
std::string extraInfo = extraInfoStream.str();
|
||||
|
|
@ -1349,7 +1290,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
|
|||
// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
|
||||
// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
|
||||
//
|
||||
TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
|
||||
TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line)
|
||||
{
|
||||
TIntermTyped* typedNode;
|
||||
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
|
||||
|
|
@ -1384,7 +1325,7 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T
|
|||
// to the function could either be a symbol node (a[0] where a is a constant array)that represents a
|
||||
// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
|
||||
//
|
||||
TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
|
||||
TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line)
|
||||
{
|
||||
TIntermTyped* typedNode;
|
||||
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
|
||||
|
|
@ -1400,9 +1341,8 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
|
|||
index = 0;
|
||||
}
|
||||
|
||||
int arrayElementSize = arrayElementType.getObjectSize();
|
||||
|
||||
if (tempConstantNode) {
|
||||
size_t arrayElementSize = arrayElementType.getObjectSize();
|
||||
ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
|
||||
typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
|
||||
} else {
|
||||
|
|
@ -1421,22 +1361,21 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
|
|||
// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
|
||||
// function and returns the parse-tree with the values of the embedded/nested struct.
|
||||
//
|
||||
TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
|
||||
TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line)
|
||||
{
|
||||
const TTypeList* fields = node->getType().getStruct();
|
||||
TIntermTyped *typedNode;
|
||||
int instanceSize = 0;
|
||||
unsigned int index = 0;
|
||||
TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
|
||||
const TFieldList& fields = node->getType().getStruct()->fields();
|
||||
|
||||
for ( index = 0; index < fields->size(); ++index) {
|
||||
if ((*fields)[index].type->getFieldName() == identifier) {
|
||||
size_t instanceSize = 0;
|
||||
for (size_t index = 0; index < fields.size(); ++index) {
|
||||
if (fields[index]->name() == identifier) {
|
||||
break;
|
||||
} else {
|
||||
instanceSize += (*fields)[index].type->getObjectSize();
|
||||
instanceSize += fields[index]->type()->getObjectSize();
|
||||
}
|
||||
}
|
||||
|
||||
TIntermTyped* typedNode = 0;
|
||||
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
|
||||
if (tempConstantNode) {
|
||||
ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
|
||||
|
||||
|
|
@ -1451,7 +1390,7 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n
|
|||
return typedNode;
|
||||
}
|
||||
|
||||
bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
|
||||
bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier)
|
||||
{
|
||||
++structNestingLevel;
|
||||
|
||||
|
|
@ -1477,30 +1416,166 @@ const int kWebGLMaxStructNesting = 4;
|
|||
|
||||
} // namespace
|
||||
|
||||
bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType)
|
||||
bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
|
||||
{
|
||||
if (!isWebGLBasedSpec(shaderSpec)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fieldType.getBasicType() != EbtStruct) {
|
||||
if (field.type()->getBasicType() != EbtStruct) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We're already inside a structure definition at this point, so add
|
||||
// one to the field's struct nesting.
|
||||
if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) {
|
||||
std::stringstream extraInfoStream;
|
||||
extraInfoStream << "Reference of struct type " << fieldType.getTypeName()
|
||||
<< " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
|
||||
std::string extraInfo = extraInfoStream.str();
|
||||
error(line, "", "", extraInfo.c_str());
|
||||
if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
|
||||
std::stringstream reasonStream;
|
||||
reasonStream << "Reference of struct type "
|
||||
<< field.type()->getStruct()->name().c_str()
|
||||
<< " exceeds maximum allowed nesting level of "
|
||||
<< kWebGLMaxStructNesting;
|
||||
std::string reason = reasonStream.str();
|
||||
error(line, reason.c_str(), field.name().c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse an array index expression
|
||||
//
|
||||
TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression)
|
||||
{
|
||||
TIntermTyped *indexedExpression = NULL;
|
||||
|
||||
if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
|
||||
{
|
||||
if (baseExpression->getAsSymbolNode())
|
||||
{
|
||||
error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
|
||||
}
|
||||
recover();
|
||||
}
|
||||
|
||||
if (indexExpression->getQualifier() == EvqConst)
|
||||
{
|
||||
int index = indexExpression->getAsConstantUnion()->getIConst(0);
|
||||
if (index < 0)
|
||||
{
|
||||
std::stringstream infoStream;
|
||||
infoStream << index;
|
||||
std::string info = infoStream.str();
|
||||
error(location, "negative index", info.c_str());
|
||||
recover();
|
||||
index = 0;
|
||||
}
|
||||
if (baseExpression->getType().getQualifier() == EvqConst)
|
||||
{
|
||||
if (baseExpression->isArray())
|
||||
{
|
||||
// constant folding for arrays
|
||||
indexedExpression = addConstArrayNode(index, baseExpression, location);
|
||||
}
|
||||
else if (baseExpression->isVector())
|
||||
{
|
||||
// constant folding for vectors
|
||||
TVectorFields fields;
|
||||
fields.num = 1;
|
||||
fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
|
||||
indexedExpression = addConstVectorNode(fields, baseExpression, location);
|
||||
}
|
||||
else if (baseExpression->isMatrix())
|
||||
{
|
||||
// constant folding for matrices
|
||||
indexedExpression = addConstMatrixNode(index, baseExpression, location);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (baseExpression->isArray())
|
||||
{
|
||||
if (index >= baseExpression->getType().getArraySize())
|
||||
{
|
||||
std::stringstream extraInfoStream;
|
||||
extraInfoStream << "array index out of range '" << index << "'";
|
||||
std::string extraInfo = extraInfoStream.str();
|
||||
error(location, "", "[", extraInfo.c_str());
|
||||
recover();
|
||||
index = baseExpression->getType().getArraySize() - 1;
|
||||
}
|
||||
else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
|
||||
{
|
||||
error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
|
||||
recover();
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
|
||||
{
|
||||
std::stringstream extraInfoStream;
|
||||
extraInfoStream << "field selection out of range '" << index << "'";
|
||||
std::string extraInfo = extraInfoStream.str();
|
||||
error(location, "", "[", extraInfo.c_str());
|
||||
recover();
|
||||
index = baseExpression->getType().getNominalSize() - 1;
|
||||
}
|
||||
|
||||
indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
|
||||
indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
|
||||
}
|
||||
|
||||
if (indexedExpression == 0)
|
||||
{
|
||||
ConstantUnion *unionArray = new ConstantUnion[1];
|
||||
unionArray->setFConst(0.0f);
|
||||
indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
|
||||
}
|
||||
else if (baseExpression->isArray())
|
||||
{
|
||||
const TType &baseType = baseExpression->getType();
|
||||
if (baseType.getStruct())
|
||||
{
|
||||
TType copyOfType(baseType.getStruct());
|
||||
indexedExpression->setType(copyOfType);
|
||||
}
|
||||
else
|
||||
{
|
||||
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix()));
|
||||
}
|
||||
|
||||
if (baseExpression->getType().getQualifier() == EvqConst)
|
||||
{
|
||||
indexedExpression->getTypePointer()->setQualifier(EvqConst);
|
||||
}
|
||||
}
|
||||
else if (baseExpression->isMatrix())
|
||||
{
|
||||
TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
|
||||
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize()));
|
||||
}
|
||||
else if (baseExpression->isVector())
|
||||
{
|
||||
TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
|
||||
indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
|
||||
}
|
||||
else
|
||||
{
|
||||
indexedExpression->setType(baseExpression->getType());
|
||||
}
|
||||
|
||||
return indexedExpression;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse an array of strings using yyparse.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
|
@ -33,10 +33,8 @@ struct TParseContext {
|
|||
compileOptions(options),
|
||||
sourcePath(sourcePath),
|
||||
treeRoot(0),
|
||||
lexAfterType(false),
|
||||
loopNestingLevel(0),
|
||||
structNestingLevel(0),
|
||||
inTypeParen(false),
|
||||
currentFunctionType(NULL),
|
||||
functionReturnsValue(false),
|
||||
checksPrecisionErrors(checksPrecErrors),
|
||||
|
|
@ -51,16 +49,13 @@ struct TParseContext {
|
|||
int compileOptions;
|
||||
const char* sourcePath; // Path of source file or NULL.
|
||||
TIntermNode* treeRoot; // root of parse tree being created
|
||||
bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
|
||||
int loopNestingLevel; // 0 if outside all loops
|
||||
int structNestingLevel; // incremented while parsing a struct declaration
|
||||
bool inTypeParen; // true if in parentheses, looking only for an identifier
|
||||
const TType* currentFunctionType; // the return type of the function that's currently being parsed
|
||||
bool functionReturnsValue; // true if a non-void function has a return
|
||||
bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
|
||||
bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language.
|
||||
TString HashErrMsg;
|
||||
bool AfterEOF;
|
||||
TDiagnostics diagnostics;
|
||||
TDirectiveHandler directiveHandler;
|
||||
pp::Preprocessor preprocessor;
|
||||
|
|
@ -68,71 +63,69 @@ struct TParseContext {
|
|||
|
||||
int numErrors() const { return diagnostics.numErrors(); }
|
||||
TInfoSink& infoSink() { return diagnostics.infoSink(); }
|
||||
void error(TSourceLoc loc, const char *reason, const char* token,
|
||||
void error(const TSourceLoc& loc, const char *reason, const char* token,
|
||||
const char* extraInfo="");
|
||||
void warning(TSourceLoc loc, const char* reason, const char* token,
|
||||
void warning(const TSourceLoc& loc, const char* reason, const char* token,
|
||||
const char* extraInfo="");
|
||||
void trace(const char* str);
|
||||
void recover();
|
||||
|
||||
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
|
||||
bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, int line);
|
||||
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line);
|
||||
bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line);
|
||||
|
||||
bool reservedErrorCheck(int line, const TString& identifier);
|
||||
void assignError(int line, const char* op, TString left, TString right);
|
||||
void unaryOpError(int line, const char* op, TString operand);
|
||||
void binaryOpError(int line, const char* op, TString left, TString right);
|
||||
bool precisionErrorCheck(int line, TPrecision precision, TBasicType type);
|
||||
bool lValueErrorCheck(int line, const char* op, TIntermTyped*);
|
||||
bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier);
|
||||
void assignError(const TSourceLoc& line, const char* op, TString left, TString right);
|
||||
void unaryOpError(const TSourceLoc& line, const char* op, TString operand);
|
||||
void binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right);
|
||||
bool precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type);
|
||||
bool lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped*);
|
||||
bool constErrorCheck(TIntermTyped* node);
|
||||
bool integerErrorCheck(TIntermTyped* node, const char* token);
|
||||
bool globalErrorCheck(int line, bool global, const char* token);
|
||||
bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*);
|
||||
bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
|
||||
bool arrayQualifierErrorCheck(int line, TPublicType type);
|
||||
bool arrayTypeErrorCheck(int line, TPublicType type);
|
||||
bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable);
|
||||
bool voidErrorCheck(int, const TString&, const TPublicType&);
|
||||
bool boolErrorCheck(int, const TIntermTyped*);
|
||||
bool boolErrorCheck(int, const TPublicType&);
|
||||
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
|
||||
bool structQualifierErrorCheck(int line, const TPublicType& pType);
|
||||
bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
|
||||
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array);
|
||||
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable);
|
||||
bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
|
||||
bool extensionErrorCheck(int line, const TString&);
|
||||
|
||||
const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
|
||||
bool supportsExtension(const char* extension);
|
||||
void handleExtensionDirective(int line, const char* extName, const char* behavior);
|
||||
bool globalErrorCheck(const TSourceLoc& line, bool global, const char* token);
|
||||
bool constructorErrorCheck(const TSourceLoc& line, TIntermNode*, TFunction&, TOperator, TType*);
|
||||
bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size);
|
||||
bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type);
|
||||
bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type);
|
||||
bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable);
|
||||
bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&);
|
||||
bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*);
|
||||
bool boolErrorCheck(const TSourceLoc&, const TPublicType&);
|
||||
bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason);
|
||||
bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType);
|
||||
bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type);
|
||||
bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array);
|
||||
bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable);
|
||||
bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
|
||||
bool extensionErrorCheck(const TSourceLoc& line, const TString&);
|
||||
|
||||
const TPragma& pragma() const { return directiveHandler.pragma(); }
|
||||
void handlePragmaDirective(int line, const char* name, const char* value);
|
||||
const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
|
||||
bool supportsExtension(const char* extension);
|
||||
bool isExtensionEnabled(const char* extension) const;
|
||||
|
||||
bool containsSampler(TType& type);
|
||||
bool areAllChildConst(TIntermAggregate* aggrNode);
|
||||
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
|
||||
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
|
||||
const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0);
|
||||
bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
|
||||
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
|
||||
bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
|
||||
|
||||
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
|
||||
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
|
||||
TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
|
||||
TIntermTyped* constructStruct(TIntermNode*, TType*, int, TSourceLoc, bool subset);
|
||||
TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, TSourceLoc, bool subset);
|
||||
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
|
||||
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, TSourceLoc);
|
||||
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
|
||||
TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
|
||||
TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset);
|
||||
TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset);
|
||||
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
|
||||
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&);
|
||||
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line);
|
||||
TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&);
|
||||
TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
|
||||
|
||||
// Performs an error check for embedded struct declarations.
|
||||
// Returns true if an error was raised due to the declaration of
|
||||
// this struct.
|
||||
bool enterStructDeclaration(TSourceLoc line, const TString& identifier);
|
||||
bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier);
|
||||
void exitStructDeclaration();
|
||||
|
||||
bool structNestingErrorCheck(TSourceLoc line, const TType& fieldType);
|
||||
bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
|
||||
};
|
||||
|
||||
int PaParseStrings(size_t count, const char* const string[], const int length[],
|
||||
|
|
|
|||
|
|
@ -17,55 +17,32 @@
|
|||
|
||||
OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
|
||||
|
||||
void InitializeGlobalPools()
|
||||
{
|
||||
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
|
||||
if (globalPools)
|
||||
return;
|
||||
|
||||
TThreadGlobalPools* threadData = new TThreadGlobalPools();
|
||||
threadData->globalPoolAllocator = 0;
|
||||
|
||||
OS_SetTLSValue(PoolIndex, threadData);
|
||||
}
|
||||
|
||||
void FreeGlobalPools()
|
||||
{
|
||||
// Release the allocated memory for this thread.
|
||||
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
|
||||
if (!globalPools)
|
||||
return;
|
||||
|
||||
delete globalPools;
|
||||
}
|
||||
|
||||
bool InitializePoolIndex()
|
||||
{
|
||||
// Allocate a TLS index.
|
||||
if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
|
||||
return false;
|
||||
assert(PoolIndex == OS_INVALID_TLS_INDEX);
|
||||
|
||||
return true;
|
||||
PoolIndex = OS_AllocTLSIndex();
|
||||
return PoolIndex != OS_INVALID_TLS_INDEX;
|
||||
}
|
||||
|
||||
void FreePoolIndex()
|
||||
{
|
||||
// Release the TLS index.
|
||||
assert(PoolIndex != OS_INVALID_TLS_INDEX);
|
||||
|
||||
OS_FreeTLSIndex(PoolIndex);
|
||||
PoolIndex = OS_INVALID_TLS_INDEX;
|
||||
}
|
||||
|
||||
TPoolAllocator& GetGlobalPoolAllocator()
|
||||
TPoolAllocator* GetGlobalPoolAllocator()
|
||||
{
|
||||
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
|
||||
|
||||
return *threadData->globalPoolAllocator;
|
||||
assert(PoolIndex != OS_INVALID_TLS_INDEX);
|
||||
return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
|
||||
}
|
||||
|
||||
void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
|
||||
{
|
||||
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
|
||||
|
||||
threadData->globalPoolAllocator = poolAllocator;
|
||||
assert(PoolIndex != OS_INVALID_TLS_INDEX);
|
||||
OS_SetTLSValue(PoolIndex, poolAllocator);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -228,24 +205,27 @@ void TPoolAllocator::popAll()
|
|||
|
||||
void* TPoolAllocator::allocate(size_t numBytes)
|
||||
{
|
||||
// If we are using guard blocks, all allocations are bracketed by
|
||||
// them: [guardblock][allocation][guardblock]. numBytes is how
|
||||
// much memory the caller asked for. allocationSize is the total
|
||||
// size including guard blocks. In release build,
|
||||
// guardBlockSize=0 and this all gets optimized away.
|
||||
size_t allocationSize = TAllocation::allocationSize(numBytes);
|
||||
|
||||
//
|
||||
// Just keep some interesting statistics.
|
||||
//
|
||||
++numCalls;
|
||||
totalBytes += numBytes;
|
||||
|
||||
// If we are using guard blocks, all allocations are bracketed by
|
||||
// them: [guardblock][allocation][guardblock]. numBytes is how
|
||||
// much memory the caller asked for. allocationSize is the total
|
||||
// size including guard blocks. In release build,
|
||||
// guardBlockSize=0 and this all gets optimized away.
|
||||
size_t allocationSize = TAllocation::allocationSize(numBytes);
|
||||
// Detect integer overflow.
|
||||
if (allocationSize < numBytes)
|
||||
return 0;
|
||||
|
||||
//
|
||||
// Do the allocation, most likely case first, for efficiency.
|
||||
// This step could be moved to be inline sometime.
|
||||
//
|
||||
if (currentPageOffset + allocationSize <= pageSize) {
|
||||
if (allocationSize <= pageSize - currentPageOffset) {
|
||||
//
|
||||
// Safe to allocate from currentPageOffset.
|
||||
//
|
||||
|
|
@ -256,12 +236,16 @@ void* TPoolAllocator::allocate(size_t numBytes)
|
|||
return initializeAllocation(inUseList, memory, numBytes);
|
||||
}
|
||||
|
||||
if (allocationSize + headerSkip > pageSize) {
|
||||
if (allocationSize > pageSize - headerSkip) {
|
||||
//
|
||||
// Do a multi-page allocation. Don't mix these with the others.
|
||||
// The OS is efficient and allocating and free-ing multiple pages.
|
||||
//
|
||||
size_t numBytesToAlloc = allocationSize + headerSkip;
|
||||
// Detect integer overflow.
|
||||
if (numBytesToAlloc < allocationSize)
|
||||
return 0;
|
||||
|
||||
tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
|
||||
if (memory == 0)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -219,14 +219,8 @@ private:
|
|||
// different times. But a simple use is to have a global pop
|
||||
// with everyone using the same global allocator.
|
||||
//
|
||||
extern TPoolAllocator& GetGlobalPoolAllocator();
|
||||
extern TPoolAllocator* GetGlobalPoolAllocator();
|
||||
extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
|
||||
#define GlobalPoolAllocator GetGlobalPoolAllocator()
|
||||
|
||||
struct TThreadGlobalPools
|
||||
{
|
||||
TPoolAllocator* globalPoolAllocator;
|
||||
};
|
||||
|
||||
//
|
||||
// This STL compatible allocator is intended to be used as the allocator
|
||||
|
|
@ -253,7 +247,7 @@ public:
|
|||
pointer address(reference x) const { return &x; }
|
||||
const_pointer address(const_reference x) const { return &x; }
|
||||
|
||||
pool_allocator() : allocator(&GlobalPoolAllocator) { }
|
||||
pool_allocator() : allocator(GetGlobalPoolAllocator()) { }
|
||||
pool_allocator(TPoolAllocator& a) : allocator(&a) { }
|
||||
pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ public:
|
|||
TInfoSink& getInfoSink() { return infoSink; }
|
||||
const TVariableInfoList& getAttribs() const { return attribs; }
|
||||
const TVariableInfoList& getUniforms() const { return uniforms; }
|
||||
const TVariableInfoList& getVaryings() const { return varyings; }
|
||||
int getMappedNameMaxLength() const;
|
||||
|
||||
ShHashFunction64 getHashFunction() const { return hashFunction; }
|
||||
|
|
@ -83,15 +84,15 @@ protected:
|
|||
bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
|
||||
// Clears the results from the previous compilation.
|
||||
void clearResults();
|
||||
// Return true if function recursion is detected.
|
||||
bool detectRecursion(TIntermNode* root);
|
||||
// Return true if function recursion is detected or call depth exceeded.
|
||||
bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth);
|
||||
// Rewrites a shader's intermediate tree according to the CSS Shaders spec.
|
||||
void rewriteCSSShader(TIntermNode* root);
|
||||
// Returns true if the given shader does not exceed the minimum
|
||||
// functionality mandated in GLSL 1.0 spec Appendix A.
|
||||
bool validateLimitations(TIntermNode* root);
|
||||
// Collect info for all attribs and uniforms.
|
||||
void collectAttribsUniforms(TIntermNode* root);
|
||||
// Collect info for all attribs, uniforms, varyings.
|
||||
void collectVariables(TIntermNode* root);
|
||||
// Map long variable names into shorter ones.
|
||||
void mapLongVariableNames(TIntermNode* root);
|
||||
// Translate to object code.
|
||||
|
|
@ -106,6 +107,8 @@ protected:
|
|||
// Returns true if the shader does not use sampler dependent values to affect control
|
||||
// flow or in operations whose time can depend on the input values.
|
||||
bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
|
||||
// Return true if the maximum expression complexity below the limit.
|
||||
bool limitExpressionComplexity(TIntermNode* root);
|
||||
// Get built-in extensions with default behavior.
|
||||
const TExtensionBehavior& getExtensionBehavior() const;
|
||||
// Get the resources set by InitBuiltInSymbolTable
|
||||
|
|
@ -120,6 +123,8 @@ private:
|
|||
ShShaderSpec shaderSpec;
|
||||
|
||||
int maxUniformVectors;
|
||||
int maxExpressionComplexity;
|
||||
int maxCallStackDepth;
|
||||
|
||||
ShBuiltInResources compileResources;
|
||||
|
||||
|
|
@ -138,6 +143,7 @@ private:
|
|||
TInfoSink infoSink; // Output sink.
|
||||
TVariableInfoList attribs; // Active attributes in the compiled shader.
|
||||
TVariableInfoList uniforms; // Active uniforms in the compiled shader.
|
||||
TVariableInfoList varyings; // Varyings in the compiled shader.
|
||||
|
||||
// Cached copy of the ref-counted singleton.
|
||||
LongNameMap* longNameMap;
|
||||
|
|
|
|||
|
|
@ -15,20 +15,25 @@
|
|||
#include "compiler/preprocessor/length_limits.h"
|
||||
#include "compiler/ShHandle.h"
|
||||
#include "compiler/TranslatorHLSL.h"
|
||||
#include "compiler/VariablePacker.h"
|
||||
|
||||
//
|
||||
// This is the platform independent interface between an OGL driver
|
||||
// and the shading language compiler.
|
||||
//
|
||||
|
||||
static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
|
||||
size_t expectedValue)
|
||||
static bool checkVariableMaxLengths(const ShHandle handle,
|
||||
size_t expectedValue)
|
||||
{
|
||||
size_t activeUniformLimit = 0;
|
||||
ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
|
||||
size_t activeAttribLimit = 0;
|
||||
ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
|
||||
return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
|
||||
size_t varyingLimit = 0;
|
||||
ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
|
||||
return (expectedValue == activeUniformLimit &&
|
||||
expectedValue == activeAttribLimit &&
|
||||
expectedValue == varyingLimit);
|
||||
}
|
||||
|
||||
static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
|
||||
|
|
@ -38,62 +43,14 @@ static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue
|
|||
return (expectedValue == mappedNameMaxLength);
|
||||
}
|
||||
|
||||
static void getVariableInfo(ShShaderInfo varType,
|
||||
const ShHandle handle,
|
||||
int index,
|
||||
size_t* length,
|
||||
int* size,
|
||||
ShDataType* type,
|
||||
char* name,
|
||||
char* mappedName)
|
||||
{
|
||||
if (!handle || !size || !type || !name)
|
||||
return;
|
||||
ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
|
||||
(varType == SH_ACTIVE_UNIFORMS));
|
||||
|
||||
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
|
||||
TCompiler* compiler = base->getAsCompiler();
|
||||
if (compiler == 0)
|
||||
return;
|
||||
|
||||
const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
|
||||
compiler->getAttribs() : compiler->getUniforms();
|
||||
if (index < 0 || index >= static_cast<int>(varList.size()))
|
||||
return;
|
||||
|
||||
const TVariableInfo& varInfo = varList[index];
|
||||
if (length) *length = varInfo.name.size();
|
||||
*size = varInfo.size;
|
||||
*type = varInfo.type;
|
||||
|
||||
// This size must match that queried by
|
||||
// SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
|
||||
// in ShGetInfo, below.
|
||||
size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
|
||||
strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
|
||||
name[activeUniformAndAttribLength - 1] = 0;
|
||||
if (mappedName) {
|
||||
// This size must match that queried by
|
||||
// SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
|
||||
size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
|
||||
strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
|
||||
mappedName[maxMappedNameLength - 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Driver must call this first, once, before doing any other
|
||||
// compiler operations.
|
||||
// Driver must call this first, once, before doing any other compiler operations.
|
||||
// Subsequent calls to this function are no-op.
|
||||
//
|
||||
int ShInitialize()
|
||||
{
|
||||
if (!InitProcess())
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
static const bool kInitialized = InitProcess();
|
||||
return kInitialized ? 1 : 0;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -101,9 +58,7 @@ int ShInitialize()
|
|||
//
|
||||
int ShFinalize()
|
||||
{
|
||||
if (!DetachProcess())
|
||||
return 0;
|
||||
|
||||
DetachProcess();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +82,7 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
|
|||
resources->OES_EGL_image_external = 0;
|
||||
resources->ARB_texture_rectangle = 0;
|
||||
resources->EXT_draw_buffers = 0;
|
||||
resources->EXT_frag_depth = 0;
|
||||
|
||||
// Disable highp precision in fragment shader by default.
|
||||
resources->FragmentPrecisionHigh = 0;
|
||||
|
|
@ -144,9 +100,6 @@ ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
|
|||
ShShaderOutput output,
|
||||
const ShBuiltInResources* resources)
|
||||
{
|
||||
if (!InitThread())
|
||||
return 0;
|
||||
|
||||
TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
|
||||
TCompiler* compiler = base->getAsCompiler();
|
||||
if (compiler == 0)
|
||||
|
|
@ -185,9 +138,6 @@ int ShCompile(
|
|||
size_t numStrings,
|
||||
int compileOptions)
|
||||
{
|
||||
if (!InitThread())
|
||||
return 0;
|
||||
|
||||
if (handle == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -229,6 +179,12 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
|
|||
case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
|
||||
*params = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
break;
|
||||
case SH_VARYINGS:
|
||||
*params = compiler->getVaryings().size();
|
||||
break;
|
||||
case SH_VARYING_MAX_LENGTH:
|
||||
*params = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
break;
|
||||
case SH_MAPPED_NAME_MAX_LENGTH:
|
||||
// Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
|
||||
// handle array and struct dereferences.
|
||||
|
|
@ -286,28 +242,71 @@ void ShGetObjectCode(const ShHandle handle, char* objCode)
|
|||
strcpy(objCode, infoSink.obj.c_str());
|
||||
}
|
||||
|
||||
void ShGetActiveAttrib(const ShHandle handle,
|
||||
void ShGetVariableInfo(const ShHandle handle,
|
||||
ShShaderInfo varType,
|
||||
int index,
|
||||
size_t* length,
|
||||
int* size,
|
||||
ShDataType* type,
|
||||
ShPrecisionType* precision,
|
||||
int* staticUse,
|
||||
char* name,
|
||||
char* mappedName)
|
||||
{
|
||||
getVariableInfo(SH_ACTIVE_ATTRIBUTES,
|
||||
handle, index, length, size, type, name, mappedName);
|
||||
}
|
||||
if (!handle || !size || !type || !precision || !staticUse || !name)
|
||||
return;
|
||||
ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
|
||||
(varType == SH_ACTIVE_UNIFORMS) ||
|
||||
(varType == SH_VARYINGS));
|
||||
|
||||
void ShGetActiveUniform(const ShHandle handle,
|
||||
int index,
|
||||
size_t* length,
|
||||
int* size,
|
||||
ShDataType* type,
|
||||
char* name,
|
||||
char* mappedName)
|
||||
{
|
||||
getVariableInfo(SH_ACTIVE_UNIFORMS,
|
||||
handle, index, length, size, type, name, mappedName);
|
||||
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
|
||||
TCompiler* compiler = base->getAsCompiler();
|
||||
if (compiler == 0)
|
||||
return;
|
||||
|
||||
const TVariableInfoList& varList =
|
||||
varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() :
|
||||
(varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() :
|
||||
compiler->getVaryings());
|
||||
if (index < 0 || index >= static_cast<int>(varList.size()))
|
||||
return;
|
||||
|
||||
const TVariableInfo& varInfo = varList[index];
|
||||
if (length) *length = varInfo.name.size();
|
||||
*size = varInfo.size;
|
||||
*type = varInfo.type;
|
||||
switch (varInfo.precision) {
|
||||
case EbpLow:
|
||||
*precision = SH_PRECISION_LOWP;
|
||||
break;
|
||||
case EbpMedium:
|
||||
*precision = SH_PRECISION_MEDIUMP;
|
||||
break;
|
||||
case EbpHigh:
|
||||
*precision = SH_PRECISION_HIGHP;
|
||||
break;
|
||||
default:
|
||||
// Some types does not support precision, for example, boolean.
|
||||
*precision = SH_PRECISION_UNDEFINED;
|
||||
break;
|
||||
}
|
||||
*staticUse = varInfo.staticUse ? 1 : 0;
|
||||
|
||||
// This size must match that queried by
|
||||
// SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
|
||||
// in ShGetInfo, below.
|
||||
size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
ASSERT(checkVariableMaxLengths(handle, variableLength));
|
||||
strncpy(name, varInfo.name.c_str(), variableLength);
|
||||
name[variableLength - 1] = 0;
|
||||
if (mappedName) {
|
||||
// This size must match that queried by
|
||||
// SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
|
||||
size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
|
||||
ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
|
||||
strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
|
||||
mappedName[maxMappedNameLength - 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ShGetNameHashingEntry(const ShHandle handle,
|
||||
|
|
@ -370,3 +369,19 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
|
|||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
int ShCheckVariablesWithinPackingLimits(
|
||||
int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
|
||||
{
|
||||
if (varInfoArraySize == 0)
|
||||
return 1;
|
||||
ASSERT(varInfoArray);
|
||||
TVariableInfoList variables;
|
||||
for (size_t ii = 0; ii < varInfoArraySize; ++ii)
|
||||
{
|
||||
TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size);
|
||||
variables.push_back(var);
|
||||
}
|
||||
VariablePacker packer;
|
||||
return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,48 +17,34 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include <climits>
|
||||
|
||||
TType::TType(const TPublicType &p) :
|
||||
type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
|
||||
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
|
||||
type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0)
|
||||
{
|
||||
if (p.userDef) {
|
||||
if (p.userDef)
|
||||
structure = p.userDef->getStruct();
|
||||
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
|
||||
computeDeepestStructNesting();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Recursively generate mangled names.
|
||||
//
|
||||
void TType::buildMangledName(TString& mangledName)
|
||||
TString TType::buildMangledName() const
|
||||
{
|
||||
TString mangledName;
|
||||
if (isMatrix())
|
||||
mangledName += 'm';
|
||||
else if (isVector())
|
||||
mangledName += 'v';
|
||||
|
||||
switch (type) {
|
||||
case EbtFloat: mangledName += 'f'; break;
|
||||
case EbtInt: mangledName += 'i'; break;
|
||||
case EbtBool: mangledName += 'b'; break;
|
||||
case EbtSampler2D: mangledName += "s2"; break;
|
||||
case EbtSamplerCube: mangledName += "sC"; break;
|
||||
case EbtStruct:
|
||||
mangledName += "struct-";
|
||||
if (typeName)
|
||||
mangledName += *typeName;
|
||||
{// support MSVC++6.0
|
||||
for (unsigned int i = 0; i < structure->size(); ++i) {
|
||||
mangledName += '-';
|
||||
(*structure)[i].type->buildMangledName(mangledName);
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
case EbtFloat: mangledName += 'f'; break;
|
||||
case EbtInt: mangledName += 'i'; break;
|
||||
case EbtBool: mangledName += 'b'; break;
|
||||
case EbtSampler2D: mangledName += "s2"; break;
|
||||
case EbtSamplerCube: mangledName += "sC"; break;
|
||||
case EbtStruct: mangledName += structure->mangledName(); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
mangledName += static_cast<char>('0' + getNominalSize());
|
||||
|
|
@ -69,55 +55,74 @@ void TType::buildMangledName(TString& mangledName)
|
|||
mangledName += buf;
|
||||
mangledName += ']';
|
||||
}
|
||||
return mangledName;
|
||||
}
|
||||
|
||||
int TType::getStructSize() const
|
||||
size_t TType::getObjectSize() const
|
||||
{
|
||||
if (!getStruct()) {
|
||||
assert(false && "Not a struct");
|
||||
return 0;
|
||||
size_t totalSize = 0;
|
||||
|
||||
if (getBasicType() == EbtStruct)
|
||||
totalSize = structure->objectSize();
|
||||
else if (matrix)
|
||||
totalSize = size * size;
|
||||
else
|
||||
totalSize = size;
|
||||
|
||||
if (isArray()) {
|
||||
size_t arraySize = getArraySize();
|
||||
if (arraySize > INT_MAX / totalSize)
|
||||
totalSize = INT_MAX;
|
||||
else
|
||||
totalSize *= arraySize;
|
||||
}
|
||||
|
||||
if (structureSize == 0)
|
||||
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
|
||||
structureSize += ((*tl).type)->getObjectSize();
|
||||
|
||||
return structureSize;
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
void TType::computeDeepestStructNesting()
|
||||
bool TStructure::containsArrays() const
|
||||
{
|
||||
if (!getStruct()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int maxNesting = 0;
|
||||
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
|
||||
maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
|
||||
}
|
||||
|
||||
deepestStructNesting = 1 + maxNesting;
|
||||
}
|
||||
|
||||
bool TType::isStructureContainingArrays() const
|
||||
{
|
||||
if (!structure)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
|
||||
{
|
||||
if (member->type->isArray() ||
|
||||
member->type->isStructureContainingArrays())
|
||||
{
|
||||
for (size_t i = 0; i < mFields->size(); ++i) {
|
||||
const TType* fieldType = (*mFields)[i]->type();
|
||||
if (fieldType->isArray() || fieldType->isStructureContainingArrays())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TString TStructure::buildMangledName() const
|
||||
{
|
||||
TString mangledName("struct-");
|
||||
mangledName += *mName;
|
||||
for (size_t i = 0; i < mFields->size(); ++i) {
|
||||
mangledName += '-';
|
||||
mangledName += (*mFields)[i]->type()->getMangledName();
|
||||
}
|
||||
return mangledName;
|
||||
}
|
||||
|
||||
size_t TStructure::calculateObjectSize() const
|
||||
{
|
||||
size_t size = 0;
|
||||
for (size_t i = 0; i < mFields->size(); ++i) {
|
||||
size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
|
||||
if (fieldSize > INT_MAX - size)
|
||||
size = INT_MAX;
|
||||
else
|
||||
size += fieldSize;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
int TStructure::calculateDeepestNesting() const
|
||||
{
|
||||
int maxNesting = 0;
|
||||
for (size_t i = 0; i < mFields->size(); ++i) {
|
||||
maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
|
||||
}
|
||||
return 1 + maxNesting;
|
||||
}
|
||||
|
||||
//
|
||||
// Dump functions.
|
||||
//
|
||||
|
|
@ -196,84 +201,16 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
|
|||
void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
|
||||
{
|
||||
for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
|
||||
if (it->second->isFunction()) {
|
||||
TFunction* function = static_cast<TFunction*>(it->second);
|
||||
if (function->getName() == name)
|
||||
function->relateToExtension(ext);
|
||||
}
|
||||
TSymbol* symbol = it->second;
|
||||
if (symbol->getName() == name)
|
||||
symbol->relateToExtension(ext);
|
||||
}
|
||||
}
|
||||
|
||||
TSymbol::TSymbol(const TSymbol& copyOf)
|
||||
TSymbolTable::~TSymbolTable()
|
||||
{
|
||||
name = NewPoolTString(copyOf.name->c_str());
|
||||
uniqueId = copyOf.uniqueId;
|
||||
}
|
||||
|
||||
TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
|
||||
{
|
||||
type.copyType(copyOf.type, remapper);
|
||||
userType = copyOf.userType;
|
||||
// for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
|
||||
assert(copyOf.arrayInformationType == 0);
|
||||
arrayInformationType = 0;
|
||||
|
||||
if (copyOf.unionArray) {
|
||||
assert(!copyOf.type.getStruct());
|
||||
assert(copyOf.type.getObjectSize() == 1);
|
||||
unionArray = new ConstantUnion[1];
|
||||
unionArray[0] = copyOf.unionArray[0];
|
||||
} else
|
||||
unionArray = 0;
|
||||
}
|
||||
|
||||
TVariable* TVariable::clone(TStructureMap& remapper)
|
||||
{
|
||||
TVariable *variable = new TVariable(*this, remapper);
|
||||
|
||||
return variable;
|
||||
}
|
||||
|
||||
TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
|
||||
{
|
||||
for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
|
||||
TParameter param;
|
||||
parameters.push_back(param);
|
||||
parameters.back().copyParam(copyOf.parameters[i], remapper);
|
||||
}
|
||||
|
||||
returnType.copyType(copyOf.returnType, remapper);
|
||||
mangledName = copyOf.mangledName;
|
||||
op = copyOf.op;
|
||||
defined = copyOf.defined;
|
||||
}
|
||||
|
||||
TFunction* TFunction::clone(TStructureMap& remapper)
|
||||
{
|
||||
TFunction *function = new TFunction(*this, remapper);
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
|
||||
{
|
||||
TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
|
||||
tLevel::iterator iter;
|
||||
for (iter = level.begin(); iter != level.end(); ++iter) {
|
||||
symTableLevel->insert(*iter->second->clone(remapper));
|
||||
}
|
||||
|
||||
return symTableLevel;
|
||||
}
|
||||
|
||||
void TSymbolTable::copyTable(const TSymbolTable& copyOf)
|
||||
{
|
||||
TStructureMap remapper;
|
||||
uniqueId = copyOf.uniqueId;
|
||||
for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
|
||||
table.push_back(copyOf.table[i]->clone(remapper));
|
||||
}
|
||||
for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
|
||||
precisionStack.push_back( copyOf.precisionStack[i] );
|
||||
}
|
||||
for (size_t i = 0; i < table.size(); ++i)
|
||||
delete table[i];
|
||||
for (size_t i = 0; i < precisionStack.size(); ++i)
|
||||
delete precisionStack[i];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include "compiler/InfoSink.h"
|
||||
#include "compiler/intermediate.h"
|
||||
|
||||
|
|
@ -40,22 +41,26 @@
|
|||
//
|
||||
class TSymbol {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||
TSymbol(const TString *n) : name(n) { }
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
TSymbol(const TString* n) : uniqueId(0), name(n) { }
|
||||
virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
|
||||
|
||||
const TString& getName() const { return *name; }
|
||||
virtual const TString& getMangledName() const { return getName(); }
|
||||
virtual bool isFunction() const { return false; }
|
||||
virtual bool isVariable() const { return false; }
|
||||
void setUniqueId(int id) { uniqueId = id; }
|
||||
int getUniqueId() const { return uniqueId; }
|
||||
virtual void dump(TInfoSink &infoSink) const = 0;
|
||||
TSymbol(const TSymbol&);
|
||||
virtual TSymbol* clone(TStructureMap& remapper) = 0;
|
||||
virtual void dump(TInfoSink &infoSink) const = 0;
|
||||
void relateToExtension(const TString& ext) { extension = ext; }
|
||||
const TString& getExtension() const { return extension; }
|
||||
|
||||
protected:
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TSymbol);
|
||||
|
||||
int uniqueId; // For real comparing during code generation
|
||||
const TString *name;
|
||||
unsigned int uniqueId; // For real comparing during code generation
|
||||
TString extension;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -70,15 +75,13 @@ protected:
|
|||
//
|
||||
class TVariable : public TSymbol {
|
||||
public:
|
||||
TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0), arrayInformationType(0) { }
|
||||
TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { }
|
||||
virtual ~TVariable() { }
|
||||
virtual bool isVariable() const { return true; }
|
||||
TType& getType() { return type; }
|
||||
const TType& getType() const { return type; }
|
||||
bool isUserType() const { return userType; }
|
||||
void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
|
||||
void updateArrayInformationType(TType *t) { arrayInformationType = t; }
|
||||
TType* getArrayInformationType() { return arrayInformationType; }
|
||||
|
||||
virtual void dump(TInfoSink &infoSink) const;
|
||||
|
||||
|
|
@ -100,16 +103,15 @@ public:
|
|||
delete[] unionArray;
|
||||
unionArray = constArray;
|
||||
}
|
||||
TVariable(const TVariable&, TStructureMap& remapper); // copy constructor
|
||||
virtual TVariable* clone(TStructureMap& remapper);
|
||||
|
||||
protected:
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TVariable);
|
||||
|
||||
TType type;
|
||||
bool userType;
|
||||
// we are assuming that Pool Allocator will free the memory allocated to unionArray
|
||||
// when this object is destroyed
|
||||
ConstantUnion *unionArray;
|
||||
TType *arrayInformationType; // this is used for updating maxArraySize in all the references to a given symbol
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -119,11 +121,6 @@ protected:
|
|||
struct TParameter {
|
||||
TString *name;
|
||||
TType* type;
|
||||
void copyParam(const TParameter& param, TStructureMap& remapper)
|
||||
{
|
||||
name = NewPoolTString(param.name->c_str());
|
||||
type = param.type->clone(remapper);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -163,9 +160,6 @@ public:
|
|||
void relateToOperator(TOperator o) { op = o; }
|
||||
TOperator getBuiltInOp() const { return op; }
|
||||
|
||||
void relateToExtension(const TString& ext) { extension = ext; }
|
||||
const TString& getExtension() const { return extension; }
|
||||
|
||||
void setDefined() { defined = true; }
|
||||
bool isDefined() { return defined; }
|
||||
|
||||
|
|
@ -173,16 +167,15 @@ public:
|
|||
const TParameter& getParam(size_t i) const { return parameters[i]; }
|
||||
|
||||
virtual void dump(TInfoSink &infoSink) const;
|
||||
TFunction(const TFunction&, TStructureMap& remapper);
|
||||
virtual TFunction* clone(TStructureMap& remapper);
|
||||
|
||||
protected:
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TFunction);
|
||||
|
||||
typedef TVector<TParameter> TParamList;
|
||||
TParamList parameters;
|
||||
TType returnType;
|
||||
TString mangledName;
|
||||
TOperator op;
|
||||
TString extension;
|
||||
bool defined;
|
||||
};
|
||||
|
||||
|
|
@ -194,21 +187,24 @@ public:
|
|||
typedef const tLevel::value_type tLevelPair;
|
||||
typedef std::pair<tLevel::iterator, bool> tInsertResult;
|
||||
|
||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||
TSymbolTableLevel() { }
|
||||
~TSymbolTableLevel();
|
||||
|
||||
bool insert(TSymbol& symbol)
|
||||
bool insert(const TString &name, TSymbol &symbol)
|
||||
{
|
||||
//
|
||||
// returning true means symbol was added to the table
|
||||
//
|
||||
tInsertResult result;
|
||||
result = level.insert(tLevelPair(symbol.getMangledName(), &symbol));
|
||||
tInsertResult result = level.insert(tLevelPair(name, &symbol));
|
||||
|
||||
return result.second;
|
||||
}
|
||||
|
||||
bool insert(TSymbol &symbol)
|
||||
{
|
||||
return insert(symbol.getMangledName(), symbol);
|
||||
}
|
||||
|
||||
TSymbol* find(const TString& name) const
|
||||
{
|
||||
tLevel::const_iterator it = level.find(name);
|
||||
|
|
@ -231,7 +227,6 @@ public:
|
|||
void relateToOperator(const char* name, TOperator op);
|
||||
void relateToExtension(const char* name, const TString& ext);
|
||||
void dump(TInfoSink &infoSink) const;
|
||||
TSymbolTableLevel* clone(TStructureMap& remapper);
|
||||
|
||||
protected:
|
||||
tLevel level;
|
||||
|
|
@ -247,13 +242,7 @@ public:
|
|||
// that the symbol table has not been preloaded with built-ins.
|
||||
//
|
||||
}
|
||||
|
||||
~TSymbolTable()
|
||||
{
|
||||
// level 0 is always built In symbols, so we never pop that out
|
||||
while (table.size() > 1)
|
||||
pop();
|
||||
}
|
||||
~TSymbolTable();
|
||||
|
||||
//
|
||||
// When the symbol table is initialized with the built-ins, there should
|
||||
|
|
@ -266,13 +255,15 @@ public:
|
|||
void push()
|
||||
{
|
||||
table.push_back(new TSymbolTableLevel);
|
||||
precisionStack.push_back( PrecisionStackLevel() );
|
||||
precisionStack.push_back(new PrecisionStackLevel);
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
delete table[currentLevel()];
|
||||
table.pop_back();
|
||||
{
|
||||
delete table.back();
|
||||
table.pop_back();
|
||||
|
||||
delete precisionStack.back();
|
||||
precisionStack.pop_back();
|
||||
}
|
||||
|
||||
|
|
@ -282,6 +273,35 @@ public:
|
|||
return table[currentLevel()]->insert(symbol);
|
||||
}
|
||||
|
||||
bool insertConstInt(const char *name, int value)
|
||||
{
|
||||
TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
|
||||
constant->getConstPointer()->setIConst(value);
|
||||
return insert(*constant);
|
||||
}
|
||||
|
||||
bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0)
|
||||
{
|
||||
TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
|
||||
|
||||
TParameter param1 = {NULL, ptype1};
|
||||
function->addParameter(param1);
|
||||
|
||||
if(ptype2)
|
||||
{
|
||||
TParameter param2 = {NULL, ptype2};
|
||||
function->addParameter(param2);
|
||||
}
|
||||
|
||||
if(ptype3)
|
||||
{
|
||||
TParameter param3 = {NULL, ptype3};
|
||||
function->addParameter(param3);
|
||||
}
|
||||
|
||||
return insert(*function);
|
||||
}
|
||||
|
||||
TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0)
|
||||
{
|
||||
int level = currentLevel();
|
||||
|
|
@ -298,16 +318,11 @@ public:
|
|||
return symbol;
|
||||
}
|
||||
|
||||
TSymbol *findBuiltIn(const TString &name)
|
||||
TSymbol* findBuiltIn(const TString &name)
|
||||
{
|
||||
return table[0]->find(name);
|
||||
}
|
||||
|
||||
TSymbolTableLevel* getGlobalLevel() {
|
||||
assert(table.size() >= 2);
|
||||
return table[1];
|
||||
}
|
||||
|
||||
TSymbolTableLevel* getOuterLevel() {
|
||||
assert(table.size() >= 2);
|
||||
return table[currentLevel() - 1];
|
||||
|
|
@ -319,32 +334,29 @@ public:
|
|||
void relateToExtension(const char* name, const TString& ext) {
|
||||
table[0]->relateToExtension(name, ext);
|
||||
}
|
||||
int getMaxSymbolId() { return uniqueId; }
|
||||
void dump(TInfoSink &infoSink) const;
|
||||
void copyTable(const TSymbolTable& copyOf);
|
||||
|
||||
bool setDefaultPrecision( const TPublicType& type, TPrecision prec ){
|
||||
if (IsSampler(type.type))
|
||||
return true; // Skip sampler types for the time being
|
||||
if (type.type != EbtFloat && type.type != EbtInt)
|
||||
return false; // Only set default precision for int/float
|
||||
bool setDefaultPrecision(const TPublicType& type, TPrecision prec) {
|
||||
if (!supportsPrecision(type.type))
|
||||
return false;
|
||||
if (type.size != 1 || type.matrix || type.array)
|
||||
return false; // Not allowed to set for aggregate types
|
||||
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
|
||||
precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value
|
||||
(*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value
|
||||
return true;
|
||||
}
|
||||
|
||||
// Searches down the precisionStack for a precision qualifier for the specified TBasicType
|
||||
TPrecision getDefaultPrecision( TBasicType type){
|
||||
if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
|
||||
TPrecision getDefaultPrecision(TBasicType type) {
|
||||
if (!supportsPrecision(type))
|
||||
return EbpUndefined;
|
||||
int level = static_cast<int>(precisionStack.size()) - 1;
|
||||
assert( level >= 0); // Just to be safe. Should not happen.
|
||||
assert(level >= 0); // Just to be safe. Should not happen.
|
||||
PrecisionStackLevel::iterator it;
|
||||
TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
|
||||
while( level >= 0 ){
|
||||
it = precisionStack[level].find( type );
|
||||
if( it != precisionStack[level].end() ){
|
||||
while (level >= 0) {
|
||||
it = precisionStack[level]->find(type);
|
||||
if (it != precisionStack[level]->end()) {
|
||||
prec = (*it).second;
|
||||
break;
|
||||
}
|
||||
|
|
@ -353,13 +365,18 @@ public:
|
|||
return prec;
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
|
||||
|
||||
std::vector<TSymbolTableLevel*> table;
|
||||
typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
|
||||
std::vector< PrecisionStackLevel > precisionStack;
|
||||
bool supportsPrecision(TBasicType type) {
|
||||
// Only supports precision for int, float, and sampler types.
|
||||
return type == EbtFloat || type == EbtInt || IsSampler(type);
|
||||
}
|
||||
|
||||
int uniqueId; // for unique identification in code generation
|
||||
std::vector<TSymbolTableLevel*> table;
|
||||
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
|
||||
std::vector<PrecisionStackLevel*> precisionStack;
|
||||
};
|
||||
|
||||
#endif // _SYMBOL_TABLE_INCLUDED_
|
||||
|
|
|
|||
|
|
@ -7,30 +7,85 @@
|
|||
#ifndef _TYPES_INCLUDED
|
||||
#define _TYPES_INCLUDED
|
||||
|
||||
#include "common/angleutils.h"
|
||||
|
||||
#include "compiler/BaseTypes.h"
|
||||
#include "compiler/Common.h"
|
||||
#include "compiler/debug.h"
|
||||
|
||||
class TType;
|
||||
struct TPublicType;
|
||||
class TType;
|
||||
|
||||
//
|
||||
// Need to have association of line numbers to types in a list for building structs.
|
||||
//
|
||||
struct TTypeLine {
|
||||
TType* type;
|
||||
int line;
|
||||
};
|
||||
typedef TVector<TTypeLine> TTypeList;
|
||||
|
||||
inline TTypeList* NewPoolTTypeList()
|
||||
class TField
|
||||
{
|
||||
void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
|
||||
return new(memory) TTypeList;
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
TField(TType* type, TString* name) : mType(type), mName(name) {}
|
||||
|
||||
// TODO(alokp): We should only return const type.
|
||||
// Fix it by tweaking grammar.
|
||||
TType* type() { return mType; }
|
||||
const TType* type() const { return mType; }
|
||||
|
||||
const TString& name() const { return *mName; }
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TField);
|
||||
TType* mType;
|
||||
TString* mName;
|
||||
};
|
||||
|
||||
typedef TVector<TField*> TFieldList;
|
||||
inline TFieldList* NewPoolTFieldList()
|
||||
{
|
||||
void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
|
||||
return new(memory) TFieldList;
|
||||
}
|
||||
|
||||
typedef TMap<TTypeList*, TTypeList*> TStructureMap;
|
||||
typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
|
||||
class TStructure
|
||||
{
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
TStructure(TString* name, TFieldList* fields)
|
||||
: mName(name),
|
||||
mFields(fields),
|
||||
mObjectSize(0),
|
||||
mDeepestNesting(0) {
|
||||
}
|
||||
|
||||
const TString& name() const { return *mName; }
|
||||
const TFieldList& fields() const { return *mFields; }
|
||||
|
||||
const TString& mangledName() const {
|
||||
if (mMangledName.empty())
|
||||
mMangledName = buildMangledName();
|
||||
return mMangledName;
|
||||
}
|
||||
size_t objectSize() const {
|
||||
if (mObjectSize == 0)
|
||||
mObjectSize = calculateObjectSize();
|
||||
return mObjectSize;
|
||||
};
|
||||
int deepestNesting() const {
|
||||
if (mDeepestNesting == 0)
|
||||
mDeepestNesting = calculateDeepestNesting();
|
||||
return mDeepestNesting;
|
||||
}
|
||||
bool containsArrays() const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TStructure);
|
||||
TString buildMangledName() const;
|
||||
size_t calculateObjectSize() const;
|
||||
int calculateDeepestNesting() const;
|
||||
|
||||
TString* mName;
|
||||
TFieldList* mFields;
|
||||
|
||||
mutable TString mMangledName;
|
||||
mutable size_t mObjectSize;
|
||||
mutable int mDeepestNesting;
|
||||
};
|
||||
|
||||
//
|
||||
// Base class for things that have a type.
|
||||
|
|
@ -38,72 +93,16 @@ typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
|
|||
class TType
|
||||
{
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
TType() {}
|
||||
TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
|
||||
type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
|
||||
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
|
||||
type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0)
|
||||
{
|
||||
}
|
||||
explicit TType(const TPublicType &p);
|
||||
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
|
||||
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
|
||||
maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
|
||||
TType(TStructure* userDef, TPrecision p = EbpUndefined) :
|
||||
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef)
|
||||
{
|
||||
typeName = NewPoolTString(n.c_str());
|
||||
}
|
||||
|
||||
void copyType(const TType& copyOf, TStructureMap& remapper)
|
||||
{
|
||||
type = copyOf.type;
|
||||
precision = copyOf.precision;
|
||||
qualifier = copyOf.qualifier;
|
||||
size = copyOf.size;
|
||||
matrix = copyOf.matrix;
|
||||
array = copyOf.array;
|
||||
arraySize = copyOf.arraySize;
|
||||
|
||||
TStructureMapIterator iter;
|
||||
if (copyOf.structure) {
|
||||
if ((iter = remapper.find(structure)) == remapper.end()) {
|
||||
// create the new structure here
|
||||
structure = NewPoolTTypeList();
|
||||
for (unsigned int i = 0; i < copyOf.structure->size(); ++i) {
|
||||
TTypeLine typeLine;
|
||||
typeLine.line = (*copyOf.structure)[i].line;
|
||||
typeLine.type = (*copyOf.structure)[i].type->clone(remapper);
|
||||
structure->push_back(typeLine);
|
||||
}
|
||||
} else {
|
||||
structure = iter->second;
|
||||
}
|
||||
} else
|
||||
structure = 0;
|
||||
|
||||
fieldName = 0;
|
||||
if (copyOf.fieldName)
|
||||
fieldName = NewPoolTString(copyOf.fieldName->c_str());
|
||||
typeName = 0;
|
||||
if (copyOf.typeName)
|
||||
typeName = NewPoolTString(copyOf.typeName->c_str());
|
||||
|
||||
mangled = 0;
|
||||
if (copyOf.mangled)
|
||||
mangled = NewPoolTString(copyOf.mangled->c_str());
|
||||
|
||||
structureSize = copyOf.structureSize;
|
||||
maxArraySize = copyOf.maxArraySize;
|
||||
deepestStructNesting = copyOf.deepestStructNesting;
|
||||
assert(copyOf.arrayInformationType == 0);
|
||||
arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
|
||||
}
|
||||
|
||||
TType* clone(TStructureMap& remapper)
|
||||
{
|
||||
TType *newType = new TType();
|
||||
newType->copyType(*this, remapper);
|
||||
|
||||
return newType;
|
||||
}
|
||||
|
||||
TBasicType getBasicType() const { return type; }
|
||||
|
|
@ -119,34 +118,18 @@ public:
|
|||
int getNominalSize() const { return size; }
|
||||
void setNominalSize(int s) { size = s; }
|
||||
// Full size of single instance of type
|
||||
int getObjectSize() const
|
||||
{
|
||||
int totalSize;
|
||||
|
||||
if (getBasicType() == EbtStruct)
|
||||
totalSize = getStructSize();
|
||||
else if (matrix)
|
||||
totalSize = size * size;
|
||||
else
|
||||
totalSize = size;
|
||||
|
||||
if (isArray())
|
||||
totalSize *= std::max(getArraySize(), getMaxArraySize());
|
||||
|
||||
return totalSize;
|
||||
}
|
||||
size_t getObjectSize() const;
|
||||
|
||||
int elementRegisterCount() const
|
||||
{
|
||||
TTypeList *structure = getStruct();
|
||||
|
||||
if (structure)
|
||||
{
|
||||
const TFieldList &fields = getStruct()->fields();
|
||||
int registerCount = 0;
|
||||
|
||||
for (size_t i = 0; i < structure->size(); i++)
|
||||
for (size_t i = 0; i < fields.size(); i++)
|
||||
{
|
||||
registerCount += (*structure)[i].type->totalRegisterCount();
|
||||
registerCount += fields[i]->type()->totalRegisterCount();
|
||||
}
|
||||
|
||||
return registerCount;
|
||||
|
|
@ -179,47 +162,20 @@ public:
|
|||
bool isArray() const { return array ? true : false; }
|
||||
int getArraySize() const { return arraySize; }
|
||||
void setArraySize(int s) { array = true; arraySize = s; }
|
||||
int getMaxArraySize () const { return maxArraySize; }
|
||||
void setMaxArraySize (int s) { maxArraySize = s; }
|
||||
void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
|
||||
void setArrayInformationType(TType* t) { arrayInformationType = t; }
|
||||
TType* getArrayInformationType() const { return arrayInformationType; }
|
||||
void clearArrayness() { array = false; arraySize = 0; }
|
||||
|
||||
bool isVector() const { return size > 1 && !matrix; }
|
||||
bool isScalar() const { return size == 1 && !matrix && !structure; }
|
||||
|
||||
TTypeList* getStruct() const { return structure; }
|
||||
void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
|
||||
TStructure* getStruct() const { return structure; }
|
||||
void setStruct(TStructure* s) { structure = s; }
|
||||
|
||||
const TString& getTypeName() const
|
||||
{
|
||||
assert(typeName);
|
||||
return *typeName;
|
||||
}
|
||||
void setTypeName(const TString& n)
|
||||
{
|
||||
typeName = NewPoolTString(n.c_str());
|
||||
}
|
||||
|
||||
bool isField() const { return fieldName != 0; }
|
||||
const TString& getFieldName() const
|
||||
{
|
||||
assert(fieldName);
|
||||
return *fieldName;
|
||||
}
|
||||
void setFieldName(const TString& n)
|
||||
{
|
||||
fieldName = NewPoolTString(n.c_str());
|
||||
}
|
||||
|
||||
TString& getMangledName() {
|
||||
if (!mangled) {
|
||||
mangled = NewPoolTString("");
|
||||
buildMangledName(*mangled);
|
||||
*mangled += ';' ;
|
||||
const TString& getMangledName() const {
|
||||
if (mangled.empty()) {
|
||||
mangled = buildMangledName();
|
||||
mangled += ';';
|
||||
}
|
||||
|
||||
return *mangled;
|
||||
return mangled;
|
||||
}
|
||||
|
||||
bool sameElementType(const TType& right) const {
|
||||
|
|
@ -267,14 +223,16 @@ public:
|
|||
// For type "nesting2", this method would return 2 -- the number
|
||||
// of structures through which indirection must occur to reach the
|
||||
// deepest field (nesting2.field1.position).
|
||||
int getDeepestStructNesting() const { return deepestStructNesting; }
|
||||
int getDeepestStructNesting() const {
|
||||
return structure ? structure->deepestNesting() : 0;
|
||||
}
|
||||
|
||||
bool isStructureContainingArrays() const;
|
||||
bool isStructureContainingArrays() const {
|
||||
return structure ? structure->containsArrays() : false;
|
||||
}
|
||||
|
||||
protected:
|
||||
void buildMangledName(TString&);
|
||||
int getStructSize() const;
|
||||
void computeDeepestStructNesting();
|
||||
private:
|
||||
TString buildMangledName() const;
|
||||
|
||||
TBasicType type : 6;
|
||||
TPrecision precision;
|
||||
|
|
@ -283,16 +241,10 @@ protected:
|
|||
unsigned int matrix : 1;
|
||||
unsigned int array : 1;
|
||||
int arraySize;
|
||||
int maxArraySize;
|
||||
TType* arrayInformationType;
|
||||
|
||||
TTypeList* structure; // 0 unless this is a struct
|
||||
mutable int structureSize;
|
||||
int deepestStructNesting;
|
||||
TStructure* structure; // 0 unless this is a struct
|
||||
|
||||
TString *fieldName; // for structure field names
|
||||
TString *mangled;
|
||||
TString *typeName; // for structure field type name
|
||||
mutable TString mangled;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -314,9 +266,9 @@ struct TPublicType
|
|||
bool array;
|
||||
int arraySize;
|
||||
TType* userDef;
|
||||
int line;
|
||||
TSourceLoc line;
|
||||
|
||||
void setBasic(TBasicType bt, TQualifier q, int ln = 0)
|
||||
void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln)
|
||||
{
|
||||
type = bt;
|
||||
qualifier = q;
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
|
|||
return true;
|
||||
|
||||
bool valid = true;
|
||||
TSymbolTable& symbolTable = GlobalParseContext->symbolTable;
|
||||
TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
|
||||
TSymbol* symbol = symbolTable.find(node->getName());
|
||||
ASSERT(symbol && symbol->isFunction());
|
||||
TFunction* function = static_cast<TFunction*>(symbol);
|
||||
|
|
|
|||
|
|
@ -6,15 +6,17 @@
|
|||
|
||||
#include "compiler/VariableInfo.h"
|
||||
|
||||
static TString arrayBrackets(int index)
|
||||
namespace {
|
||||
|
||||
TString arrayBrackets(int index)
|
||||
{
|
||||
TStringStream stream;
|
||||
stream << "[" << index << "]";
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
// Returns the data type for an attribute or uniform.
|
||||
static ShDataType getVariableDataType(const TType& type)
|
||||
// Returns the data type for an attribute, uniform, or varying.
|
||||
ShDataType getVariableDataType(const TType& type)
|
||||
{
|
||||
switch (type.getBasicType()) {
|
||||
case EbtFloat:
|
||||
|
|
@ -70,22 +72,22 @@ static ShDataType getVariableDataType(const TType& type)
|
|||
return SH_NONE;
|
||||
}
|
||||
|
||||
static void getBuiltInVariableInfo(const TType& type,
|
||||
const TString& name,
|
||||
const TString& mappedName,
|
||||
TVariableInfoList& infoList);
|
||||
static void getUserDefinedVariableInfo(const TType& type,
|
||||
const TString& name,
|
||||
const TString& mappedName,
|
||||
TVariableInfoList& infoList,
|
||||
ShHashFunction64 hashFunction);
|
||||
|
||||
// Returns info for an attribute or uniform.
|
||||
static void getVariableInfo(const TType& type,
|
||||
void getBuiltInVariableInfo(const TType& type,
|
||||
const TString& name,
|
||||
const TString& mappedName,
|
||||
TVariableInfoList& infoList,
|
||||
ShHashFunction64 hashFunction)
|
||||
TVariableInfoList& infoList);
|
||||
void getUserDefinedVariableInfo(const TType& type,
|
||||
const TString& name,
|
||||
const TString& mappedName,
|
||||
TVariableInfoList& infoList,
|
||||
ShHashFunction64 hashFunction);
|
||||
|
||||
// Returns info for an attribute, uniform, or varying.
|
||||
void getVariableInfo(const TType& type,
|
||||
const TString& name,
|
||||
const TString& mappedName,
|
||||
TVariableInfoList& infoList,
|
||||
ShHashFunction64 hashFunction)
|
||||
{
|
||||
if (type.getBasicType() == EbtStruct) {
|
||||
if (type.isArray()) {
|
||||
|
|
@ -119,6 +121,7 @@ void getBuiltInVariableInfo(const TType& type,
|
|||
varInfo.mappedName = mappedName.c_str();
|
||||
varInfo.size = 1;
|
||||
}
|
||||
varInfo.precision = type.getPrecision();
|
||||
varInfo.type = getVariableDataType(type);
|
||||
infoList.push_back(varInfo);
|
||||
}
|
||||
|
|
@ -131,86 +134,156 @@ void getUserDefinedVariableInfo(const TType& type,
|
|||
{
|
||||
ASSERT(type.getBasicType() == EbtStruct);
|
||||
|
||||
const TTypeList* structure = type.getStruct();
|
||||
for (size_t i = 0; i < structure->size(); ++i) {
|
||||
const TType* fieldType = (*structure)[i].type;
|
||||
getVariableInfo(*fieldType,
|
||||
name + "." + fieldType->getFieldName(),
|
||||
mappedName + "." + TIntermTraverser::hash(fieldType->getFieldName(), hashFunction),
|
||||
const TFieldList& fields = type.getStruct()->fields();
|
||||
for (size_t i = 0; i < fields.size(); ++i) {
|
||||
const TType& fieldType = *(fields[i]->type());
|
||||
const TString& fieldName = fields[i]->name();
|
||||
getVariableInfo(fieldType,
|
||||
name + "." + fieldName,
|
||||
mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
|
||||
infoList,
|
||||
hashFunction);
|
||||
}
|
||||
}
|
||||
|
||||
TVariableInfo* findVariable(const TType& type,
|
||||
const TString& name,
|
||||
TVariableInfoList& infoList)
|
||||
{
|
||||
// TODO(zmo): optimize this function.
|
||||
TString myName = name;
|
||||
if (type.isArray())
|
||||
myName += "[0]";
|
||||
for (size_t ii = 0; ii < infoList.size(); ++ii)
|
||||
{
|
||||
if (infoList[ii].name.c_str() == myName)
|
||||
return &(infoList[ii]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
TVariableInfo::TVariableInfo()
|
||||
: type(SH_NONE),
|
||||
size(0),
|
||||
precision(EbpUndefined),
|
||||
staticUse(false)
|
||||
{
|
||||
}
|
||||
|
||||
TVariableInfo::TVariableInfo(ShDataType type, int size)
|
||||
: type(type),
|
||||
size(size)
|
||||
size(size),
|
||||
precision(EbpUndefined),
|
||||
staticUse(false)
|
||||
{
|
||||
}
|
||||
|
||||
CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
|
||||
TVariableInfoList& uniforms,
|
||||
ShHashFunction64 hashFunction)
|
||||
CollectVariables::CollectVariables(TVariableInfoList& attribs,
|
||||
TVariableInfoList& uniforms,
|
||||
TVariableInfoList& varyings,
|
||||
ShHashFunction64 hashFunction)
|
||||
: mAttribs(attribs),
|
||||
mUniforms(uniforms),
|
||||
mVaryings(varyings),
|
||||
mPointCoordAdded(false),
|
||||
mFrontFacingAdded(false),
|
||||
mFragCoordAdded(false),
|
||||
mHashFunction(hashFunction)
|
||||
{
|
||||
}
|
||||
|
||||
// We are only interested in attribute and uniform variable declaration.
|
||||
void CollectAttribsUniforms::visitSymbol(TIntermSymbol*)
|
||||
// We want to check whether a uniform/varying is statically used
|
||||
// because we only count the used ones in packing computing.
|
||||
// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
|
||||
// toward varying counting if they are statically used in a fragment
|
||||
// shader.
|
||||
void CollectVariables::visitSymbol(TIntermSymbol* symbol)
|
||||
{
|
||||
ASSERT(symbol != NULL);
|
||||
TVariableInfo* var = NULL;
|
||||
switch (symbol->getQualifier())
|
||||
{
|
||||
case EvqVaryingOut:
|
||||
case EvqInvariantVaryingOut:
|
||||
case EvqVaryingIn:
|
||||
case EvqInvariantVaryingIn:
|
||||
var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
|
||||
break;
|
||||
case EvqUniform:
|
||||
var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
|
||||
break;
|
||||
case EvqFragCoord:
|
||||
if (!mFragCoordAdded) {
|
||||
TVariableInfo info;
|
||||
info.name = "gl_FragCoord";
|
||||
info.mappedName = "gl_FragCoord";
|
||||
info.type = SH_FLOAT_VEC4;
|
||||
info.size = 1;
|
||||
info.precision = EbpMedium; // Use mediump as it doesn't really matter.
|
||||
info.staticUse = true;
|
||||
mVaryings.push_back(info);
|
||||
mFragCoordAdded = true;
|
||||
}
|
||||
return;
|
||||
case EvqFrontFacing:
|
||||
if (!mFrontFacingAdded) {
|
||||
TVariableInfo info;
|
||||
info.name = "gl_FrontFacing";
|
||||
info.mappedName = "gl_FrontFacing";
|
||||
info.type = SH_BOOL;
|
||||
info.size = 1;
|
||||
info.precision = EbpUndefined;
|
||||
info.staticUse = true;
|
||||
mVaryings.push_back(info);
|
||||
mFrontFacingAdded = true;
|
||||
}
|
||||
return;
|
||||
case EvqPointCoord:
|
||||
if (!mPointCoordAdded) {
|
||||
TVariableInfo info;
|
||||
info.name = "gl_PointCoord";
|
||||
info.mappedName = "gl_PointCoord";
|
||||
info.type = SH_FLOAT_VEC2;
|
||||
info.size = 1;
|
||||
info.precision = EbpMedium; // Use mediump as it doesn't really matter.
|
||||
info.staticUse = true;
|
||||
mVaryings.push_back(info);
|
||||
mPointCoordAdded = true;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (var)
|
||||
var->staticUse = true;
|
||||
}
|
||||
|
||||
void CollectAttribsUniforms::visitConstantUnion(TIntermConstantUnion*)
|
||||
bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
|
||||
{
|
||||
}
|
||||
|
||||
bool CollectAttribsUniforms::visitBinary(Visit, TIntermBinary*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CollectAttribsUniforms::visitUnary(Visit, TIntermUnary*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CollectAttribsUniforms::visitSelection(Visit, TIntermSelection*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
|
||||
{
|
||||
bool visitChildren = false;
|
||||
bool visitChildren = true;
|
||||
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpSequence:
|
||||
// We need to visit sequence children to get to variable declarations.
|
||||
visitChildren = true;
|
||||
break;
|
||||
case EOpDeclaration: {
|
||||
const TIntermSequence& sequence = node->getSequence();
|
||||
TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
|
||||
if (qualifier == EvqAttribute || qualifier == EvqUniform)
|
||||
if (qualifier == EvqAttribute || qualifier == EvqUniform ||
|
||||
qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
|
||||
qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
|
||||
{
|
||||
TVariableInfoList& infoList = qualifier == EvqAttribute ?
|
||||
mAttribs : mUniforms;
|
||||
TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs :
|
||||
(qualifier == EvqUniform ? mUniforms : mVaryings);
|
||||
for (TIntermSequence::const_iterator i = sequence.begin();
|
||||
i != sequence.end(); ++i)
|
||||
{
|
||||
const TIntermSymbol* variable = (*i)->getAsSymbolNode();
|
||||
// The only case in which the sequence will not contain a
|
||||
// TIntermSymbol node is initialization. It will contain a
|
||||
// TInterBinary node in that case. Since attributes and unifroms
|
||||
// cannot be initialized in a shader, we must have only
|
||||
// TIntermSymbol nodes in the sequence.
|
||||
// TInterBinary node in that case. Since attributes, uniforms,
|
||||
// and varyings cannot be initialized in a shader, we must have
|
||||
// only TIntermSymbol nodes in the sequence.
|
||||
ASSERT(variable != NULL);
|
||||
TString processedSymbol;
|
||||
if (mHashFunction == NULL)
|
||||
|
|
@ -222,6 +295,7 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
|
|||
processedSymbol,
|
||||
infoList,
|
||||
mHashFunction);
|
||||
visitChildren = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -232,13 +306,3 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
|
|||
return visitChildren;
|
||||
}
|
||||
|
||||
bool CollectAttribsUniforms::visitLoop(Visit, TIntermLoop*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CollectAttribsUniforms::visitBranch(Visit, TIntermBranch*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,28 +20,30 @@ struct TVariableInfo {
|
|||
TPersistString mappedName;
|
||||
ShDataType type;
|
||||
int size;
|
||||
TPrecision precision;
|
||||
bool staticUse;
|
||||
};
|
||||
typedef std::vector<TVariableInfo> TVariableInfoList;
|
||||
|
||||
// Traverses intermediate tree to collect all attributes and uniforms.
|
||||
class CollectAttribsUniforms : public TIntermTraverser {
|
||||
// Traverses intermediate tree to collect all attributes, uniforms, varyings.
|
||||
class CollectVariables : public TIntermTraverser {
|
||||
public:
|
||||
CollectAttribsUniforms(TVariableInfoList& attribs,
|
||||
TVariableInfoList& uniforms,
|
||||
ShHashFunction64 hashFunction);
|
||||
CollectVariables(TVariableInfoList& attribs,
|
||||
TVariableInfoList& uniforms,
|
||||
TVariableInfoList& varyings,
|
||||
ShHashFunction64 hashFunction);
|
||||
|
||||
virtual void visitSymbol(TIntermSymbol*);
|
||||
virtual void visitConstantUnion(TIntermConstantUnion*);
|
||||
virtual bool visitBinary(Visit, TIntermBinary*);
|
||||
virtual bool visitUnary(Visit, TIntermUnary*);
|
||||
virtual bool visitSelection(Visit, TIntermSelection*);
|
||||
virtual bool visitAggregate(Visit, TIntermAggregate*);
|
||||
virtual bool visitLoop(Visit, TIntermLoop*);
|
||||
virtual bool visitBranch(Visit, TIntermBranch*);
|
||||
|
||||
private:
|
||||
TVariableInfoList& mAttribs;
|
||||
TVariableInfoList& mUniforms;
|
||||
TVariableInfoList& mVaryings;
|
||||
|
||||
bool mPointCoordAdded;
|
||||
bool mFrontFacingAdded;
|
||||
bool mFragCoordAdded;
|
||||
|
||||
ShHashFunction64 mHashFunction;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -47,20 +47,23 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
|
|||
#pragma warning(disable : 4102)
|
||||
#endif
|
||||
|
||||
#define YY_USER_ACTION yylval->lex.line = yylineno;
|
||||
#define YY_USER_ACTION \
|
||||
yylloc->first_file = yylloc->last_file = yycolumn; \
|
||||
yylloc->first_line = yylloc->last_line = yylineno;
|
||||
|
||||
#define YY_INPUT(buf, result, max_size) \
|
||||
result = string_input(buf, max_size, yyscanner);
|
||||
|
||||
static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
|
||||
static int check_type(yyscan_t yyscanner);
|
||||
static int reserved_word(yyscan_t yyscanner);
|
||||
static int int_constant(yyscan_t yyscanner);
|
||||
static int float_constant(yyscan_t yyscanner);
|
||||
%}
|
||||
|
||||
%option noyywrap nounput never-interactive
|
||||
%option yylineno reentrant bison-bridge
|
||||
%option stack
|
||||
%option yylineno reentrant bison-bridge bison-locations
|
||||
%option extra-type="TParseContext*"
|
||||
%x COMMENT FIELDS
|
||||
|
||||
D [0-9]
|
||||
L [a-zA-Z_]
|
||||
|
|
@ -70,73 +73,60 @@ O [0-7]
|
|||
|
||||
%%
|
||||
|
||||
%{
|
||||
TParseContext* context = yyextra;
|
||||
%}
|
||||
"invariant" { return INVARIANT; }
|
||||
"highp" { return HIGH_PRECISION; }
|
||||
"mediump" { return MEDIUM_PRECISION; }
|
||||
"lowp" { return LOW_PRECISION; }
|
||||
"precision" { return PRECISION; }
|
||||
|
||||
/* Single-line comments */
|
||||
"//"[^\n]* ;
|
||||
"attribute" { return ATTRIBUTE; }
|
||||
"const" { return CONST_QUAL; }
|
||||
"uniform" { return UNIFORM; }
|
||||
"varying" { return VARYING; }
|
||||
|
||||
/* Multi-line comments */
|
||||
"/*" { yy_push_state(COMMENT, yyscanner); }
|
||||
<COMMENT>. |
|
||||
<COMMENT>\n ;
|
||||
<COMMENT>"*/" { yy_pop_state(yyscanner); }
|
||||
"break" { return BREAK; }
|
||||
"continue" { return CONTINUE; }
|
||||
"do" { return DO; }
|
||||
"for" { return FOR; }
|
||||
"while" { return WHILE; }
|
||||
|
||||
"invariant" { return(INVARIANT); }
|
||||
"highp" { return(HIGH_PRECISION); }
|
||||
"mediump" { return(MEDIUM_PRECISION); }
|
||||
"lowp" { return(LOW_PRECISION); }
|
||||
"precision" { return(PRECISION); }
|
||||
"if" { return IF; }
|
||||
"else" { return ELSE; }
|
||||
|
||||
"attribute" { return(ATTRIBUTE); }
|
||||
"const" { return(CONST_QUAL); }
|
||||
"uniform" { return(UNIFORM); }
|
||||
"varying" { return(VARYING); }
|
||||
"in" { return IN_QUAL; }
|
||||
"out" { return OUT_QUAL; }
|
||||
"inout" { return INOUT_QUAL; }
|
||||
|
||||
"break" { return(BREAK); }
|
||||
"continue" { return(CONTINUE); }
|
||||
"do" { return(DO); }
|
||||
"for" { return(FOR); }
|
||||
"while" { return(WHILE); }
|
||||
"float" { return FLOAT_TYPE; }
|
||||
"int" { return INT_TYPE; }
|
||||
"void" { return VOID_TYPE; }
|
||||
"bool" { return BOOL_TYPE; }
|
||||
"true" { yylval->lex.b = true; return BOOLCONSTANT; }
|
||||
"false" { yylval->lex.b = false; return BOOLCONSTANT; }
|
||||
|
||||
"if" { return(IF); }
|
||||
"else" { return(ELSE); }
|
||||
"discard" { return DISCARD; }
|
||||
"return" { return RETURN; }
|
||||
|
||||
"in" { return(IN_QUAL); }
|
||||
"out" { return(OUT_QUAL); }
|
||||
"inout" { return(INOUT_QUAL); }
|
||||
"mat2" { return MATRIX2; }
|
||||
"mat3" { return MATRIX3; }
|
||||
"mat4" { return MATRIX4; }
|
||||
|
||||
"float" { context->lexAfterType = true; return(FLOAT_TYPE); }
|
||||
"int" { context->lexAfterType = true; return(INT_TYPE); }
|
||||
"void" { context->lexAfterType = true; return(VOID_TYPE); }
|
||||
"bool" { context->lexAfterType = true; return(BOOL_TYPE); }
|
||||
"true" { yylval->lex.b = true; return(BOOLCONSTANT); }
|
||||
"false" { yylval->lex.b = false; return(BOOLCONSTANT); }
|
||||
"vec2" { return VEC2; }
|
||||
"vec3" { return VEC3; }
|
||||
"vec4" { return VEC4; }
|
||||
"ivec2" { return IVEC2; }
|
||||
"ivec3" { return IVEC3; }
|
||||
"ivec4" { return IVEC4; }
|
||||
"bvec2" { return BVEC2; }
|
||||
"bvec3" { return BVEC3; }
|
||||
"bvec4" { return BVEC4; }
|
||||
|
||||
"discard" { return(DISCARD); }
|
||||
"return" { return(RETURN); }
|
||||
"sampler2D" { return SAMPLER2D; }
|
||||
"samplerCube" { return SAMPLERCUBE; }
|
||||
"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; }
|
||||
"sampler2DRect" { return SAMPLER2DRECT; }
|
||||
|
||||
"mat2" { context->lexAfterType = true; return(MATRIX2); }
|
||||
"mat3" { context->lexAfterType = true; return(MATRIX3); }
|
||||
"mat4" { context->lexAfterType = true; return(MATRIX4); }
|
||||
|
||||
"vec2" { context->lexAfterType = true; return (VEC2); }
|
||||
"vec3" { context->lexAfterType = true; return (VEC3); }
|
||||
"vec4" { context->lexAfterType = true; return (VEC4); }
|
||||
"ivec2" { context->lexAfterType = true; return (IVEC2); }
|
||||
"ivec3" { context->lexAfterType = true; return (IVEC3); }
|
||||
"ivec4" { context->lexAfterType = true; return (IVEC4); }
|
||||
"bvec2" { context->lexAfterType = true; return (BVEC2); }
|
||||
"bvec3" { context->lexAfterType = true; return (BVEC3); }
|
||||
"bvec4" { context->lexAfterType = true; return (BVEC4); }
|
||||
|
||||
"sampler2D" { context->lexAfterType = true; return SAMPLER2D; }
|
||||
"samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; }
|
||||
"samplerExternalOES" { context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; }
|
||||
"sampler2DRect" { context->lexAfterType = true; return SAMPLER2DRECT; }
|
||||
|
||||
"struct" { context->lexAfterType = true; return(STRUCT); }
|
||||
"struct" { return STRUCT; }
|
||||
|
||||
"asm" { return reserved_word(yyscanner); }
|
||||
|
||||
|
|
@ -183,13 +173,11 @@ O [0-7]
|
|||
"fvec3" { return reserved_word(yyscanner); }
|
||||
"fvec4" { return reserved_word(yyscanner); }
|
||||
|
||||
"sampler1D" { return reserved_word(yyscanner); }
|
||||
"sampler3D" { return reserved_word(yyscanner); }
|
||||
|
||||
"sampler1DShadow" { return reserved_word(yyscanner); }
|
||||
"sampler2DShadow" { return reserved_word(yyscanner); }
|
||||
|
||||
"sampler3DRect" { return reserved_word(yyscanner); }
|
||||
"sampler1D" { return reserved_word(yyscanner); }
|
||||
"sampler3D" { return reserved_word(yyscanner); }
|
||||
"sampler1DShadow" { return reserved_word(yyscanner); }
|
||||
"sampler2DShadow" { return reserved_word(yyscanner); }
|
||||
"sampler3DRect" { return reserved_word(yyscanner); }
|
||||
"sampler2DRectShadow" { return reserved_word(yyscanner); }
|
||||
|
||||
"sizeof" { return reserved_word(yyscanner); }
|
||||
|
|
@ -203,72 +191,64 @@ O [0-7]
|
|||
return check_type(yyscanner);
|
||||
}
|
||||
|
||||
0[xX]{H}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); }
|
||||
0{O}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); }
|
||||
0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;}
|
||||
{D}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return(INTCONSTANT); }
|
||||
0[xX]{H}+ { return int_constant(yyscanner); }
|
||||
0{O}+ { return int_constant(yyscanner); }
|
||||
{D}+ { return int_constant(yyscanner); }
|
||||
|
||||
{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
|
||||
{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
|
||||
"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); }
|
||||
{D}+{E} { return float_constant(yyscanner); }
|
||||
{D}+"."{D}*({E})? { return float_constant(yyscanner); }
|
||||
"."{D}+({E})? { return float_constant(yyscanner); }
|
||||
|
||||
"+=" { return(ADD_ASSIGN); }
|
||||
"-=" { return(SUB_ASSIGN); }
|
||||
"*=" { return(MUL_ASSIGN); }
|
||||
"/=" { return(DIV_ASSIGN); }
|
||||
"%=" { return(MOD_ASSIGN); }
|
||||
"<<=" { return(LEFT_ASSIGN); }
|
||||
">>=" { return(RIGHT_ASSIGN); }
|
||||
"&=" { return(AND_ASSIGN); }
|
||||
"^=" { return(XOR_ASSIGN); }
|
||||
"|=" { return(OR_ASSIGN); }
|
||||
"+=" { return ADD_ASSIGN; }
|
||||
"-=" { return SUB_ASSIGN; }
|
||||
"*=" { return MUL_ASSIGN; }
|
||||
"/=" { return DIV_ASSIGN; }
|
||||
"%=" { return MOD_ASSIGN; }
|
||||
"<<=" { return LEFT_ASSIGN; }
|
||||
">>=" { return RIGHT_ASSIGN; }
|
||||
"&=" { return AND_ASSIGN; }
|
||||
"^=" { return XOR_ASSIGN; }
|
||||
"|=" { return OR_ASSIGN; }
|
||||
|
||||
"++" { return(INC_OP); }
|
||||
"--" { return(DEC_OP); }
|
||||
"&&" { return(AND_OP); }
|
||||
"||" { return(OR_OP); }
|
||||
"^^" { return(XOR_OP); }
|
||||
"<=" { return(LE_OP); }
|
||||
">=" { return(GE_OP); }
|
||||
"==" { return(EQ_OP); }
|
||||
"!=" { return(NE_OP); }
|
||||
"<<" { return(LEFT_OP); }
|
||||
">>" { return(RIGHT_OP); }
|
||||
";" { context->lexAfterType = false; return(SEMICOLON); }
|
||||
("{"|"<%") { context->lexAfterType = false; return(LEFT_BRACE); }
|
||||
("}"|"%>") { return(RIGHT_BRACE); }
|
||||
"," { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); }
|
||||
":" { return(COLON); }
|
||||
"=" { context->lexAfterType = false; return(EQUAL); }
|
||||
"(" { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); }
|
||||
")" { context->inTypeParen = false; return(RIGHT_PAREN); }
|
||||
("["|"<:") { return(LEFT_BRACKET); }
|
||||
("]"|":>") { return(RIGHT_BRACKET); }
|
||||
"." { BEGIN(FIELDS); return(DOT); }
|
||||
"!" { return(BANG); }
|
||||
"-" { return(DASH); }
|
||||
"~" { return(TILDE); }
|
||||
"+" { return(PLUS); }
|
||||
"*" { return(STAR); }
|
||||
"/" { return(SLASH); }
|
||||
"%" { return(PERCENT); }
|
||||
"<" { return(LEFT_ANGLE); }
|
||||
">" { return(RIGHT_ANGLE); }
|
||||
"|" { return(VERTICAL_BAR); }
|
||||
"^" { return(CARET); }
|
||||
"&" { return(AMPERSAND); }
|
||||
"?" { return(QUESTION); }
|
||||
"++" { return INC_OP; }
|
||||
"--" { return DEC_OP; }
|
||||
"&&" { return AND_OP; }
|
||||
"||" { return OR_OP; }
|
||||
"^^" { return XOR_OP; }
|
||||
"<=" { return LE_OP; }
|
||||
">=" { return GE_OP; }
|
||||
"==" { return EQ_OP; }
|
||||
"!=" { return NE_OP; }
|
||||
"<<" { return LEFT_OP; }
|
||||
">>" { return RIGHT_OP; }
|
||||
";" { return SEMICOLON; }
|
||||
("{"|"<%") { return LEFT_BRACE; }
|
||||
("}"|"%>") { return RIGHT_BRACE; }
|
||||
"," { return COMMA; }
|
||||
":" { return COLON; }
|
||||
"=" { return EQUAL; }
|
||||
"(" { return LEFT_PAREN; }
|
||||
")" { return RIGHT_PAREN; }
|
||||
("["|"<:") { return LEFT_BRACKET; }
|
||||
("]"|":>") { return RIGHT_BRACKET; }
|
||||
"." { return DOT; }
|
||||
"!" { return BANG; }
|
||||
"-" { return DASH; }
|
||||
"~" { return TILDE; }
|
||||
"+" { return PLUS; }
|
||||
"*" { return STAR; }
|
||||
"/" { return SLASH; }
|
||||
"%" { return PERCENT; }
|
||||
"<" { return LEFT_ANGLE; }
|
||||
">" { return RIGHT_ANGLE; }
|
||||
"|" { return VERTICAL_BAR; }
|
||||
"^" { return CARET; }
|
||||
"&" { return AMPERSAND; }
|
||||
"?" { return QUESTION; }
|
||||
|
||||
<FIELDS>{L}({L}|{D})* {
|
||||
BEGIN(INITIAL);
|
||||
yylval->lex.string = NewPoolTString(yytext);
|
||||
return FIELD_SELECTION;
|
||||
}
|
||||
<FIELDS>[ \t\v\f\r] {}
|
||||
|
||||
[ \t\v\n\f\r] { }
|
||||
<*><<EOF>> { context->AfterEOF = true; yyterminate(); }
|
||||
<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; }
|
||||
[ \t\v\n\f\r] { }
|
||||
<<EOF>> { yyterminate(); }
|
||||
. { assert(false); return 0; }
|
||||
|
||||
%%
|
||||
|
||||
|
|
@ -278,7 +258,8 @@ yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
|
|||
yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
|
||||
if (len < max_size)
|
||||
memcpy(buf, token.text.c_str(), len);
|
||||
yyset_lineno(EncodeSourceLoc(token.location.file, token.location.line), yyscanner);
|
||||
yyset_column(token.location.file, yyscanner);
|
||||
yyset_lineno(token.location.line, yyscanner);
|
||||
|
||||
if (len >= max_size)
|
||||
YY_FATAL_ERROR("Input buffer overflow");
|
||||
|
|
@ -292,12 +273,10 @@ int check_type(yyscan_t yyscanner) {
|
|||
|
||||
int token = IDENTIFIER;
|
||||
TSymbol* symbol = yyextra->symbolTable.find(yytext);
|
||||
if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) {
|
||||
if (symbol && symbol->isVariable()) {
|
||||
TVariable* variable = static_cast<TVariable*>(symbol);
|
||||
if (variable->isUserType()) {
|
||||
yyextra->lexAfterType = true;
|
||||
if (variable->isUserType())
|
||||
token = TYPE_NAME;
|
||||
}
|
||||
}
|
||||
yylval->lex.symbol = symbol;
|
||||
return token;
|
||||
|
|
@ -306,22 +285,32 @@ int check_type(yyscan_t yyscanner) {
|
|||
int reserved_word(yyscan_t yyscanner) {
|
||||
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
|
||||
|
||||
yyextra->error(yylineno, "Illegal use of reserved word", yytext, "");
|
||||
yyextra->error(*yylloc, "Illegal use of reserved word", yytext, "");
|
||||
yyextra->recover();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void yyerror(TParseContext* context, const char* reason) {
|
||||
struct yyguts_t* yyg = (struct yyguts_t*) context->scanner;
|
||||
|
||||
if (context->AfterEOF) {
|
||||
context->error(yylineno, reason, "unexpected EOF");
|
||||
} else {
|
||||
context->error(yylineno, reason, yytext);
|
||||
}
|
||||
void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
|
||||
context->error(*lloc, reason, yyget_text(context->scanner));
|
||||
context->recover();
|
||||
}
|
||||
|
||||
int int_constant(yyscan_t yyscanner) {
|
||||
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
|
||||
|
||||
if (!atoi_clamp(yytext, &(yylval->lex.i)))
|
||||
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
|
||||
return INTCONSTANT;
|
||||
}
|
||||
|
||||
int float_constant(yyscan_t yyscanner) {
|
||||
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
|
||||
|
||||
if (!atof_clamp(yytext, &(yylval->lex.f)))
|
||||
yyextra->warning(*yylloc, "Float overflow", yytext, "");
|
||||
return FLOATCONSTANT;
|
||||
}
|
||||
|
||||
int glslang_initialize(TParseContext* context) {
|
||||
yyscan_t scanner = NULL;
|
||||
if (yylex_init_extra(context, &scanner))
|
||||
|
|
@ -344,12 +333,13 @@ int glslang_finalize(TParseContext* context) {
|
|||
int glslang_scan(size_t count, const char* const string[], const int length[],
|
||||
TParseContext* context) {
|
||||
yyrestart(NULL, context->scanner);
|
||||
yyset_lineno(EncodeSourceLoc(0, 1), context->scanner);
|
||||
context->AfterEOF = false;
|
||||
yyset_column(0, context->scanner);
|
||||
yyset_lineno(1, context->scanner);
|
||||
|
||||
// Initialize preprocessor.
|
||||
if (!context->preprocessor.init(count, string, length))
|
||||
return 1;
|
||||
context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH);
|
||||
|
||||
// Define extension macros.
|
||||
const TExtensionBehavior& extBehavior = context->extensionBehavior();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -189,7 +189,9 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
|
|||
case EOpAny: out << "any"; break;
|
||||
case EOpAll: out << "all"; break;
|
||||
|
||||
default: out.message(EPrefixError, "Bad unary op");
|
||||
default:
|
||||
out.prefix(EPrefixError);
|
||||
out << "Bad unary op";
|
||||
}
|
||||
|
||||
out << " (" << node->getCompleteString() << ")";
|
||||
|
|
@ -204,7 +206,8 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
|
|||
TInfoSinkBase& out = sink;
|
||||
|
||||
if (node->getOp() == EOpNull) {
|
||||
out.message(EPrefixError, "node is still EOpNull!");
|
||||
out.prefix(EPrefixError);
|
||||
out << "node is still EOpNull!";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -263,7 +266,9 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
|
|||
|
||||
case EOpDeclaration: out << "Declaration: "; break;
|
||||
|
||||
default: out.message(EPrefixError, "Bad aggregation op");
|
||||
default:
|
||||
out.prefix(EPrefixError);
|
||||
out << "Bad aggregation op";
|
||||
}
|
||||
|
||||
if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
|
||||
|
|
@ -311,9 +316,9 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
|||
{
|
||||
TInfoSinkBase& out = sink;
|
||||
|
||||
int size = node->getType().getObjectSize();
|
||||
size_t size = node->getType().getObjectSize();
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
OutputTreeText(out, node, depth);
|
||||
switch (node->getUnionArrayPointer()[i].getType()) {
|
||||
case EbtBool:
|
||||
|
|
@ -334,7 +339,7 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
|||
out << " (const int)\n";
|
||||
break;
|
||||
default:
|
||||
out.message(EPrefixInternalError, "Unknown constant", node->getLine());
|
||||
out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "GLSLANG/ShaderLang.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "compiler/Common.h"
|
||||
#include "compiler/Types.h"
|
||||
#include "compiler/ConstantUnion.h"
|
||||
|
|
@ -204,12 +205,17 @@ class TInfoSink;
|
|||
//
|
||||
class TIntermNode {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
TIntermNode() {
|
||||
// TODO: Move this to TSourceLoc constructor
|
||||
// after getting rid of TPublicType.
|
||||
line.first_file = line.last_file = 0;
|
||||
line.first_line = line.last_line = 0;
|
||||
}
|
||||
virtual ~TIntermNode() { }
|
||||
|
||||
TIntermNode() : line(0) {}
|
||||
|
||||
TSourceLoc getLine() const { return line; }
|
||||
void setLine(TSourceLoc l) { line = l; }
|
||||
const TSourceLoc& getLine() const { return line; }
|
||||
void setLine(const TSourceLoc& l) { line = l; }
|
||||
|
||||
virtual void traverse(TIntermTraverser*) = 0;
|
||||
virtual TIntermTyped* getAsTyped() { return 0; }
|
||||
|
|
@ -220,7 +226,6 @@ public:
|
|||
virtual TIntermSelection* getAsSelectionNode() { return 0; }
|
||||
virtual TIntermSymbol* getAsSymbolNode() { return 0; }
|
||||
virtual TIntermLoop* getAsLoopNode() { return 0; }
|
||||
virtual ~TIntermNode() { }
|
||||
|
||||
protected:
|
||||
TSourceLoc line;
|
||||
|
|
@ -454,7 +459,7 @@ typedef TVector<int> TQualifierList;
|
|||
//
|
||||
class TIntermAggregate : public TIntermOperator {
|
||||
public:
|
||||
TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), endLine(0), useEmulatedFunction(false) { }
|
||||
TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
|
||||
TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
|
||||
~TIntermAggregate() { }
|
||||
|
||||
|
|
@ -474,9 +479,6 @@ public:
|
|||
void setDebug(bool d) { debug = d; }
|
||||
bool getDebug() { return debug; }
|
||||
|
||||
void setEndLine(TSourceLoc line) { endLine = line; }
|
||||
TSourceLoc getEndLine() const { return endLine; }
|
||||
|
||||
void setUseEmulatedFunction() { useEmulatedFunction = true; }
|
||||
bool getUseEmulatedFunction() { return useEmulatedFunction; }
|
||||
|
||||
|
|
@ -489,7 +491,6 @@ protected:
|
|||
|
||||
bool optimize;
|
||||
bool debug;
|
||||
TSourceLoc endLine;
|
||||
|
||||
// If set to true, replace the built-in function call with an emulated one
|
||||
// to work around driver bugs.
|
||||
|
|
@ -538,14 +539,14 @@ enum Visit
|
|||
class TIntermTraverser
|
||||
{
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
|
||||
preVisit(preVisit),
|
||||
inVisit(inVisit),
|
||||
postVisit(postVisit),
|
||||
rightToLeft(rightToLeft),
|
||||
depth(0) {}
|
||||
depth(0),
|
||||
maxDepth(0) {}
|
||||
virtual ~TIntermTraverser() {};
|
||||
|
||||
virtual void visitSymbol(TIntermSymbol*) {}
|
||||
|
|
@ -557,7 +558,8 @@ public:
|
|||
virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
|
||||
virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
|
||||
|
||||
void incrementDepth() {depth++;}
|
||||
int getMaxDepth() const {return maxDepth;}
|
||||
void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); }
|
||||
void decrementDepth() {depth--;}
|
||||
|
||||
// Return the original name if hash function pointer is NULL;
|
||||
|
|
@ -571,6 +573,7 @@ public:
|
|||
|
||||
protected:
|
||||
int depth;
|
||||
int maxDepth;
|
||||
};
|
||||
|
||||
#endif // __INTERMEDIATE_H
|
||||
|
|
|
|||
|
|
@ -22,37 +22,36 @@ struct TVectorFields {
|
|||
class TInfoSink;
|
||||
class TIntermediate {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||
|
||||
POOL_ALLOCATOR_NEW_DELETE();
|
||||
TIntermediate(TInfoSink& i) : infoSink(i) { }
|
||||
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
|
||||
|
||||
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&);
|
||||
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
|
||||
TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
|
||||
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
|
||||
TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
|
||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
|
||||
TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
|
||||
TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
|
||||
TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
|
||||
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
|
||||
TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||
TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, TSourceLoc);
|
||||
TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&);
|
||||
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
|
||||
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
|
||||
TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&);
|
||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
|
||||
TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
|
||||
TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&);
|
||||
TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
|
||||
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
|
||||
TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
|
||||
TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&);
|
||||
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
|
||||
bool parseConstTree(TSourceLoc, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);
|
||||
TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, TSourceLoc);
|
||||
TIntermBranch* addBranch(TOperator, TSourceLoc);
|
||||
TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
|
||||
TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
|
||||
bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);
|
||||
TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&);
|
||||
TIntermBranch* addBranch(TOperator, const TSourceLoc&);
|
||||
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
|
||||
TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&);
|
||||
bool postProcess(TIntermNode*);
|
||||
void remove(TIntermNode*);
|
||||
void remove(TIntermNode*);
|
||||
void outputTree(TIntermNode*);
|
||||
|
||||
protected:
|
||||
TInfoSink& infoSink;
|
||||
|
||||
private:
|
||||
void operator=(TIntermediate&); // prevent assignments
|
||||
|
||||
TInfoSink& infoSink;
|
||||
};
|
||||
|
||||
#endif // _LOCAL_INTERMEDIATE_INCLUDED_
|
||||
|
|
|
|||
|
|
@ -38,16 +38,16 @@ protected:
|
|||
bool visitLoop(Visit visit, TIntermLoop*);
|
||||
bool visitBranch(Visit visit, TIntermBranch*);
|
||||
|
||||
int index;
|
||||
size_t index;
|
||||
ConstantUnion *unionArray;
|
||||
TType type;
|
||||
TOperator constructorType;
|
||||
bool singleConstantParam;
|
||||
TInfoSink& infoSink;
|
||||
TSymbolTable& symbolTable;
|
||||
int size; // size of the constructor ( 4 for vec4)
|
||||
size_t size; // size of the constructor ( 4 for vec4)
|
||||
bool isMatrix;
|
||||
int matrixSize; // dimension of the matrix (nominal size and not the instance size)
|
||||
size_t matrixSize; // dimension of the matrix (nominal size and not the instance size)
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -61,7 +61,7 @@ protected:
|
|||
|
||||
void TConstTraverser::visitSymbol(TIntermSymbol* node)
|
||||
{
|
||||
infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor");
|
||||
return;
|
||||
|
||||
}
|
||||
|
|
@ -74,12 +74,12 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
|
|||
TString buf;
|
||||
buf.append("'constructor' : assigning non-constant to ");
|
||||
buf.append(type.getCompleteString());
|
||||
infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
|
||||
infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
|
|||
TString buf;
|
||||
buf.append("'constructor' : assigning non-constant to ");
|
||||
buf.append(type.getCompleteString());
|
||||
infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
|
||||
infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -100,7 +100,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
|
|||
TString buf;
|
||||
buf.append("'constructor' : assigning non-constant to ");
|
||||
buf.append(type.getCompleteString());
|
||||
infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
|
||||
infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -144,7 +144,7 @@ bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
|
|||
|
||||
bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
|
||||
{
|
||||
infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -159,16 +159,16 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
|||
}
|
||||
|
||||
ConstantUnion* leftUnionArray = unionArray;
|
||||
int instanceSize = type.getObjectSize();
|
||||
size_t instanceSize = type.getObjectSize();
|
||||
|
||||
if (index >= instanceSize)
|
||||
return;
|
||||
|
||||
if (!singleConstantParam) {
|
||||
int size = node->getType().getObjectSize();
|
||||
size_t size = node->getType().getObjectSize();
|
||||
|
||||
ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
|
||||
for (int i=0; i < size; i++) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (index >= instanceSize)
|
||||
return;
|
||||
leftUnionArray[index] = rightUnionArray[i];
|
||||
|
|
@ -176,11 +176,11 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
|||
(index)++;
|
||||
}
|
||||
} else {
|
||||
int totalSize = index + size;
|
||||
size_t totalSize = index + size;
|
||||
ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
|
||||
if (!isMatrix) {
|
||||
int count = 0;
|
||||
for (int i = index; i < totalSize; i++) {
|
||||
size_t count = 0;
|
||||
for (size_t i = index; i < totalSize; i++) {
|
||||
if (i >= instanceSize)
|
||||
return;
|
||||
|
||||
|
|
@ -192,9 +192,9 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
|||
count++;
|
||||
}
|
||||
} else { // for matrix constructors
|
||||
int count = 0;
|
||||
int element = index;
|
||||
for (int i = index; i < totalSize; i++) {
|
||||
size_t count = 0;
|
||||
size_t element = index;
|
||||
for (size_t i = index; i < totalSize; i++) {
|
||||
if (i >= instanceSize)
|
||||
return;
|
||||
if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
|
||||
|
|
@ -213,14 +213,14 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
|||
|
||||
bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
|
||||
{
|
||||
infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
|
||||
{
|
||||
infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
|
||||
infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
|
||||
error = true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -230,7 +230,7 @@ bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
|
|||
// Individual functions can be initialized to 0 to skip processing of that
|
||||
// type of node. It's children will still be processed.
|
||||
//
|
||||
bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
|
||||
bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
|
||||
{
|
||||
if (root == 0)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ void Preprocessor::predefineMacro(const char* name, int value)
|
|||
mImpl->macroSet[name] = macro;
|
||||
}
|
||||
|
||||
void Preprocessor::setMaxTokenLength(size_t maxLength)
|
||||
{
|
||||
mImpl->tokenizer.setMaxTokenLength(maxLength);
|
||||
}
|
||||
|
||||
void Preprocessor::lex(Token* token)
|
||||
{
|
||||
bool validToken = false;
|
||||
|
|
@ -95,34 +100,6 @@ void Preprocessor::lex(Token* token)
|
|||
case Token::PP_HASH:
|
||||
assert(false);
|
||||
break;
|
||||
case Token::CONST_INT:
|
||||
{
|
||||
int val = 0;
|
||||
if (!token->iValue(&val))
|
||||
{
|
||||
// Do not mark the token as invalid.
|
||||
// Just emit the diagnostic and reset value to 0.
|
||||
mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
|
||||
token->location, token->text);
|
||||
token->text.assign("0");
|
||||
}
|
||||
validToken = true;
|
||||
break;
|
||||
}
|
||||
case Token::CONST_FLOAT:
|
||||
{
|
||||
float val = 0;
|
||||
if (!token->fValue(&val))
|
||||
{
|
||||
// Do not mark the token as invalid.
|
||||
// Just emit the diagnostic and reset value to 0.0.
|
||||
mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
|
||||
token->location, token->text);
|
||||
token->text.assign("0.0");
|
||||
}
|
||||
validToken = true;
|
||||
break;
|
||||
}
|
||||
case Token::PP_NUMBER:
|
||||
mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
|
||||
token->location, token->text);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@ class Preprocessor
|
|||
bool init(size_t count, const char* const string[], const int length[]);
|
||||
// Adds a pre-defined macro.
|
||||
void predefineMacro(const char* name, int value);
|
||||
// Sets maximum allowed token length.
|
||||
// If token length exceeds this limit,
|
||||
// the token text will be truncated to the given maximum length, and
|
||||
// TOKEN_TOO_LONG diagnostic will be generated.
|
||||
// The maximum length defaults to 256.
|
||||
void setMaxTokenLength(size_t maxLength);
|
||||
|
||||
void lex(Token* token);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ class Tokenizer : public Lexer
|
|||
bool leadingSpace;
|
||||
bool lineStart;
|
||||
};
|
||||
static const std::size_t kMaxTokenLength;
|
||||
|
||||
Tokenizer(Diagnostics* diagnostics);
|
||||
~Tokenizer();
|
||||
|
||||
bool init(size_t count, const char* const string[], const int length[]);
|
||||
|
||||
void setMaxTokenLength(size_t maxLength) { mMaxTokenLength = maxLength; }
|
||||
void setFileNumber(int file);
|
||||
void setLineNumber(int line);
|
||||
|
||||
|
|
@ -51,6 +51,7 @@ class Tokenizer : public Lexer
|
|||
|
||||
void* mHandle; // Scanner handle.
|
||||
Context mContext; // Scanner extra.
|
||||
size_t mMaxTokenLength;
|
||||
};
|
||||
|
||||
} // namespace pp
|
||||
|
|
|
|||
|
|
@ -267,11 +267,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
|
|||
|
||||
namespace pp {
|
||||
|
||||
// TODO(alokp): Maximum token length should ideally be specified by
|
||||
// the preprocessor client, i.e., the compiler.
|
||||
const size_t Tokenizer::kMaxTokenLength = 256;
|
||||
|
||||
Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
|
||||
Tokenizer::Tokenizer(Diagnostics* diagnostics)
|
||||
: mHandle(0),
|
||||
mMaxTokenLength(256)
|
||||
{
|
||||
mContext.diagnostics = diagnostics;
|
||||
}
|
||||
|
|
@ -304,11 +302,11 @@ void Tokenizer::setLineNumber(int line)
|
|||
void Tokenizer::lex(Token* token)
|
||||
{
|
||||
token->type = yylex(&token->text, &token->location, mHandle);
|
||||
if (token->text.size() > kMaxTokenLength)
|
||||
if (token->text.size() > mMaxTokenLength)
|
||||
{
|
||||
mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
|
||||
token->location, token->text);
|
||||
token->text.erase(kMaxTokenLength);
|
||||
token->text.erase(mMaxTokenLength);
|
||||
}
|
||||
|
||||
token->flags = 0;
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node)
|
|||
{
|
||||
if (IsSampler(node->getBasicType())) {
|
||||
++mNumErrors;
|
||||
mSink.prefix(EPrefixError);
|
||||
mSink.location(node->getLine());
|
||||
mSink << "Samplers are not permitted in vertex shaders.\n";
|
||||
mSink.message(EPrefixError,
|
||||
node->getLine(),
|
||||
"Samplers are not permitted in vertex shaders");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,30 +4,25 @@
|
|||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "compiler/util.h"
|
||||
|
||||
#include "util.h"
|
||||
#include <limits>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <locale.h>
|
||||
#else
|
||||
#include <sstream>
|
||||
#endif
|
||||
#include "compiler/preprocessor/numeric_lex.h"
|
||||
|
||||
double atof_dot(const char *str)
|
||||
bool atof_clamp(const char *str, float *value)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
_locale_t l = _create_locale(LC_NUMERIC, "C");
|
||||
double result = _atof_l(str, l);
|
||||
_free_locale(l);
|
||||
return result;
|
||||
#else
|
||||
double result;
|
||||
std::istringstream s(str);
|
||||
std::locale l("C");
|
||||
s.imbue(l);
|
||||
s >> result;
|
||||
return result;
|
||||
#endif
|
||||
bool success = pp::numeric_lex_float(str, value);
|
||||
if (!success)
|
||||
*value = std::numeric_limits<float>::max();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool atoi_clamp(const char *str, int *value)
|
||||
{
|
||||
bool success = pp::numeric_lex_int(str, value);
|
||||
if (!success)
|
||||
*value = std::numeric_limits<int>::max();
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,15 +7,14 @@
|
|||
#ifndef COMPILER_UTIL_H
|
||||
#define COMPILER_UTIL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// atof_clamp is like atof but
|
||||
// 1. it forces C locale, i.e. forcing '.' as decimal point.
|
||||
// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens.
|
||||
// Return false if overflow happens.
|
||||
extern bool atof_clamp(const char *str, float *value);
|
||||
|
||||
// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point.
|
||||
double atof_dot(const char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end extern "C"
|
||||
#endif
|
||||
// If overflow happens, clamp the value to INT_MIN or INT_MAX.
|
||||
// Return false if overflow happens.
|
||||
extern bool atoi_clamp(const char *str, int *value);
|
||||
|
||||
#endif // COMPILER_UTIL_H
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
|
@ -38,31 +38,16 @@ egl::Display *Display::getDisplay(EGLNativeDisplayType displayId)
|
|||
return displays[displayId];
|
||||
}
|
||||
|
||||
egl::Display *display = NULL;
|
||||
// FIXME: Check if displayId is a valid display device context
|
||||
|
||||
if (displayId == EGL_DEFAULT_DISPLAY)
|
||||
{
|
||||
display = new egl::Display(displayId, (HDC)NULL, false);
|
||||
}
|
||||
else if (displayId == EGL_SOFTWARE_DISPLAY_ANGLE)
|
||||
{
|
||||
display = new egl::Display(displayId, (HDC)NULL, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: Check if displayId is a valid display device context
|
||||
|
||||
display = new egl::Display(displayId, (HDC)displayId, false);
|
||||
}
|
||||
egl::Display *display = new egl::Display(displayId, (HDC)displayId);
|
||||
|
||||
displays[displayId] = display;
|
||||
return display;
|
||||
}
|
||||
|
||||
Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software) : mDc(deviceContext)
|
||||
Display::Display(EGLNativeDisplayType displayId, HDC deviceContext) : mDc(deviceContext)
|
||||
{
|
||||
|
||||
mSoftwareDevice = software;
|
||||
mDisplayId = displayId;
|
||||
mRenderer = NULL;
|
||||
}
|
||||
|
|
@ -86,7 +71,7 @@ bool Display::initialize()
|
|||
return true;
|
||||
}
|
||||
|
||||
mRenderer = glCreateRenderer(this, mDc, mSoftwareDevice);
|
||||
mRenderer = glCreateRenderer(this, mDc, mDisplayId);
|
||||
|
||||
if (!mRenderer)
|
||||
{
|
||||
|
|
@ -128,6 +113,7 @@ bool Display::initialize()
|
|||
}
|
||||
|
||||
initExtensionString();
|
||||
initVendorString();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -528,5 +514,24 @@ const char *Display::getExtensionString() const
|
|||
return mExtensionString.c_str();
|
||||
}
|
||||
|
||||
void Display::initVendorString()
|
||||
{
|
||||
mVendorString = "Google Inc.";
|
||||
|
||||
LUID adapterLuid = {0};
|
||||
|
||||
if (mRenderer && mRenderer->getLUID(&adapterLuid))
|
||||
{
|
||||
char adapterLuidString[64];
|
||||
sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
|
||||
|
||||
mVendorString += adapterLuidString;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Display::getVendorString() const
|
||||
{
|
||||
return mVendorString.c_str();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
|
@ -60,11 +60,12 @@ class Display
|
|||
virtual void recreateSwapChains();
|
||||
|
||||
const char *getExtensionString() const;
|
||||
const char *getVendorString() const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Display);
|
||||
|
||||
Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software);
|
||||
Display(EGLNativeDisplayType displayId, HDC deviceContext);
|
||||
|
||||
bool restoreLostDevice();
|
||||
|
||||
|
|
@ -84,7 +85,9 @@ class Display
|
|||
rx::Renderer *mRenderer;
|
||||
|
||||
void initExtensionString();
|
||||
void initVendorString();
|
||||
std::string mExtensionString;
|
||||
std::string mVendorString;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@
|
|||
#include "libEGL/main.h"
|
||||
#include "libEGL/Display.h"
|
||||
|
||||
#include <dwmapi.h>
|
||||
|
||||
namespace egl
|
||||
{
|
||||
|
||||
|
|
@ -71,44 +69,9 @@ Surface::~Surface()
|
|||
|
||||
bool Surface::initialize()
|
||||
{
|
||||
typedef HRESULT (STDAPICALLTYPE *PtrDwmIsCompositionEnabled)(BOOL*);
|
||||
typedef HRESULT (STDAPICALLTYPE *PtrDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS *);
|
||||
|
||||
if (!resetSwapChain())
|
||||
return false;
|
||||
|
||||
// Modify present parameters for this window, if we are composited,
|
||||
// to minimize the amount of queuing done by DWM between our calls to
|
||||
// present and the actual screen.
|
||||
if (mWindow && (getComparableOSVersion() >= versionWindowsVista)) {
|
||||
// Resolve dwmapi.dll functions dynamically as the Library is
|
||||
// not present on Windows XP. Alternatively, /DELAYLOAD could be used.
|
||||
static PtrDwmIsCompositionEnabled dwmIsCompositionEnabled = 0;
|
||||
static PtrDwmSetPresentParameters dwmSetPresentParameters = 0;
|
||||
if (!dwmIsCompositionEnabled) {
|
||||
if (const HMODULE dwmLibrary = LoadLibraryW(L"dwmapi.dll")) {
|
||||
dwmIsCompositionEnabled =
|
||||
(PtrDwmIsCompositionEnabled)GetProcAddress(dwmLibrary, "DwmIsCompositionEnabled");
|
||||
dwmSetPresentParameters =
|
||||
(PtrDwmSetPresentParameters)GetProcAddress(dwmLibrary, "DwmSetPresentParameters");
|
||||
}
|
||||
}
|
||||
if (dwmIsCompositionEnabled && dwmSetPresentParameters) {
|
||||
BOOL isComposited;
|
||||
HRESULT result = dwmIsCompositionEnabled(&isComposited);
|
||||
if (SUCCEEDED(result) && isComposited) {
|
||||
DWM_PRESENT_PARAMETERS presentParams;
|
||||
memset(&presentParams, 0, sizeof(presentParams));
|
||||
presentParams.cbSize = sizeof(DWM_PRESENT_PARAMETERS);
|
||||
presentParams.cBuffer = 2;
|
||||
|
||||
result = dwmSetPresentParameters(mWindow, &presentParams);
|
||||
if (FAILED(result))
|
||||
ERR("Unable to set present parameters: 0x%08X", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -180,9 +180,9 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
|
|||
case EGL_CLIENT_APIS:
|
||||
return egl::success("OpenGL_ES");
|
||||
case EGL_EXTENSIONS:
|
||||
return display->getExtensionString();
|
||||
return egl::success(display->getExtensionString());
|
||||
case EGL_VENDOR:
|
||||
return egl::success("Google Inc.");
|
||||
return egl::success(display->getVendorString());
|
||||
case EGL_VERSION:
|
||||
return egl::success("1.4 (ANGLE " VERSION_STRING ")");
|
||||
}
|
||||
|
|
@ -888,15 +888,18 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
|
|||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
rx::Renderer *renderer = display->getRenderer();
|
||||
if (renderer->testDeviceLost(true))
|
||||
if (dpy != EGL_NO_DISPLAY)
|
||||
{
|
||||
return EGL_FALSE;
|
||||
}
|
||||
rx::Renderer *renderer = display->getRenderer();
|
||||
if (renderer->testDeviceLost(true))
|
||||
{
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (renderer->isDeviceLost())
|
||||
{
|
||||
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
|
||||
if (renderer->isDeviceLost())
|
||||
{
|
||||
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
|
||||
|
|
|
|||
|
|
@ -88,72 +88,89 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static inline egl::Current *current()
|
||||
{
|
||||
return (egl::Current*)TlsGetValue(currentTLS);
|
||||
}
|
||||
|
||||
#else // !QT_OPENGL_ES_2_ANGLE_STATIC
|
||||
|
||||
static egl::Current *current()
|
||||
{
|
||||
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
|
||||
static egl::Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE };
|
||||
return &curr;
|
||||
}
|
||||
|
||||
#endif // QT_OPENGL_ES_2_ANGLE_STATIC
|
||||
#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
|
||||
|
||||
namespace egl
|
||||
{
|
||||
Current *getCurrent()
|
||||
{
|
||||
#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
|
||||
return (Current*)TlsGetValue(currentTLS);
|
||||
#else
|
||||
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
|
||||
static Current curr = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE };
|
||||
return &curr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void setCurrentError(EGLint error)
|
||||
{
|
||||
current()->error = error;
|
||||
Current *current = getCurrent();
|
||||
|
||||
current->error = error;
|
||||
}
|
||||
|
||||
EGLint getCurrentError()
|
||||
{
|
||||
return current()->error;
|
||||
Current *current = getCurrent();
|
||||
|
||||
return current->error;
|
||||
}
|
||||
|
||||
void setCurrentAPI(EGLenum API)
|
||||
{
|
||||
current()->API = API;
|
||||
Current *current = getCurrent();
|
||||
|
||||
current->API = API;
|
||||
}
|
||||
|
||||
EGLenum getCurrentAPI()
|
||||
{
|
||||
return current()->API;
|
||||
Current *current = getCurrent();
|
||||
|
||||
return current->API;
|
||||
}
|
||||
|
||||
void setCurrentDisplay(EGLDisplay dpy)
|
||||
{
|
||||
current()->display = dpy;
|
||||
Current *current = getCurrent();
|
||||
|
||||
current->display = dpy;
|
||||
}
|
||||
|
||||
EGLDisplay getCurrentDisplay()
|
||||
{
|
||||
return current()->display;
|
||||
Current *current = getCurrent();
|
||||
|
||||
return current->display;
|
||||
}
|
||||
|
||||
void setCurrentDrawSurface(EGLSurface surface)
|
||||
{
|
||||
current()->drawSurface = surface;
|
||||
Current *current = getCurrent();
|
||||
|
||||
current->drawSurface = surface;
|
||||
}
|
||||
|
||||
EGLSurface getCurrentDrawSurface()
|
||||
{
|
||||
return current()->drawSurface;
|
||||
Current *current = getCurrent();
|
||||
|
||||
return current->drawSurface;
|
||||
}
|
||||
|
||||
void setCurrentReadSurface(EGLSurface surface)
|
||||
{
|
||||
current()->readSurface = surface;
|
||||
Current *current = getCurrent();
|
||||
|
||||
current->readSurface = surface;
|
||||
}
|
||||
|
||||
EGLSurface getCurrentReadSurface()
|
||||
{
|
||||
return current()->readSurface;
|
||||
Current *current = getCurrent();
|
||||
|
||||
return current->readSurface;
|
||||
}
|
||||
|
||||
void error(EGLint errorCode)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ Buffer::~Buffer()
|
|||
void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
|
||||
{
|
||||
mBufferStorage->clear();
|
||||
mIndexRangeCache.clear();
|
||||
mBufferStorage->setData(data, size, 0);
|
||||
|
||||
mUsage = usage;
|
||||
|
|
@ -56,6 +57,7 @@ void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
|
|||
void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
|
||||
{
|
||||
mBufferStorage->setData(data, size, offset);
|
||||
mIndexRangeCache.invalidateRange(offset, size);
|
||||
|
||||
if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
|
||||
{
|
||||
|
|
@ -70,7 +72,7 @@ rx::BufferStorage *Buffer::getStorage() const
|
|||
return mBufferStorage;
|
||||
}
|
||||
|
||||
unsigned int Buffer::size()
|
||||
unsigned int Buffer::size() const
|
||||
{
|
||||
return mBufferStorage->getSize();
|
||||
}
|
||||
|
|
@ -116,4 +118,9 @@ void Buffer::promoteStaticUsage(int dataSize)
|
|||
}
|
||||
}
|
||||
|
||||
rx::IndexRangeCache *Buffer::getIndexRangeCache()
|
||||
{
|
||||
return &mIndexRangeCache;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "common/angleutils.h"
|
||||
#include "common/RefCountObject.h"
|
||||
#include "libGLESv2/renderer/IndexRangeCache.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
|
@ -38,13 +39,15 @@ class Buffer : public RefCountObject
|
|||
GLenum usage() const;
|
||||
|
||||
rx::BufferStorage *getStorage() const;
|
||||
unsigned int size();
|
||||
unsigned int size() const;
|
||||
|
||||
rx::StaticVertexBufferInterface *getStaticVertexBuffer();
|
||||
rx::StaticIndexBufferInterface *getStaticIndexBuffer();
|
||||
void invalidateStaticData();
|
||||
void promoteStaticUsage(int dataSize);
|
||||
|
||||
rx::IndexRangeCache *getIndexRangeCache();
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Buffer);
|
||||
|
||||
|
|
@ -53,6 +56,8 @@ class Buffer : public RefCountObject
|
|||
|
||||
rx::BufferStorage *mBufferStorage;
|
||||
|
||||
rx::IndexRangeCache mIndexRangeCache;
|
||||
|
||||
rx::StaticVertexBufferInterface *mStaticVertexBuffer;
|
||||
rx::StaticIndexBufferInterface *mStaticIndexBuffer;
|
||||
unsigned int mUnmodifiedDataUse;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n
|
|||
mState.rasterizer.polygonOffsetFactor = 0.0f;
|
||||
mState.rasterizer.polygonOffsetUnits = 0.0f;
|
||||
mState.rasterizer.pointDrawMode = false;
|
||||
mState.rasterizer.multiSample = false;
|
||||
mState.scissorTest = false;
|
||||
mState.scissor.x = 0;
|
||||
mState.scissor.y = 0;
|
||||
|
|
@ -1075,6 +1076,7 @@ void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum inter
|
|||
case GL_RGB565:
|
||||
case GL_RGB8_OES:
|
||||
case GL_RGBA8_OES:
|
||||
case GL_BGRA8_EXT:
|
||||
renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples);
|
||||
break;
|
||||
case GL_STENCIL_INDEX8:
|
||||
|
|
@ -1741,7 +1743,11 @@ bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
|
|||
// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
|
||||
void Context::applyState(GLenum drawMode)
|
||||
{
|
||||
Framebuffer *framebufferObject = getDrawFramebuffer();
|
||||
int samples = framebufferObject->getSamples();
|
||||
|
||||
mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS);
|
||||
mState.rasterizer.multiSample = (samples != 0);
|
||||
mRenderer->setRasterizerState(mState.rasterizer);
|
||||
|
||||
unsigned int mask = 0;
|
||||
|
|
@ -1749,10 +1755,10 @@ void Context::applyState(GLenum drawMode)
|
|||
{
|
||||
if (mState.sampleCoverageValue != 0)
|
||||
{
|
||||
Framebuffer *framebufferObject = getDrawFramebuffer();
|
||||
|
||||
float threshold = 0.5f;
|
||||
|
||||
for (int i = 0; i < framebufferObject->getSamples(); ++i)
|
||||
for (int i = 0; i < samples; ++i)
|
||||
{
|
||||
mask <<= 1;
|
||||
|
||||
|
|
@ -2582,6 +2588,7 @@ void Context::initExtensionString()
|
|||
}
|
||||
|
||||
extensionString += "GL_EXT_texture_storage ";
|
||||
extensionString += "GL_EXT_frag_depth ";
|
||||
|
||||
// ANGLE-specific extensions
|
||||
if (supportsDepthTextures())
|
||||
|
|
|
|||
|
|
@ -303,6 +303,19 @@ bool Framebuffer::hasStencil() const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Framebuffer::usingExtendedDrawBuffers() const
|
||||
{
|
||||
for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
|
||||
{
|
||||
if (isEnabledColorAttachment(colorAttachment))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GLenum Framebuffer::completeness() const
|
||||
{
|
||||
int width = 0;
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ class Framebuffer
|
|||
bool hasEnabledColorAttachment() const;
|
||||
bool hasStencil() const;
|
||||
int getSamples() const;
|
||||
bool usingExtendedDrawBuffers() const;
|
||||
|
||||
virtual GLenum completeness() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1165,7 +1165,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
|
|||
bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
|
||||
bool usesFragColor = fragmentShader->mUsesFragColor;
|
||||
bool usesFragData = fragmentShader->mUsesFragData;
|
||||
if (usesMRT && usesFragColor && usesFragData)
|
||||
if (usesFragColor && usesFragData)
|
||||
{
|
||||
infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader.");
|
||||
return false;
|
||||
|
|
@ -1177,6 +1177,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
|
|||
|
||||
const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0);
|
||||
|
||||
// The output color is broadcast to all enabled draw buffers when writing to gl_FragColor
|
||||
const bool broadcast = fragmentShader->mUsesFragColor;
|
||||
const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1);
|
||||
|
||||
if (registersNeeded > maxVaryingVectors)
|
||||
{
|
||||
infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord");
|
||||
|
|
@ -1221,8 +1225,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
|
|||
std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
|
||||
std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
|
||||
std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
|
||||
|
||||
const unsigned int renderTargetCount = usesMRT ? mRenderer->getMaxRenderTargets() : 1;
|
||||
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
|
||||
|
||||
// special varyings that use reserved registers
|
||||
int reservedRegisterIndex = registers;
|
||||
|
|
@ -1472,9 +1475,14 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
|
|||
"struct PS_OUTPUT\n"
|
||||
"{\n";
|
||||
|
||||
for (unsigned int i = 0; i < renderTargetCount; i++)
|
||||
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
|
||||
{
|
||||
pixelHLSL += " float4 gl_Color" + str(i) + " : " + targetSemantic + str(i) + ";\n";
|
||||
pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n";
|
||||
}
|
||||
|
||||
if (fragmentShader->mUsesFragDepth)
|
||||
{
|
||||
pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n";
|
||||
}
|
||||
|
||||
pixelHLSL += "};\n"
|
||||
|
|
@ -1583,11 +1591,16 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying
|
|||
"\n"
|
||||
" PS_OUTPUT output;\n";
|
||||
|
||||
for (unsigned int i = 0; i < renderTargetCount; i++)
|
||||
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
|
||||
{
|
||||
unsigned int sourceColor = fragmentShader->mUsesFragData ? i : 0;
|
||||
unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
|
||||
|
||||
pixelHLSL += " output.gl_Color" + str(i) + " = gl_Color[" + str(sourceColor) + "];\n";
|
||||
pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n";
|
||||
}
|
||||
|
||||
if (fragmentShader->mUsesFragDepth)
|
||||
{
|
||||
pixelHLSL += " output.gl_Depth = gl_Depth;\n";
|
||||
}
|
||||
|
||||
pixelHLSL += "\n"
|
||||
|
|
@ -1617,6 +1630,14 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
|
|||
return false;
|
||||
}
|
||||
|
||||
int compileFlags = 0;
|
||||
stream.read(&compileFlags);
|
||||
if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
|
||||
{
|
||||
infoLog.append("Mismatched compilation flags.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
|
||||
{
|
||||
stream.read(&mLinkedAttribute[i].type);
|
||||
|
|
@ -1626,6 +1647,8 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
|
|||
stream.read(&mSemanticIndex[i]);
|
||||
}
|
||||
|
||||
initAttributesByLayout();
|
||||
|
||||
for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
|
||||
{
|
||||
stream.read(&mSamplersPS[i].active);
|
||||
|
|
@ -1769,6 +1792,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
|
|||
|
||||
stream.write(GL_PROGRAM_BINARY_ANGLE);
|
||||
stream.write(VERSION_DWORD);
|
||||
stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
|
||||
|
||||
for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
|
||||
{
|
||||
|
|
@ -1917,27 +1941,6 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
|
|||
}
|
||||
|
||||
bool success = true;
|
||||
mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX);
|
||||
mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL);
|
||||
|
||||
if (usesGeometryShader())
|
||||
{
|
||||
std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
|
||||
mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY);
|
||||
}
|
||||
|
||||
if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
|
||||
{
|
||||
infoLog.append("Failed to create D3D shaders.");
|
||||
success = false;
|
||||
|
||||
delete mVertexExecutable;
|
||||
mVertexExecutable = NULL;
|
||||
delete mPixelExecutable;
|
||||
mPixelExecutable = NULL;
|
||||
delete mGeometryExecutable;
|
||||
mGeometryExecutable = NULL;
|
||||
}
|
||||
|
||||
if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
|
||||
{
|
||||
|
|
@ -1949,6 +1952,39 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
|
|||
success = false;
|
||||
}
|
||||
|
||||
// special case for gl_DepthRange, the only built-in uniform (also a struct)
|
||||
if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange)
|
||||
{
|
||||
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0));
|
||||
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0));
|
||||
mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0));
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX);
|
||||
mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL);
|
||||
|
||||
if (usesGeometryShader())
|
||||
{
|
||||
std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
|
||||
mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY);
|
||||
}
|
||||
|
||||
if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
|
||||
{
|
||||
infoLog.append("Failed to create D3D shaders.");
|
||||
success = false;
|
||||
|
||||
delete mVertexExecutable;
|
||||
mVertexExecutable = NULL;
|
||||
delete mPixelExecutable;
|
||||
mPixelExecutable = NULL;
|
||||
delete mGeometryExecutable;
|
||||
mGeometryExecutable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -2019,6 +2055,8 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at
|
|||
}
|
||||
}
|
||||
|
||||
initAttributesByLayout();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2545,12 +2583,6 @@ struct AttributeSorter
|
|||
AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
|
||||
: originalIndices(semanticIndices)
|
||||
{
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
indices[i] = i;
|
||||
}
|
||||
|
||||
std::sort(&indices[0], &indices[MAX_VERTEX_ATTRIBS], *this);
|
||||
}
|
||||
|
||||
bool operator()(int a, int b)
|
||||
|
|
@ -2558,27 +2590,32 @@ struct AttributeSorter
|
|||
return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b];
|
||||
}
|
||||
|
||||
int indices[MAX_VERTEX_ATTRIBS];
|
||||
const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
|
||||
};
|
||||
|
||||
void ProgramBinary::initAttributesByLayout()
|
||||
{
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
mAttributesByLayout[i] = i;
|
||||
}
|
||||
|
||||
std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
|
||||
}
|
||||
|
||||
void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
|
||||
{
|
||||
AttributeSorter sorter(mSemanticIndex);
|
||||
|
||||
int oldIndices[MAX_VERTEX_ATTRIBS];
|
||||
rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
oldIndices[i] = mSemanticIndex[i];
|
||||
oldTranslatedAttributes[i] = attributes[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
int oldIndex = sorter.indices[i];
|
||||
sortedSemanticIndices[i] = oldIndices[oldIndex];
|
||||
int oldIndex = mAttributesByLayout[i];
|
||||
sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
|
||||
attributes[i] = oldTranslatedAttributes[oldIndex];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ class ProgramBinary : public RefCountObject
|
|||
|
||||
unsigned int getSerial() const;
|
||||
|
||||
void initAttributesByLayout();
|
||||
void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
|
||||
|
||||
static std::string decorateAttribute(const std::string &name); // Prepend an underscore
|
||||
|
|
@ -142,6 +143,7 @@ class ProgramBinary : public RefCountObject
|
|||
|
||||
Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
|
||||
int mSemanticIndex[MAX_VERTEX_ATTRIBS];
|
||||
int mAttributesByLayout[MAX_VERTEX_ATTRIBS];
|
||||
|
||||
struct Sampler
|
||||
{
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ void Shader::initializeCompiler()
|
|||
resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1;
|
||||
// resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
|
||||
resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
|
||||
resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
|
||||
|
||||
mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
|
||||
mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources);
|
||||
|
|
@ -304,6 +305,8 @@ void Shader::parseVaryings()
|
|||
mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
|
||||
mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
|
||||
mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
|
||||
mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL;
|
||||
mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,6 +338,8 @@ void Shader::uncompile()
|
|||
mUsesFrontFacing = false;
|
||||
mUsesPointSize = false;
|
||||
mUsesPointCoord = false;
|
||||
mUsesDepthRange = false;
|
||||
mUsesFragDepth = false;
|
||||
|
||||
mActiveUniforms.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ class Shader
|
|||
bool mUsesFrontFacing;
|
||||
bool mUsesPointSize;
|
||||
bool mUsesPointCoord;
|
||||
bool mUsesDepthRange;
|
||||
bool mUsesFragDepth;
|
||||
|
||||
static void *mFragmentCompiler;
|
||||
static void *mVertexCompiler;
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@
|
|||
#include "libGLESv2/main.h"
|
||||
#include "libGLESv2/mathutil.h"
|
||||
#include "libGLESv2/utilities.h"
|
||||
#if defined(ANGLE_ENABLE_D3D11)
|
||||
# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN
|
||||
#ifndef ANGLE_ENABLE_D3D11
|
||||
# include "libGLESv2/renderer/Blit.h"
|
||||
#else
|
||||
# include "libGLESv2/renderer/Blit.h"
|
||||
# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN
|
||||
#endif
|
||||
#include "libGLESv2/Renderbuffer.h"
|
||||
#include "libGLESv2/renderer/Image.h"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
|
@ -54,6 +54,7 @@ struct RasterizerState
|
|||
GLfloat polygonOffsetUnits;
|
||||
|
||||
bool pointDrawMode;
|
||||
bool multiSample;
|
||||
};
|
||||
|
||||
struct BlendState
|
||||
|
|
|
|||
|
|
@ -4893,6 +4893,7 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp
|
|||
case GL_RGB565:
|
||||
case GL_RGB8_OES:
|
||||
case GL_RGBA8_OES:
|
||||
case GL_BGRA8_EXT:
|
||||
case GL_STENCIL_INDEX8:
|
||||
case GL_DEPTH24_STENCIL8_OES:
|
||||
context->setRenderbufferStorage(width, height, internalformat, samples);
|
||||
|
|
@ -6977,17 +6978,14 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
|
|||
|
||||
if (context->getDrawFramebufferHandle() == 0)
|
||||
{
|
||||
if (n > 1)
|
||||
if (n != 1)
|
||||
{
|
||||
return gl::error(GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
if (n == 1)
|
||||
if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
|
||||
{
|
||||
if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
|
||||
{
|
||||
return gl::error(GL_INVALID_OPERATION);
|
||||
}
|
||||
return gl::error(GL_INVALID_OPERATION);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -7008,6 +7006,11 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
|
|||
{
|
||||
framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]);
|
||||
}
|
||||
|
||||
for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++)
|
||||
{
|
||||
framebuffer->setDrawBufferState(colorAttachment, GL_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
|
|
|
|||
|
|
@ -182,4 +182,7 @@ EXPORTS
|
|||
glGetProcAddress @148 NONAME
|
||||
glBindTexImage @158 NONAME
|
||||
glCreateRenderer @177 NONAME
|
||||
glDestroyRenderer @178 NONAME
|
||||
glDestroyRenderer @178 NONAME
|
||||
|
||||
; Setting up TRACE macro callbacks
|
||||
SetTraceFunctionPointers @180
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ EXPORTS
|
|||
glDrawElementsInstancedANGLE@20 @174
|
||||
glProgramBinaryOES@16 @175
|
||||
glGetProgramBinaryOES@20 @176
|
||||
glDrawBuffersEXT@8 @179
|
||||
|
||||
; EGL dependencies
|
||||
glCreateContext @144 NONAME
|
||||
|
|
@ -181,4 +182,7 @@ EXPORTS
|
|||
glGetProcAddress@4 @148 NONAME
|
||||
glBindTexImage@4 @158 NONAME
|
||||
glCreateRenderer @177 NONAME
|
||||
glDestroyRenderer @178 NONAME
|
||||
glDestroyRenderer @178 NONAME
|
||||
|
||||
; Setting up TRACE macro callbacks
|
||||
SetTraceFunctionPointers@8 @180
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ EXPORTS
|
|||
glDrawElementsInstancedANGLE @174
|
||||
glProgramBinaryOES @175
|
||||
glGetProgramBinaryOES @176
|
||||
glDrawBuffersEXT @179
|
||||
|
||||
; EGL dependencies
|
||||
glCreateContext @144 NONAME
|
||||
|
|
@ -182,3 +183,6 @@ EXPORTS
|
|||
glBindTexImage @158 NONAME
|
||||
glCreateRenderer @177 NONAME
|
||||
glDestroyRenderer @178 NONAME
|
||||
|
||||
; Setting up TRACE macro callbacks
|
||||
SetTraceFunctionPointers @180
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ EXPORTS
|
|||
glDrawElementsInstancedANGLE@20 @174
|
||||
glProgramBinaryOES@16 @175
|
||||
glGetProgramBinaryOES@20 @176
|
||||
glDrawBuffersEXT@8 @179
|
||||
|
||||
; EGL dependencies
|
||||
glCreateContext @144 NONAME
|
||||
|
|
@ -181,4 +182,7 @@ EXPORTS
|
|||
glGetProcAddress@4 @148 NONAME
|
||||
glBindTexImage@4 @158 NONAME
|
||||
glCreateRenderer @177 NONAME
|
||||
glDestroyRenderer @178 NONAME
|
||||
glDestroyRenderer @178 NONAME
|
||||
|
||||
; Setting up TRACE macro callbacks
|
||||
SetTraceFunctionPointers@8 @180
|
||||
|
|
|
|||
|
|
@ -71,30 +71,27 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gl::Current *current()
|
||||
{
|
||||
return (gl::Current*)TlsGetValue(currentTLS);
|
||||
}
|
||||
|
||||
#else // !QT_OPENGL_ES_2_ANGLE_STATIC
|
||||
|
||||
static inline gl::Current *current()
|
||||
{
|
||||
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
|
||||
static gl::Current curr = { 0, 0 };
|
||||
return &curr;
|
||||
}
|
||||
|
||||
#endif // QT_OPENGL_ES_2_ANGLE_STATIC
|
||||
#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
|
||||
|
||||
namespace gl
|
||||
{
|
||||
Current *getCurrent()
|
||||
{
|
||||
#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
|
||||
return (Current*)TlsGetValue(currentTLS);
|
||||
#else
|
||||
// No precautions for thread safety taken as ANGLE is used single-threaded in Qt.
|
||||
static gl::Current curr = { 0, 0 };
|
||||
return &curr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
|
||||
{
|
||||
Current *curr = current();
|
||||
Current *current = getCurrent();
|
||||
|
||||
curr->context = context;
|
||||
curr->display = display;
|
||||
current->context = context;
|
||||
current->display = display;
|
||||
|
||||
if (context && display && surface)
|
||||
{
|
||||
|
|
@ -104,7 +101,9 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
|
|||
|
||||
Context *getContext()
|
||||
{
|
||||
return current()->context;
|
||||
Current *current = getCurrent();
|
||||
|
||||
return current->context;
|
||||
}
|
||||
|
||||
Context *getNonLostContext()
|
||||
|
|
@ -128,7 +127,9 @@ Context *getNonLostContext()
|
|||
|
||||
egl::Display *getDisplay()
|
||||
{
|
||||
return current()->display;
|
||||
Current *current = getCurrent();
|
||||
|
||||
return current->display;
|
||||
}
|
||||
|
||||
// Records an error code
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
|
||||
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
|
@ -58,7 +58,7 @@ gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *rend
|
|||
void glDestroyContext(gl::Context *context);
|
||||
void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
|
||||
gl::Context *glGetCurrentContext();
|
||||
rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, bool softwareDevice);
|
||||
rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, EGLNativeDisplayType displayId);
|
||||
void glDestroyRenderer(rx::Renderer *renderer);
|
||||
|
||||
__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname);
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ inline bool supportsSSE2()
|
|||
return supports;
|
||||
}
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid()
|
||||
int info[4];
|
||||
__cpuid(info, 0);
|
||||
|
||||
|
|
@ -102,6 +103,7 @@ inline bool supportsSSE2()
|
|||
|
||||
supports = (info[3] >> 26) & 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
checked = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@
|
|||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#if defined(ANGLE_ENABLE_D3D11)
|
||||
# include <D3D11.h>
|
||||
# include <dxgi.h>
|
||||
#ifndef ANGLE_ENABLE_D3D11
|
||||
#include <d3d9.h>
|
||||
#else
|
||||
# include <d3d9.h>
|
||||
#include <D3D11.h>
|
||||
#include <dxgi.h>
|
||||
#endif
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -160,12 +160,20 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
|
|||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initialData;
|
||||
initialData.pSysMem = data;
|
||||
initialData.SysMemPitch = size;
|
||||
initialData.SysMemSlicePitch = 0;
|
||||
if (data)
|
||||
{
|
||||
D3D11_SUBRESOURCE_DATA initialData;
|
||||
initialData.pSysMem = data;
|
||||
initialData.SysMemPitch = size;
|
||||
initialData.SysMemSlicePitch = 0;
|
||||
|
||||
result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
|
||||
}
|
||||
|
||||
result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return gl::error(GL_OUT_OF_MEMORY);
|
||||
|
|
@ -173,7 +181,7 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
|
|||
|
||||
mStagingBufferSize = size;
|
||||
}
|
||||
else
|
||||
else if (data)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
|
||||
|
|
@ -182,8 +190,7 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
|
|||
return gl::error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
if (data)
|
||||
memcpy(mappedResource.pData, data, size);
|
||||
memcpy(mappedResource.pData, data, size);
|
||||
|
||||
context->Unmap(mStagingBuffer, 0);
|
||||
}
|
||||
|
|
@ -212,7 +219,6 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
|
|||
mBufferSize = 0;
|
||||
}
|
||||
|
||||
|
||||
if (data)
|
||||
{
|
||||
D3D11_SUBRESOURCE_DATA initialData;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,9 @@ void BufferStorage9::setData(const void* data, unsigned int size, unsigned int o
|
|||
|
||||
mSize = std::max(mSize, offset + size);
|
||||
if (data)
|
||||
{
|
||||
memcpy(reinterpret_cast<char*>(mMemory) + offset, data, size);
|
||||
}
|
||||
}
|
||||
|
||||
void BufferStorage9::clear()
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src)
|
|||
ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped;
|
||||
dest->map(&destMapped);
|
||||
src->map(&srcMapped);
|
||||
dest->map(D3D11_MAP_WRITE, &destMapped);
|
||||
src->map(D3D11_MAP_READ, &srcMapped);
|
||||
|
||||
const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(srcMapped.pData);
|
||||
unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData);
|
||||
|
|
@ -171,7 +171,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
|
|||
GLint unpackAlignment, const void *input)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mappedImage;
|
||||
HRESULT result = map(&mappedImage);
|
||||
HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("Could not map image for loading.");
|
||||
|
|
@ -194,7 +194,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
|
|||
loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
|
||||
break;
|
||||
case GL_LUMINANCE32F_EXT:
|
||||
loadLuminanceFloatDataToRGB(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
|
||||
loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
|
||||
break;
|
||||
case GL_ALPHA16F_EXT:
|
||||
loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
|
||||
|
|
@ -230,7 +230,7 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig
|
|||
loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
|
||||
break;
|
||||
case GL_RGB32F_EXT:
|
||||
loadRGBFloatDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
|
||||
loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
|
||||
break;
|
||||
case GL_RGB16F_EXT:
|
||||
loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
|
||||
|
|
@ -254,7 +254,7 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GL
|
|||
ASSERT(yoffset % 4 == 0);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mappedImage;
|
||||
HRESULT result = map(&mappedImage);
|
||||
HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("Could not map image for loading.");
|
||||
|
|
@ -344,8 +344,8 @@ void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width
|
|||
{
|
||||
// This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
|
||||
D3D11_MAPPED_SUBRESOURCE mappedImage;
|
||||
HRESULT result = map(&mappedImage);
|
||||
|
||||
HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
|
||||
|
||||
// determine the offset coordinate into the destination buffer
|
||||
GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset;
|
||||
void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset;
|
||||
|
|
@ -402,7 +402,7 @@ void Image11::createStagingTexture()
|
|||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.BindFlags = 0;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
|
||||
|
|
@ -420,7 +420,7 @@ void Image11::createStagingTexture()
|
|||
mDirty = false;
|
||||
}
|
||||
|
||||
HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
|
||||
HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
|
||||
{
|
||||
createStagingTexture();
|
||||
|
||||
|
|
@ -429,7 +429,7 @@ HRESULT Image11::map(D3D11_MAPPED_SUBRESOURCE *map)
|
|||
if (mStagingTexture)
|
||||
{
|
||||
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
|
||||
result = deviceContext->Map(mStagingTexture, mStagingSubresource, D3D11_MAP_WRITE, 0, map);
|
||||
result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map);
|
||||
|
||||
// this can fail if the device is removed (from TDR)
|
||||
if (d3d11::isDeviceLostError(result))
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class Image11 : public Image
|
|||
virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
|
||||
|
||||
protected:
|
||||
HRESULT map(D3D11_MAPPED_SUBRESOURCE *map);
|
||||
HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
|
||||
void unmap();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -67,18 +67,30 @@ unsigned int IndexBufferInterface::getSerial() const
|
|||
return mIndexBuffer->getSerial();
|
||||
}
|
||||
|
||||
int IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory)
|
||||
bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset)
|
||||
{
|
||||
if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
|
||||
// Protect against integer overflow
|
||||
if (mWritePosition + size < mWritePosition)
|
||||
{
|
||||
*outMappedMemory = NULL;
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
int oldWritePos = static_cast<int>(mWritePosition);
|
||||
mWritePosition += size;
|
||||
if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
|
||||
{
|
||||
if (outMappedMemory)
|
||||
{
|
||||
*outMappedMemory = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return oldWritePos;
|
||||
if (streamOffset)
|
||||
{
|
||||
*streamOffset = mWritePosition;
|
||||
}
|
||||
|
||||
mWritePosition += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndexBufferInterface::unmapBuffer()
|
||||
|
|
@ -130,12 +142,13 @@ bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum
|
|||
{
|
||||
bool result = true;
|
||||
unsigned int curBufferSize = getBufferSize();
|
||||
unsigned int writePos = getWritePosition();
|
||||
if (size > curBufferSize)
|
||||
{
|
||||
result = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
|
||||
setWritePosition(0);
|
||||
}
|
||||
else if (getWritePosition() + size > curBufferSize)
|
||||
else if (writePos + size > curBufferSize || writePos + size < writePos)
|
||||
{
|
||||
if (!discard())
|
||||
{
|
||||
|
|
@ -175,27 +188,9 @@ bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum in
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int StaticIndexBufferInterface::lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex)
|
||||
IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache()
|
||||
{
|
||||
IndexRange range = {offset, count};
|
||||
|
||||
std::map<IndexRange, IndexResult>::iterator res = mCache.find(range);
|
||||
|
||||
if (res == mCache.end())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*minIndex = res->second.minIndex;
|
||||
*maxIndex = res->second.maxIndex;
|
||||
return res->second.streamOffset;
|
||||
}
|
||||
|
||||
void StaticIndexBufferInterface::addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset)
|
||||
{
|
||||
IndexRange indexRange = {offset, count};
|
||||
IndexResult indexResult = {minIndex, maxIndex, streamOffset};
|
||||
mCache[indexRange] = indexResult;
|
||||
return &mIndexRangeCache;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#define LIBGLESV2_RENDERER_INDEXBUFFER_H_
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include "libGLESv2/renderer/IndexRangeCache.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
|
@ -58,7 +59,7 @@ class IndexBufferInterface
|
|||
|
||||
unsigned int getSerial() const;
|
||||
|
||||
int mapBuffer(unsigned int size, void** outMappedMemory);
|
||||
bool mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset);
|
||||
bool unmapBuffer();
|
||||
|
||||
IndexBuffer *getIndexBuffer() const;
|
||||
|
|
@ -99,37 +100,10 @@ class StaticIndexBufferInterface : public IndexBufferInterface
|
|||
|
||||
virtual bool reserveBufferSpace(unsigned int size, GLenum indexType);
|
||||
|
||||
unsigned int lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex); // Returns the offset into the index buffer, or -1 if not found
|
||||
void addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset);
|
||||
IndexRangeCache *getIndexRangeCache();
|
||||
|
||||
private:
|
||||
struct IndexRange
|
||||
{
|
||||
intptr_t offset;
|
||||
GLsizei count;
|
||||
|
||||
bool operator<(const IndexRange& rhs) const
|
||||
{
|
||||
if (offset != rhs.offset)
|
||||
{
|
||||
return offset < rhs.offset;
|
||||
}
|
||||
if (count != rhs.count)
|
||||
{
|
||||
return count < rhs.count;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct IndexResult
|
||||
{
|
||||
unsigned int minIndex;
|
||||
unsigned int maxIndex;
|
||||
unsigned int streamOffset;
|
||||
};
|
||||
|
||||
std::map<IndexRange, IndexResult> mCache;
|
||||
IndexRangeCache mIndexRangeCache;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** out
|
|||
{
|
||||
if (mBuffer)
|
||||
{
|
||||
if (offset + size > mBufferSize)
|
||||
// Check for integer overflows and out-out-bounds map requests
|
||||
if (offset + size < offset || offset + size > mBufferSize)
|
||||
{
|
||||
ERR("Index buffer map range is not inside the buffer.");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "libGLESv2/Buffer.h"
|
||||
#include "libGLESv2/main.h"
|
||||
#include "libGLESv2/utilities.h"
|
||||
#include "libGLESv2/renderer/IndexBuffer.h"
|
||||
|
||||
namespace rx
|
||||
|
|
@ -53,17 +54,6 @@ IndexDataManager::~IndexDataManager()
|
|||
delete mCountingBuffer;
|
||||
}
|
||||
|
||||
static unsigned int indexTypeSize(GLenum type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GL_UNSIGNED_INT: return sizeof(GLuint);
|
||||
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
|
||||
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
|
||||
default: UNREACHABLE(); return sizeof(GLushort);
|
||||
}
|
||||
}
|
||||
|
||||
static void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
|
||||
{
|
||||
if (type == GL_UNSIGNED_BYTE)
|
||||
|
|
@ -125,13 +115,19 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
|
|||
}
|
||||
|
||||
GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
|
||||
intptr_t offset = reinterpret_cast<intptr_t>(indices);
|
||||
unsigned int offset = 0;
|
||||
bool alignedOffset = false;
|
||||
|
||||
BufferStorage *storage = NULL;
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
if (reinterpret_cast<uintptr_t>(indices) > std::numeric_limits<unsigned int>::max())
|
||||
{
|
||||
return GL_OUT_OF_MEMORY;
|
||||
}
|
||||
offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
|
||||
|
||||
storage = buffer->getStorage();
|
||||
|
||||
switch (type)
|
||||
|
|
@ -142,7 +138,16 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
|
|||
default: UNREACHABLE(); alignedOffset = false;
|
||||
}
|
||||
|
||||
if (indexTypeSize(type) * count + offset > storage->getSize())
|
||||
unsigned int typeSize = gl::ComputeTypeSize(type);
|
||||
|
||||
// check for integer overflows
|
||||
if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeSize) ||
|
||||
typeSize * static_cast<unsigned int>(count) + offset < offset)
|
||||
{
|
||||
return GL_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (typeSize * static_cast<unsigned int>(count) + offset > storage->getSize())
|
||||
{
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
|
@ -156,37 +161,44 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
|
|||
IndexBufferInterface *indexBuffer = streamingBuffer;
|
||||
bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() &&
|
||||
destinationIndexType == type;
|
||||
UINT streamOffset = 0;
|
||||
unsigned int streamOffset = 0;
|
||||
|
||||
if (directStorage)
|
||||
{
|
||||
indexBuffer = streamingBuffer;
|
||||
streamOffset = offset;
|
||||
storage->markBufferUsage();
|
||||
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
|
||||
|
||||
if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
|
||||
&translated->maxIndex, NULL))
|
||||
{
|
||||
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
|
||||
buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
|
||||
translated->maxIndex, offset);
|
||||
}
|
||||
}
|
||||
else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset)
|
||||
{
|
||||
indexBuffer = staticBuffer;
|
||||
streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
|
||||
|
||||
if (streamOffset == -1)
|
||||
if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
|
||||
&translated->maxIndex, &streamOffset))
|
||||
{
|
||||
streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
|
||||
streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
|
||||
computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
|
||||
staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
|
||||
staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
|
||||
translated->maxIndex, streamOffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int convertCount = count;
|
||||
unsigned int convertCount = count;
|
||||
|
||||
if (staticBuffer)
|
||||
{
|
||||
if (staticBuffer->getBufferSize() == 0 && alignedOffset)
|
||||
{
|
||||
indexBuffer = staticBuffer;
|
||||
convertCount = storage->getSize() / indexTypeSize(type);
|
||||
convertCount = storage->getSize() / gl::ComputeTypeSize(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -201,12 +213,22 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
|
|||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
unsigned int bufferSizeRequired = convertCount * indexTypeSize(destinationIndexType);
|
||||
indexBuffer->reserveBufferSpace(bufferSizeRequired, type);
|
||||
unsigned int indexTypeSize = gl::ComputeTypeSize(destinationIndexType);
|
||||
if (convertCount > std::numeric_limits<unsigned int>::max() / indexTypeSize)
|
||||
{
|
||||
ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize);
|
||||
return GL_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
unsigned int bufferSizeRequired = convertCount * indexTypeSize;
|
||||
if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type))
|
||||
{
|
||||
ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired);
|
||||
return GL_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
void* output = NULL;
|
||||
streamOffset = indexBuffer->mapBuffer(bufferSizeRequired, &output);
|
||||
if (streamOffset == -1 || output == NULL)
|
||||
if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset))
|
||||
{
|
||||
ERR("Failed to map index buffer.");
|
||||
return GL_OUT_OF_MEMORY;
|
||||
|
|
@ -224,20 +246,21 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer
|
|||
|
||||
if (staticBuffer)
|
||||
{
|
||||
streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType);
|
||||
staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
|
||||
streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
|
||||
staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
|
||||
translated->maxIndex, streamOffset);
|
||||
}
|
||||
}
|
||||
|
||||
translated->storage = directStorage ? storage : NULL;
|
||||
translated->indexBuffer = indexBuffer->getIndexBuffer();
|
||||
translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
|
||||
translated->startIndex = streamOffset / indexTypeSize(destinationIndexType);
|
||||
translated->startIndex = streamOffset / gl::ComputeTypeSize(destinationIndexType);
|
||||
translated->startOffset = streamOffset;
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
buffer->promoteStaticUsage(count * indexTypeSize(type));
|
||||
buffer->promoteStaticUsage(count * gl::ComputeTypeSize(type));
|
||||
}
|
||||
|
||||
return GL_NO_ERROR;
|
||||
|
|
@ -256,7 +279,7 @@ StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
|
|||
mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
|
||||
|
||||
void* mappedMemory = NULL;
|
||||
if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
|
||||
if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
|
||||
{
|
||||
ERR("Failed to map counting buffer.");
|
||||
return NULL;
|
||||
|
|
@ -286,7 +309,7 @@ StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
|
|||
mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
|
||||
|
||||
void* mappedMemory = NULL;
|
||||
if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL)
|
||||
if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
|
||||
{
|
||||
ERR("Failed to map counting buffer.");
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
#include "precompiled.h"
|
||||
//
|
||||
// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
// IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about
|
||||
// ranges of indices.
|
||||
|
||||
#include "libGLESv2/renderer/IndexRangeCache.h"
|
||||
#include "common/debug.h"
|
||||
#include "libGLESv2/utilities.h"
|
||||
#include <tuple>
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx,
|
||||
unsigned int streamOffset)
|
||||
{
|
||||
mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(minIdx, maxIdx, streamOffset);
|
||||
}
|
||||
|
||||
void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
|
||||
{
|
||||
unsigned int invalidateStart = offset;
|
||||
unsigned int invalidateEnd = offset + size;
|
||||
|
||||
IndexRangeMap::iterator i = mIndexRangeCache.begin();
|
||||
while (i != mIndexRangeCache.end())
|
||||
{
|
||||
unsigned int rangeStart = i->second.streamOffset;
|
||||
unsigned int rangeEnd = i->second.streamOffset + (gl::ComputeTypeSize(i->first.type) * i->first.count);
|
||||
|
||||
if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = mIndexRangeCache.erase(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex,
|
||||
unsigned int *outMaxIndex, unsigned int *outStreamOffset) const
|
||||
{
|
||||
IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count));
|
||||
if (i != mIndexRangeCache.end())
|
||||
{
|
||||
if (outMinIndex) *outMinIndex = i->second.minIndex;
|
||||
if (outMaxIndex) *outMaxIndex = i->second.maxIndex;
|
||||
if (outStreamOffset) *outStreamOffset = i->second.streamOffset;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outMinIndex) *outMinIndex = 0;
|
||||
if (outMaxIndex) *outMaxIndex = 0;
|
||||
if (outStreamOffset) *outStreamOffset = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void IndexRangeCache::clear()
|
||||
{
|
||||
mIndexRangeCache.clear();
|
||||
}
|
||||
|
||||
IndexRangeCache::IndexRange::IndexRange()
|
||||
: type(GL_NONE), offset(0), count(0)
|
||||
{
|
||||
}
|
||||
|
||||
IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c)
|
||||
: type(typ), offset(off), count(c)
|
||||
{
|
||||
}
|
||||
|
||||
bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const
|
||||
{
|
||||
return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count);
|
||||
}
|
||||
|
||||
IndexRangeCache::IndexBounds::IndexBounds()
|
||||
: minIndex(0), maxIndex(0), streamOffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
IndexRangeCache::IndexBounds::IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset)
|
||||
: minIndex(minIdx), maxIndex(maxIdx), streamOffset(offset)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
|
||||
// IndexRangeCache.h: Defines the rx::IndexRangeCache class which stores information about
|
||||
// ranges of indices.
|
||||
|
||||
#ifndef LIBGLESV2_RENDERER_INDEXRANGECACHE_H_
|
||||
#define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_
|
||||
|
||||
#include "common/angleutils.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class IndexRangeCache
|
||||
{
|
||||
public:
|
||||
void addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx,
|
||||
unsigned int streamOffset);
|
||||
bool findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex,
|
||||
unsigned int *outMaxIndex, unsigned int *outStreamOffset) const;
|
||||
|
||||
void invalidateRange(unsigned int offset, unsigned int size);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
struct IndexRange
|
||||
{
|
||||
GLenum type;
|
||||
unsigned int offset;
|
||||
GLsizei count;
|
||||
|
||||
IndexRange();
|
||||
IndexRange(GLenum type, intptr_t offset, GLsizei count);
|
||||
|
||||
bool operator<(const IndexRange& rhs) const;
|
||||
};
|
||||
|
||||
struct IndexBounds
|
||||
{
|
||||
unsigned int minIndex;
|
||||
unsigned int maxIndex;
|
||||
unsigned int streamOffset;
|
||||
|
||||
IndexBounds();
|
||||
IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset);
|
||||
};
|
||||
|
||||
typedef std::map<IndexRange, IndexBounds> IndexRangeMap;
|
||||
IndexRangeMap mIndexRangeCache;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif LIBGLESV2_RENDERER_INDEXRANGECACHE_H
|
||||
|
|
@ -28,6 +28,13 @@ InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInp
|
|||
mCounter = 0;
|
||||
mDevice = NULL;
|
||||
mDeviceContext = NULL;
|
||||
mCurrentIL = NULL;
|
||||
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
mCurrentBuffers[i] = -1;
|
||||
mCurrentVertexStrides[i] = -1;
|
||||
mCurrentVertexOffsets[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
InputLayoutCache::~InputLayoutCache()
|
||||
|
|
@ -49,6 +56,18 @@ void InputLayoutCache::clear()
|
|||
i->second.inputLayout->Release();
|
||||
}
|
||||
mInputLayoutMap.clear();
|
||||
markDirty();
|
||||
}
|
||||
|
||||
void InputLayoutCache::markDirty()
|
||||
{
|
||||
mCurrentIL = NULL;
|
||||
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
mCurrentBuffers[i] = -1;
|
||||
mCurrentVertexStrides[i] = -1;
|
||||
mCurrentVertexOffsets[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
|
||||
|
|
@ -66,6 +85,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
|
|||
InputLayoutKey ilKey = { 0 };
|
||||
|
||||
ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL };
|
||||
unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 };
|
||||
UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 };
|
||||
UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 };
|
||||
|
||||
|
|
@ -83,18 +103,19 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
|
|||
// Record the type of the associated vertex shader vector in our key
|
||||
// This will prevent mismatched vertex shaders from using the same input layout
|
||||
GLint attributeSize;
|
||||
programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.glslElementType[ilKey.elementCount], NULL);
|
||||
programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL);
|
||||
|
||||
ilKey.elements[ilKey.elementCount].SemanticName = semanticName;
|
||||
ilKey.elements[ilKey.elementCount].SemanticIndex = sortedSemanticIndices[i];
|
||||
ilKey.elements[ilKey.elementCount].Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
ilKey.elements[ilKey.elementCount].InputSlot = i;
|
||||
ilKey.elements[ilKey.elementCount].AlignedByteOffset = 0;
|
||||
ilKey.elements[ilKey.elementCount].InputSlotClass = inputClass;
|
||||
ilKey.elements[ilKey.elementCount].InstanceDataStepRate = attributes[i].divisor;
|
||||
ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName;
|
||||
ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i];
|
||||
ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
|
||||
ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
|
||||
ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass;
|
||||
ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor;
|
||||
ilKey.elementCount++;
|
||||
|
||||
vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer();
|
||||
vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial();
|
||||
vertexStrides[i] = attributes[i].stride;
|
||||
vertexOffsets[i] = attributes[i].offset;
|
||||
}
|
||||
|
|
@ -112,7 +133,13 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
|
|||
{
|
||||
ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
|
||||
|
||||
HRESULT result = mDevice->CreateInputLayout(ilKey.elements, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
|
||||
D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
|
||||
for (unsigned int j = 0; j < ilKey.elementCount; ++j)
|
||||
{
|
||||
descs[j] = ilKey.elements[j].desc;
|
||||
}
|
||||
|
||||
HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
|
||||
if (FAILED(result))
|
||||
{
|
||||
ERR("Failed to crate input layout, result: 0x%08x", result);
|
||||
|
|
@ -143,8 +170,23 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
|
|||
mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair));
|
||||
}
|
||||
|
||||
mDeviceContext->IASetInputLayout(inputLayout);
|
||||
mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, vertexBuffers, vertexStrides, vertexOffsets);
|
||||
if (inputLayout != mCurrentIL)
|
||||
{
|
||||
mDeviceContext->IASetInputLayout(inputLayout);
|
||||
mCurrentIL = inputLayout;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] ||
|
||||
vertexOffsets[i] != mCurrentVertexOffsets[i])
|
||||
{
|
||||
mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]);
|
||||
mCurrentBuffers[i] = vertexBufferSerials[i];
|
||||
mCurrentVertexStrides[i] = vertexStrides[i];
|
||||
mCurrentVertexOffsets[i] = vertexOffsets[i];
|
||||
}
|
||||
}
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
|
@ -154,13 +196,18 @@ std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout)
|
|||
static const unsigned int seed = 0xDEADBEEF;
|
||||
|
||||
std::size_t hash = 0;
|
||||
MurmurHash3_x86_32(&inputLayout, sizeof(InputLayoutKey), seed, &hash);
|
||||
MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(InputLayoutKey)) == 0;
|
||||
if (a.elementCount != b.elementCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::equal(a.begin(), a.end(), b.begin());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class InputLayoutCache
|
|||
|
||||
void initialize(ID3D11Device *device, ID3D11DeviceContext *context);
|
||||
void clear();
|
||||
void markDirty();
|
||||
|
||||
GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
|
||||
gl::ProgramBinary *programBinary);
|
||||
|
|
@ -37,11 +38,26 @@ class InputLayoutCache
|
|||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(InputLayoutCache);
|
||||
|
||||
struct InputLayoutElement
|
||||
{
|
||||
D3D11_INPUT_ELEMENT_DESC desc;
|
||||
GLenum glslElementType;
|
||||
};
|
||||
|
||||
struct InputLayoutKey
|
||||
{
|
||||
unsigned int elementCount;
|
||||
D3D11_INPUT_ELEMENT_DESC elements[gl::MAX_VERTEX_ATTRIBS];
|
||||
GLenum glslElementType[gl::MAX_VERTEX_ATTRIBS];
|
||||
InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS];
|
||||
|
||||
const char *begin() const
|
||||
{
|
||||
return reinterpret_cast<const char*>(&elementCount);
|
||||
}
|
||||
|
||||
const char *end() const
|
||||
{
|
||||
return reinterpret_cast<const char*>(&elements[elementCount]);
|
||||
}
|
||||
};
|
||||
|
||||
struct InputLayoutCounterPair
|
||||
|
|
@ -50,6 +66,11 @@ class InputLayoutCache
|
|||
unsigned long long lastUsedTime;
|
||||
};
|
||||
|
||||
ID3D11InputLayout *mCurrentIL;
|
||||
unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS];
|
||||
UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS];
|
||||
UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS];
|
||||
|
||||
static std::size_t hashInputLayout(const InputLayoutKey &inputLayout);
|
||||
static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b);
|
||||
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer
|
|||
rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
|
||||
rasterDesc.DepthClipEnable = TRUE;
|
||||
rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
|
||||
rasterDesc.MultisampleEnable = TRUE;
|
||||
rasterDesc.MultisampleEnable = rasterState.multiSample;
|
||||
rasterDesc.AntialiasedLineEnable = FALSE;
|
||||
|
||||
ID3D11RasterizerState *dx11RasterizerState = NULL;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue