Commit 48dcae7b by Geoff Lang

Added transform feedback shader generation.

BUG=angle:495 Change-Id: I41a0177fd3eb43c9f4ab9e54faeadac3eb483c2c Reviewed-on: https://chromium-review.googlesource.com/185035Reviewed-by: 's avatarShannon Woods <shannonwoods@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 1b6edcb6
......@@ -1065,12 +1065,12 @@ Buffer *Context::getBuffer(GLuint handle)
return mResourceManager->getBuffer(handle);
}
Shader *Context::getShader(GLuint handle)
Shader *Context::getShader(GLuint handle) const
{
return mResourceManager->getShader(handle);
}
Program *Context::getProgram(GLuint handle)
Program *Context::getProgram(GLuint handle) const
{
return mResourceManager->getProgram(handle);
}
......
......@@ -327,8 +327,8 @@ class Context
Buffer *getBuffer(GLuint handle);
FenceNV *getFenceNV(GLuint handle);
FenceSync *getFenceSync(GLsync handle) const;
Shader *getShader(GLuint handle);
Program *getProgram(GLuint handle);
Shader *getShader(GLuint handle) const;
Program *getProgram(GLuint handle) const;
Texture *getTexture(GLuint handle);
Framebuffer *getFramebuffer(GLuint handle) const;
Renderbuffer *getRenderbuffer(GLuint handle);
......
......@@ -90,33 +90,58 @@ DynamicHLSL::DynamicHLSL(rx::Renderer *const renderer)
{
}
// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
// Returns the number of used varying registers, or -1 if unsuccesful
int DynamicHLSL::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader)
static bool packVarying(sh::Varying *varying, const int maxVaryingVectors, const sh::ShaderVariable *packing[][4])
{
const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
GLenum transposedType = TransposeMatrixType(varying->type);
fragmentShader->resetVaryingsRegisterAssignment();
// matrices within varying structs are not transposed
int registers = (varying->isStruct() ? sh::HLSLVariableRegisterCount(*varying) : gl::VariableRowCount(transposedType)) * varying->elementCount();
int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
bool success = false;
for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
if (elements == 2 || elements == 3 || elements == 4)
{
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
GLenum transposedType = TransposeMatrixType(varying->type);
for (int r = 0; r <= maxVaryingVectors - registers && !success; r++)
{
bool available = true;
for (int y = 0; y < registers && available; y++)
{
for (int x = 0; x < elements && available; x++)
{
if (packing[r + y][x])
{
available = false;
}
}
}
if (available)
{
varying->registerIndex = r;
varying->elementIndex = 0;
// matrices within varying structs are not transposed
int registers = (varying->isStruct() ? sh::HLSLVariableRegisterCount(*varying) : gl::VariableRowCount(transposedType)) * varying->elementCount();
int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType));
bool success = false;
for (int y = 0; y < registers; y++)
{
for (int x = 0; x < elements; x++)
{
packing[r + y][x] = &*varying;
}
}
if (elements == 2 || elements == 3 || elements == 4)
success = true;
}
}
if (!success && elements == 2)
{
for (int r = 0; r <= maxVaryingVectors - registers && !success; r++)
for (int r = maxVaryingVectors - registers; r >= 0 && !success; r--)
{
bool available = true;
for (int y = 0; y < registers && available; y++)
{
for (int x = 0; x < elements && available; x++)
for (int x = 2; x < 4 && available; x++)
{
if (packing[r + y][x])
{
......@@ -128,11 +153,11 @@ int DynamicHLSL::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packin
if (available)
{
varying->registerIndex = r;
varying->elementIndex = 0;
varying->elementIndex = 2;
for (int y = 0; y < registers; y++)
{
for (int x = 0; x < elements; x++)
for (int x = 2; x < 4; x++)
{
packing[r + y][x] = &*varying;
}
......@@ -141,96 +166,113 @@ int DynamicHLSL::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packin
success = true;
}
}
}
}
else if (elements == 1)
{
int space[4] = { 0 };
if (!success && elements == 2)
for (int y = 0; y < maxVaryingVectors; y++)
{
for (int x = 0; x < 4; x++)
{
for (int r = maxVaryingVectors - registers; r >= 0 && !success; r--)
{
bool available = true;
for (int y = 0; y < registers && available; y++)
{
for (int x = 2; x < 4 && available; x++)
{
if (packing[r + y][x])
{
available = false;
}
}
}
if (available)
{
varying->registerIndex = r;
varying->elementIndex = 2;
space[x] += packing[y][x] ? 0 : 1;
}
}
for (int y = 0; y < registers; y++)
{
for (int x = 2; x < 4; x++)
{
packing[r + y][x] = &*varying;
}
}
int column = 0;
success = true;
}
}
for (int x = 0; x < 4; x++)
{
if (space[x] >= registers && space[x] < space[column])
{
column = x;
}
}
else if (elements == 1)
{
int space[4] = {0};
for (int y = 0; y < maxVaryingVectors; y++)
if (space[column] >= registers)
{
for (int r = 0; r < maxVaryingVectors; r++)
{
for (int x = 0; x < 4; x++)
if (!packing[r][column])
{
space[x] += packing[y][x] ? 0 : 1;
}
}
varying->registerIndex = r;
int column = 0;
for (int y = r; y < r + registers; y++)
{
packing[y][column] = &*varying;
}
for (int x = 0; x < 4; x++)
{
if (space[x] >= registers && space[x] < space[column])
{
column = x;
break;
}
}
if (space[column] >= registers)
{
for (int r = 0; r < maxVaryingVectors; r++)
{
if (!packing[r][column])
{
varying->registerIndex = r;
varying->elementIndex = column;
for (int y = r; y < r + registers; y++)
{
packing[y][column] = &*varying;
}
success = true;
}
}
else UNREACHABLE();
break;
}
}
return success;
}
varying->elementIndex = column;
// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
// Returns the number of used varying registers, or -1 if unsuccesful
int DynamicHLSL::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader,
VertexShader *vertexShader, const std::vector<std::string>& transformFeedbackVaryings)
{
const int maxVaryingVectors = mRenderer->getMaxVaryingVectors();
success = true;
}
}
else UNREACHABLE();
vertexShader->resetVaryingsRegisterAssignment();
fragmentShader->resetVaryingsRegisterAssignment();
if (!success)
std::set<std::string> packedVaryings;
for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
{
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
if (packVarying(varying, maxVaryingVectors, packing))
{
packedVaryings.insert(varying->name);
}
else
{
infoLog.append("Could not pack varying %s", varying->name.c_str());
return -1;
}
}
for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++)
{
const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex];
if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end())
{
bool found = false;
for (unsigned int varyingIndex = 0; varyingIndex < vertexShader->mVaryings.size(); varyingIndex++)
{
sh::Varying *varying = &vertexShader->mVaryings[varyingIndex];
if (transformFeedbackVarying == varying->name)
{
if (!packVarying(varying, maxVaryingVectors, packing))
{
infoLog.append("Could not pack varying %s", varying->name.c_str());
return -1;
}
found = true;
break;
}
}
if (!found && transformFeedbackVarying != "gl_Position" && transformFeedbackVarying != "gl_PointSize")
{
infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str());
return -1;
}
}
}
// Return the number of used registers
int registers = 0;
......@@ -245,19 +287,21 @@ int DynamicHLSL::packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packin
return registers;
}
std::string DynamicHLSL::generateVaryingHLSL(FragmentShader *fragmentShader, const std::string &varyingSemantic) const
std::string DynamicHLSL::generateVaryingHLSL(VertexShader *shader, const std::string &varyingSemantic,
std::vector<LinkedVarying> *linkedVaryings) const
{
std::string varyingHLSL;
for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++)
for (unsigned int varyingIndex = 0; varyingIndex < shader->mVaryings.size(); varyingIndex++)
{
sh::Varying *varying = &fragmentShader->mVaryings[varyingIndex];
sh::Varying *varying = &shader->mVaryings[varyingIndex];
if (varying->registerAssigned())
{
GLenum transposedType = TransposeMatrixType(varying->type);
int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
for (unsigned int elementIndex = 0; elementIndex < varying->elementCount(); elementIndex++)
{
GLenum transposedType = TransposeMatrixType(varying->type);
int variableRows = (varying->isStruct() ? 1 : VariableRowCount(transposedType));
for (int row = 0; row < variableRows; row++)
{
switch (varying->interpolation)
......@@ -268,7 +312,8 @@ std::string DynamicHLSL::generateVaryingHLSL(FragmentShader *fragmentShader, con
default: UNREACHABLE();
}
std::string n = Str(varying->registerIndex + elementIndex * variableRows + row);
unsigned int semanticIndex = elementIndex * variableRows + varying->registerIndex + row;
std::string n = Str(semanticIndex);
std::string typeString;
......@@ -287,8 +332,14 @@ std::string DynamicHLSL::generateVaryingHLSL(FragmentShader *fragmentShader, con
varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n";
}
}
if (linkedVaryings)
{
linkedVaryings->push_back(LinkedVarying(varying->name, varying->type, varying->elementCount(),
varyingSemantic, varying->registerIndex,
variableRows * varying->elementCount()));
}
}
else UNREACHABLE();
}
return varyingHLSL;
......@@ -361,6 +412,8 @@ std::string DynamicHLSL::generateInputLayoutHLSL(const VertexFormat inputLayout[
bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const sh::ShaderVariable *packing[][4],
std::string& pixelHLSL, std::string& vertexHLSL,
FragmentShader *fragmentShader, VertexShader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings,
std::vector<LinkedVarying> *linkedVaryings,
std::map<int, VariableLocation> *programOutputVars) const
{
if (pixelHLSL.empty() || vertexHLSL.empty())
......@@ -400,32 +453,40 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
std::string varyingSemantic = (vertexShader->mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
std::string dxPositionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
std::string varyingHLSL = generateVaryingHLSL(vertexShader, varyingSemantic, linkedVaryings);
// special varyings that use reserved registers
int reservedRegisterIndex = registers;
std::string fragCoordSemantic;
std::string pointCoordSemantic;
unsigned int glPositionSemanticIndex = reservedRegisterIndex++;
std::string glPositionSemantic = varyingSemantic;
std::string fragCoordSemantic;
unsigned int fragCoordSemanticIndex = 0;
if (fragmentShader->mUsesFragCoord)
{
fragCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
fragCoordSemanticIndex = reservedRegisterIndex++;
fragCoordSemantic = varyingSemantic;
}
std::string pointCoordSemantic;
unsigned int pointCoordSemanticIndex = 0;
if (fragmentShader->mUsesPointCoord)
{
// Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords.
// In DX11 we compute this in the GS.
if (shaderModel == 3)
{
pointCoordSemanticIndex = 0;
pointCoordSemantic = "TEXCOORD0";
}
else if (shaderModel >= 4)
{
pointCoordSemantic = varyingSemantic + Str(reservedRegisterIndex++);
pointCoordSemanticIndex = reservedRegisterIndex++;
pointCoordSemantic = varyingSemantic;
}
}
......@@ -437,24 +498,31 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
if (shaderModel < 4)
{
vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
vertexHLSL += " float4 _dx_Position : " + dxPositionSemantic + ";\n";
vertexHLSL += " float4 gl_Position : " + glPositionSemantic + Str(glPositionSemanticIndex) + ";\n";
linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, glPositionSemantic, glPositionSemanticIndex, 1));
}
vertexHLSL += varyingHLSL;
if (fragmentShader->mUsesFragCoord)
{
vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n";
vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + Str(fragCoordSemanticIndex) + ";\n";
linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, fragCoordSemantic, fragCoordSemanticIndex, 1));
}
if (vertexShader->mUsesPointSize && shaderModel >= 3)
{
vertexHLSL += " float gl_PointSize : PSIZE;\n";
linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1));
}
if (shaderModel >= 4)
{
vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n";
vertexHLSL += " float4 _dx_Position : " + dxPositionSemantic + ";\n";
vertexHLSL += " float4 gl_Position : " + glPositionSemantic + Str(glPositionSemanticIndex) + ";\n";
linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, glPositionSemantic, glPositionSemanticIndex, 1));
}
vertexHLSL += "};\n"
......@@ -469,10 +537,11 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
" gl_main();\n"
"\n"
" VS_OUTPUT output;\n"
" output.gl_Position.x = gl_Position.x;\n"
" output.gl_Position.y = -gl_Position.y;\n"
" output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.gl_Position.w = gl_Position.w;\n";
" output.gl_Position = gl_Position;\n"
" output._dx_Position.x = gl_Position.x;\n"
" output._dx_Position.y = -gl_Position.y;\n"
" output._dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output._dx_Position.w = gl_Position.w;\n";
}
else
{
......@@ -480,10 +549,11 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
" gl_main();\n"
"\n"
" VS_OUTPUT output;\n"
" output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
" output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
" output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.gl_Position.w = gl_Position.w;\n";
" output.gl_Position = gl_Position;\n"
" output._dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
" output._dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
" output._dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output._dx_Position.w = gl_Position.w;\n";
}
if (vertexShader->mUsesPointSize && shaderModel >= 3)
......@@ -574,7 +644,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
if (fragmentShader->mUsesPointCoord && shaderModel >= 3)
{
pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n";
pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + Str(pointCoordSemanticIndex) + ";\n";
}
// Must consume the PSIZE element if the geometry shader is not active
......@@ -842,7 +912,7 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, const sh::Shader
"struct GS_INPUT\n"
"{\n";
std::string varyingHLSL = generateVaryingHLSL(fragmentShader, varyingSemantic);
std::string varyingHLSL = generateVaryingHLSL(vertexShader, varyingSemantic, NULL);
geomHLSL += varyingHLSL;
......
......@@ -29,6 +29,7 @@ class InfoLog;
class FragmentShader;
class VertexShader;
struct VariableLocation;
struct LinkedVarying;
class VertexAttribute;
struct VertexFormat;
......@@ -37,11 +38,14 @@ class DynamicHLSL
public:
explicit DynamicHLSL(rx::Renderer *const renderer);
int packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader);
int packVaryings(InfoLog &infoLog, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader,
VertexShader *vertexShader, const std::vector<std::string>& transformFeedbackVaryings);
std::string generateInputLayoutHLSL(const VertexFormat inputLayout[], const sh::Attribute shaderAttributes[]) const;
bool generateShaderLinkHLSL(InfoLog &infoLog, int registers, const sh::ShaderVariable *packing[][4],
std::string& pixelHLSL, std::string& vertexHLSL,
FragmentShader *fragmentShader, VertexShader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings,
std::vector<LinkedVarying> *linkedVaryings,
std::map<int, VariableLocation> *programOutputVars) const;
std::string generateGeometryShaderHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
......@@ -53,7 +57,8 @@ class DynamicHLSL
rx::Renderer *const mRenderer;
std::string generateVaryingHLSL(FragmentShader *fragmentShader, const std::string &varyingSemantic) const;
std::string generateVaryingHLSL(VertexShader *shader, const std::string &varyingSemantic,
std::vector<LinkedVarying> *linkedVaryings) const;
void defineOutputVariables(FragmentShader *fragmentShader, std::map<int, VariableLocation> *programOutputVars) const;
std::string generatePointSpriteHLSL(int registers, const sh::ShaderVariable *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const;
......
#include "precompiled.h"
//
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2014 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.
//
......@@ -252,7 +252,8 @@ bool Program::link()
resetUniformBlockBindings();
mProgramBinary.set(new ProgramBinary(mRenderer));
mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader);
mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
mTransformFeedbackVaryings, mTransformFeedbackBufferMode);
return mLinked;
}
......@@ -297,7 +298,7 @@ bool Program::isLinked()
return mLinked;
}
ProgramBinary* Program::getProgramBinary()
ProgramBinary* Program::getProgramBinary() const
{
return mProgramBinary.get();
}
......@@ -573,22 +574,88 @@ void Program::resetUniformBlockBindings()
}
}
void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
{
mTransformFeedbackVaryings.resize(count);
for (GLsizei i = 0; i < count; i++)
{
mTransformFeedbackVaryings[i] = varyings[i];
}
mTransformFeedbackBufferMode = bufferMode;
}
void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
{
ProgramBinary *programBinary = getProgramBinary();
if (programBinary && index < programBinary->getTransformFeedbackVaryingCount())
{
const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(index);
GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
if (length)
{
*length = lastNameIdx;
}
if (size)
{
*size = varying.size;
}
if (type)
{
*type = varying.type;
}
if (name)
{
memcpy(name, varying.name.c_str(), lastNameIdx);
name[lastNameIdx] = '\0';
}
}
}
GLsizei Program::getTransformFeedbackVaryingCount() const
{
UNIMPLEMENTED();
return 0;
ProgramBinary *programBinary = getProgramBinary();
if (programBinary)
{
return static_cast<GLsizei>(programBinary->getTransformFeedbackVaryingCount());
}
else
{
return 0;
}
}
GLsizei Program::getTransformFeedbackVaryingMaxLength() const
{
UNIMPLEMENTED();
return 0;
ProgramBinary *programBinary = getProgramBinary();
if (programBinary)
{
GLsizei maxSize = 0;
for (size_t i = 0; i < programBinary->getTransformFeedbackVaryingCount(); i++)
{
const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(i);
maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
}
return maxSize;
}
else
{
return 0;
}
}
GLenum Program::getTransformFeedbackBufferMode() const
{
UNIMPLEMENTED();
return GL_NONE;
ProgramBinary *programBinary = getProgramBinary();
if (programBinary)
{
return programBinary->getTransformFeedbackBufferMode();
}
else
{
return mTransformFeedbackBufferMode;
}
}
}
......@@ -78,7 +78,7 @@ class Program
bool link();
bool isLinked();
bool setProgramBinary(const void *binary, GLsizei length);
ProgramBinary *getProgramBinary();
ProgramBinary *getProgramBinary() const;
int getInfoLogLength() const;
void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
......@@ -98,6 +98,8 @@ class Program
void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
GLsizei getTransformFeedbackVaryingCount() const;
GLsizei getTransformFeedbackVaryingMaxLength() const;
GLenum getTransformFeedbackBufferMode() const;
......@@ -126,6 +128,9 @@ class Program
GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
std::vector<std::string> mTransformFeedbackVaryings;
GLuint mTransformFeedbackBufferMode;
BindingPointer<ProgramBinary> mProgramBinary;
bool mLinked;
bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
......
#include "precompiled.h"
//
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2014 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.
//
......@@ -105,6 +105,16 @@ bool ProgramBinary::VertexExecutable::matchesInputLayout(const VertexFormat attr
return true;
}
LinkedVarying::LinkedVarying()
{
}
LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
unsigned int semanticIndex, unsigned int semanticIndexCount)
: name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount)
{
}
unsigned int ProgramBinary::mCurrentSerial = 1;
ProgramBinary::ProgramBinary(rx::Renderer *renderer)
......@@ -209,7 +219,11 @@ rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const Ver
// Generate new vertex executable
InfoLog tempInfoLog;
rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, mVertexWorkarounds);
rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, vertexHLSL.c_str(),
rx::SHADER_VERTEX,
mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
mVertexWorkarounds);
if (!vertexExecutable)
{
......@@ -432,6 +446,21 @@ GLint ProgramBinary::getFragDataLocation(const char *name) const
return -1;
}
size_t ProgramBinary::getTransformFeedbackVaryingCount() const
{
return mTransformFeedbackLinkedVaryings.size();
}
const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const
{
return mTransformFeedbackLinkedVaryings[idx];
}
GLenum ProgramBinary::getTransformFeedbackBufferMode() const
{
return mTransformFeedbackBufferMode;
}
template <typename T>
bool ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
{
......@@ -972,8 +1001,6 @@ bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuff
bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader)
{
vertexShader->resetVaryingsRegisterAssignment();
std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getVaryings();
std::vector<sh::Varying> &vertexVaryings = vertexShader->getVaryings();
......@@ -1177,6 +1204,21 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
stream.read(&mUniformIndex[i].index);
}
stream.read(&mTransformFeedbackBufferMode);
stream.read(&size);
mTransformFeedbackLinkedVaryings.resize(size);
for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
{
LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
stream.read(&varying.name);
stream.read(&varying.type);
stream.read(&varying.size);
stream.read(&varying.semanticName);
stream.read(&varying.semanticIndex);
stream.read(&varying.semanticIndexCount);
}
stream.read(&mVertexHLSL);
stream.read(&mVertexWorkarounds);
......@@ -1202,7 +1244,9 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
const char *vertexShaderFunction = (const char*) binary + stream.offset();
rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
vertexShaderSize, rx::SHADER_VERTEX);
vertexShaderSize, rx::SHADER_VERTEX,
mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
if (!shaderExecutable)
{
infoLog.append("Could not create vertex shader.");
......@@ -1219,7 +1263,8 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
const char *pixelShaderFunction = (const char*) binary + stream.offset();
mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(pixelShaderFunction),
pixelShaderSize, rx::SHADER_PIXEL);
pixelShaderSize, rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
if (!mPixelExecutable)
{
infoLog.append("Could not create pixel shader.");
......@@ -1234,7 +1279,8 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
{
const char *geometryShaderFunction = (const char*) binary + stream.offset();
mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
geometryShaderSize, rx::SHADER_GEOMETRY);
geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
if (!mGeometryExecutable)
{
infoLog.append("Could not create geometry shader.");
......@@ -1348,6 +1394,20 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
stream.write(mUniformIndex[i].index);
}
stream.write(mTransformFeedbackBufferMode);
stream.write(mTransformFeedbackLinkedVaryings.size());
for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
{
const LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
stream.write(varying.name);
stream.write(varying.type);
stream.write(varying.size);
stream.write(varying.semanticName);
stream.write(varying.semanticIndex);
stream.write(varying.semanticIndexCount);
}
stream.write(mVertexHLSL);
stream.write(mVertexWorkarounds);
......@@ -1439,7 +1499,8 @@ GLint ProgramBinary::getLength()
}
}
bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode)
{
if (!fragmentShader || !fragmentShader->isCompiled())
{
......@@ -1451,6 +1512,9 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
return false;
}
mTransformFeedbackLinkedVaryings.clear();
mTransformFeedbackBufferMode = transformFeedbackBufferMode;
mShaderVersion = vertexShader->getShaderVersion();
std::string pixelHLSL = fragmentShader->getHLSL();
......@@ -1459,7 +1523,7 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
// Map the varyings to the register file
const sh::ShaderVariable *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL};
int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShader);
int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShader, vertexShader, transformFeedbackVaryings);
if (registers < 0)
{
......@@ -1472,8 +1536,10 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
}
mUsesPointSize = vertexShader->usesPointSize();
std::vector<LinkedVarying> linkedVaryings;
if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, pixelHLSL, mVertexHLSL,
fragmentShader, vertexShader, &mOutputVariables))
fragmentShader, vertexShader, transformFeedbackVaryings,
&linkedVaryings, &mOutputVariables))
{
return false;
}
......@@ -1503,18 +1569,30 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
success = false;
}
if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings))
{
success = false;
}
if (success)
{
VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS];
GetInputLayoutFromShader(vertexShader->activeAttributes(), defaultInputLayout);
rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, fragmentShader->getD3DWorkarounds());
mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL,
mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
fragmentShader->getD3DWorkarounds());
if (usesGeometryShader())
{
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader);
mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE);
mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY,
mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
rx::ANGLE_D3D_WORKAROUND_NONE);
}
if (!defaultVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
......@@ -1530,6 +1608,8 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin
SafeDelete(mGeometryExecutable);
SafeDelete(mPixelExecutable);
mTransformFeedbackLinkedVaryings.clear();
}
}
......@@ -2071,6 +2151,64 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const sh::ActiveInterfac
return true;
}
bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
const std::vector<std::string> &transformFeedbackVaryingNames,
GLenum transformFeedbackBufferMode,
std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings) const
{
size_t totalComponents = 0;
const size_t maxSeparateComponents = mRenderer->getMaxTransformFeedbackSeparateComponents();
const size_t maxInterleavedComponents = mRenderer->getMaxTransformFeedbackInterleavedComponents();
// Gather the linked varyings that are used for transform feedback, they should all exist.
outTransformFeedbackLinkedVaryings->clear();
for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++)
{
bool found = false;
for (size_t j = 0; j < linkedVaryings.size(); j++)
{
if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name)
{
for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++)
{
if (outTransformFeedbackLinkedVaryings->at(k).name == linkedVaryings[j].name)
{
infoLog.append("Two transform feedback varyings specify the same output variable (%s).", linkedVaryings[j].name.c_str());
return false;
}
}
size_t componentCount = linkedVaryings[j].semanticIndexCount * 4;
if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
componentCount > maxSeparateComponents)
{
infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).",
linkedVaryings[j].name.c_str(), componentCount, maxSeparateComponents);
return false;
}
totalComponents += componentCount;
outTransformFeedbackLinkedVaryings->push_back(linkedVaryings[j]);
found = true;
break;
}
}
// All transform feedback varyings are expected to exist since packVaryings checks for them.
ASSERT(found);
}
if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > maxInterleavedComponents)
{
infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).",
totalComponents, maxInterleavedComponents);
return false;
}
return true;
}
void ProgramBinary::defineUniformBlockMembers(const std::vector<sh::InterfaceBlockField> &fields, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector<unsigned int> *blockUniformIndexes)
{
for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
......
//
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2014 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,6 +58,24 @@ struct VariableLocation
unsigned int index;
};
struct LinkedVarying
{
LinkedVarying();
LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
unsigned int semanticIndex, unsigned int semanticIndexCount);
// Original GL name
std::string name;
GLenum type;
GLsizei size;
// DirectX semantic information
std::string semanticName;
unsigned int semanticIndex;
unsigned int semanticIndexCount;
};
// This is the result of linking a program. It is the state that would be passed to ProgramBinary.
class ProgramBinary : public RefCountObject
{
......@@ -116,7 +134,8 @@ class ProgramBinary : public RefCountObject
bool save(void* binary, GLsizei bufSize, GLsizei *length);
GLint getLength();
bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode);
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
......@@ -136,6 +155,10 @@ class ProgramBinary : public RefCountObject
GLint getFragDataLocation(const char *name) const;
size_t getTransformFeedbackVaryingCount() const;
const LinkedVarying &getTransformFeedbackVarying(size_t idx) const;
GLenum getTransformFeedbackBufferMode() const;
void validate(InfoLog &infoLog);
bool validateSamplers(InfoLog *infoLog);
bool isValidated() const;
......@@ -169,6 +192,10 @@ class ProgramBinary : public RefCountObject
bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog);
bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock);
bool linkUniformBlocks(InfoLog &infoLog, const sh::ActiveInterfaceBlocks &vertexUniformBlocks, const sh::ActiveInterfaceBlocks &fragmentUniformBlocks);
bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
const std::vector<std::string> &transformFeedbackVaryingNames,
GLenum transformFeedbackBufferMode,
std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings) const;
void defineUniformBlockMembers(const std::vector<sh::InterfaceBlockField> &fields, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector<unsigned int> *blockUniformIndexes);
bool defineUniformBlock(InfoLog &infoLog, GLenum shader, const sh::InterfaceBlock &interfaceBlock);
bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex);
......@@ -216,6 +243,9 @@ class ProgramBinary : public RefCountObject
int mSemanticIndex[MAX_VERTEX_ATTRIBS];
int mAttributesByLayout[MAX_VERTEX_ATTRIBS];
GLenum mTransformFeedbackBufferMode;
std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings;
struct Sampler
{
Sampler();
......
#include "precompiled.h"
//
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2002-2014 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.
//
......@@ -7679,8 +7679,34 @@ void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const
return gl::error(GL_INVALID_OPERATION);
}
// glTransformFeedbackVaryings
UNIMPLEMENTED();
if (count < 0)
{
return gl::error(GL_INVALID_VALUE);
}
switch (bufferMode)
{
case GL_INTERLEAVED_ATTRIBS:
break;
case GL_SEPARATE_ATTRIBS:
if (static_cast<GLuint>(count) > context->getMaxTransformFeedbackBufferBindings())
{
return gl::error(GL_INVALID_VALUE);
}
break;
default:
return gl::error(GL_INVALID_ENUM);
}
if (!gl::ValidProgram(context, program))
{
return;
}
gl::Program *programObject = context->getProgram(program);
ASSERT(programObject);
programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
}
}
catch(std::bad_alloc&)
......@@ -7706,8 +7732,25 @@ void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsiz
return gl::error(GL_INVALID_OPERATION);
}
// glGetTransformFeedbackVarying
UNIMPLEMENTED();
if (bufSize < 0)
{
return gl::error(GL_INVALID_VALUE);
}
if (!gl::ValidProgram(context, program))
{
return;
}
gl::Program *programObject = context->getProgram(program);
ASSERT(programObject);
if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
{
return gl::error(GL_INVALID_VALUE);
}
programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
}
}
catch(std::bad_alloc&)
......
......@@ -39,6 +39,7 @@ namespace gl
{
class InfoLog;
class ProgramBinary;
struct LinkedVarying;
class VertexAttribute;
class Buffer;
class Texture;
......@@ -238,8 +239,12 @@ class Renderer
virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0;
// Shader operations
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type) = 0;
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) = 0;
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers) = 0;
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0;
virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
// Image operations
......
......@@ -2886,45 +2886,76 @@ RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum forma
return renderTarget;
}
ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type)
ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers)
{
ShaderExecutable11 *executable = NULL;
HRESULT result;
switch (type)
{
case rx::SHADER_VERTEX:
{
ID3D11VertexShader *vshader = NULL;
HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader);
ID3D11VertexShader *vertexShader = NULL;
ID3D11GeometryShader *streamOutShader = NULL;
result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
ASSERT(SUCCEEDED(result));
if (vshader)
if (transformFeedbackVaryings.size() > 0)
{
std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
for (size_t i = 0; i < transformFeedbackVaryings.size(); i++)
{
const gl::LinkedVarying &varying = transformFeedbackVaryings[i];
for (size_t j = 0; j < transformFeedbackVaryings[i].semanticIndexCount; j++)
{
D3D11_SO_DECLARATION_ENTRY entry = { 0 };
entry.Stream = 0;
entry.SemanticName = transformFeedbackVaryings[i].semanticName.c_str();
entry.SemanticIndex = transformFeedbackVaryings[i].semanticIndex + j;
entry.StartComponent = 0;
entry.ComponentCount = gl::VariableRowCount(type);
entry.OutputSlot = (separatedOutputBuffers ? i : 0);
soDeclaration.push_back(entry);
}
}
result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(),
NULL, 0, 0, NULL, &streamOutShader);
ASSERT(SUCCEEDED(result));
}
if (vertexShader)
{
executable = new ShaderExecutable11(function, length, vshader);
executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
}
}
break;
case rx::SHADER_PIXEL:
{
ID3D11PixelShader *pshader = NULL;
HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader);
ID3D11PixelShader *pixelShader = NULL;
result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
ASSERT(SUCCEEDED(result));
if (pshader)
if (pixelShader)
{
executable = new ShaderExecutable11(function, length, pshader);
executable = new ShaderExecutable11(function, length, pixelShader);
}
}
break;
case rx::SHADER_GEOMETRY:
{
ID3D11GeometryShader *gshader = NULL;
HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader);
ID3D11GeometryShader *geometryShader = NULL;
result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
ASSERT(SUCCEEDED(result));
if (gshader)
if (geometryShader)
{
executable = new ShaderExecutable11(function, length, gshader);
executable = new ShaderExecutable11(function, length, geometryShader);
}
}
break;
......@@ -2936,7 +2967,9 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
return executable;
}
ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround)
ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround)
{
const char *profile = NULL;
......@@ -2962,7 +2995,8 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch
return NULL;
}
ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type);
ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers);
SafeRelease(binary);
return executable;
......
......@@ -188,8 +188,12 @@ class Renderer11 : public Renderer
virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples);
// Shader operations
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround);
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround);
virtual UniformStorage *createUniformStorage(size_t storageSize);
// Image operations
......
#include "precompiled.h"
//
// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2012-2014 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.
//
......@@ -21,14 +21,16 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D
mPixelExecutable = executable;
mVertexExecutable = NULL;
mGeometryExecutable = NULL;
mStreamOutExecutable = NULL;
}
ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable)
ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut)
: ShaderExecutable(function, length)
{
mVertexExecutable = executable;
mPixelExecutable = NULL;
mGeometryExecutable = NULL;
mStreamOutExecutable = streamOut;
}
ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable)
......@@ -37,6 +39,7 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D
mGeometryExecutable = executable;
mVertexExecutable = NULL;
mPixelExecutable = NULL;
mStreamOutExecutable = NULL;
}
ShaderExecutable11::~ShaderExecutable11()
......@@ -44,6 +47,7 @@ ShaderExecutable11::~ShaderExecutable11()
SafeRelease(mVertexExecutable);
SafeRelease(mPixelExecutable);
SafeRelease(mGeometryExecutable);
SafeRelease(mStreamOutExecutable);
}
ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable)
......@@ -67,6 +71,11 @@ ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const
return mGeometryExecutable;
}
ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const
{
return mStreamOutExecutable;
}
UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize)
: UniformStorage(initialSize),
mConstantBuffer(NULL)
......@@ -99,4 +108,4 @@ const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStor
return static_cast<const UniformStorage11*>(uniformStorage);
}
}
\ No newline at end of file
}
//
// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
// Copyright (c) 2012-2014 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.
//
......@@ -21,7 +21,7 @@ class ShaderExecutable11 : public ShaderExecutable
{
public:
ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable);
ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable);
ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut);
ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable);
virtual ~ShaderExecutable11();
......@@ -31,6 +31,7 @@ class ShaderExecutable11 : public ShaderExecutable
ID3D11PixelShader *getPixelShader() const;
ID3D11VertexShader *getVertexShader() const;
ID3D11GeometryShader *getGeometryShader() const;
ID3D11GeometryShader *getStreamOutShader() const;
private:
DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11);
......@@ -38,6 +39,7 @@ class ShaderExecutable11 : public ShaderExecutable
ID3D11PixelShader *mPixelExecutable;
ID3D11VertexShader *mVertexExecutable;
ID3D11GeometryShader *mGeometryExecutable;
ID3D11GeometryShader *mStreamOutExecutable;
};
class UniformStorage11 : public UniformStorage
......
......@@ -3312,8 +3312,13 @@ RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format
return renderTarget;
}
ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type)
ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0);
ShaderExecutable9 *executable = NULL;
switch (type)
......@@ -3344,8 +3349,13 @@ ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length,
return executable;
}
ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround)
ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0);
const char *profile = NULL;
switch (type)
......@@ -3371,7 +3381,8 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const cha
return NULL;
}
ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type);
ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
transformFeedbackVaryings, separatedOutputBuffers);
SafeRelease(binary);
return executable;
......
......@@ -193,8 +193,12 @@ class Renderer9 : public Renderer
virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples);
// Shader operations
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround);
virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers);
virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
bool separatedOutputBuffers, D3DWorkaroundType workaround);
virtual UniformStorage *createUniformStorage(size_t storageSize);
// Image operations
......
......@@ -217,6 +217,28 @@ bool ValidQueryType(const Context *context, GLenum queryType)
}
}
bool ValidProgram(const Context *context, GLuint id)
{
// ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
// error INVALID_VALUE if the provided name is not the name of either a shader or program object and
// INVALID_OPERATION if the provided name identifies an object that is not the expected type."
if (context->getProgram(id) != NULL)
{
return true;
}
else if (context->getShader(id) != NULL)
{
// ID is the wrong type
return gl::error(GL_INVALID_OPERATION, false);
}
else
{
// No shader/program object has this ID
return gl::error(GL_INVALID_VALUE, false);
}
}
bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width, GLsizei height,
bool angleExtension)
......
......@@ -24,6 +24,7 @@ bool ValidMipLevel(const Context *context, GLenum target, GLint level);
bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth);
bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height);
bool ValidQueryType(const gl::Context *context, GLenum queryType);
bool ValidProgram(const gl::Context *context, GLuint id);
bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width, GLsizei height,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment