Commit 4e31ad55 by Jamie Madill

D3D11: Add dynamic geometry shaders.

The geometry shader we want will depend on our current draw mode, and if we're using flat shading in the shader. Without flat shading, we'll still be using them only for point sprites, but for other primitive types with flat shading enabled, we'll be using them to correct the provoking vertex order with D3D11. Note: no new features in this CL, those are turned on in follow-ups. BUG=angleproject:754 Change-Id: Iabf13ffd582f5a7200ee0df5aa9c3671aa7b6ed4 Reviewed-on: https://chromium-review.googlesource.com/309154Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 76f8fa66
......@@ -70,9 +70,9 @@ void SafeDelete(T*& resource)
template <typename T>
void SafeDeleteContainer(T& resource)
{
for (typename T::iterator i = resource.begin(); i != resource.end(); i++)
for (auto &element : resource)
{
SafeDelete(*i);
SafeDelete(element);
}
resource.clear();
}
......
......@@ -256,12 +256,14 @@ DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(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(const gl::Caps &caps,
bool DynamicHLSL::packVaryings(const gl::Caps &caps,
InfoLog &infoLog,
std::vector<PackedVarying> *packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings)
const std::vector<std::string> &transformFeedbackVaryings,
unsigned int *registerCountOut)
{
VaryingPacking packing = {};
*registerCountOut = 0;
std::set<std::string> uniqueVaryingNames;
......@@ -284,7 +286,7 @@ int DynamicHLSL::packVaryings(const gl::Caps &caps,
else
{
infoLog << "Could not pack varying " << varying.name;
return -1;
return false;
}
}
......@@ -308,7 +310,7 @@ int DynamicHLSL::packVaryings(const gl::Caps &caps,
if (!PackVarying(&packedVarying, caps.maxVaryingVectors, packing))
{
infoLog << "Could not pack varying " << varying.name;
return -1;
return false;
}
found = true;
......@@ -320,23 +322,21 @@ int DynamicHLSL::packVaryings(const gl::Caps &caps,
{
infoLog << "Transform feedback varying " << transformFeedbackVaryingName
<< " does not exist in the vertex shader.";
return -1;
return false;
}
}
}
// Return the number of used registers
int registers = 0;
for (GLuint r = 0; r < caps.maxVaryingVectors; r++)
{
if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
{
registers++;
(*registerCountOut)++;
}
}
return registers;
return true;
}
std::string DynamicHLSL::generateVaryingHLSL(const gl::Caps &caps,
......@@ -639,7 +639,7 @@ struct DynamicHLSL::SemanticInfo
BuiltinInfo glPointSize;
};
DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters,
DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(unsigned int startRegisters,
bool position,
bool fragCoord,
bool pointCoord,
......@@ -650,7 +650,7 @@ DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters,
bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4);
const std::string &varyingSemantic = getVaryingSemantic(pointSize);
int reservedRegisterIndex = startRegisters;
unsigned int reservedRegisterIndex = startRegisters;
if (hlsl4)
{
......@@ -783,7 +783,7 @@ void DynamicHLSL::storeUserLinkedVaryings(const std::vector<PackedVarying> &pack
bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
const gl::Program::Data &programData,
InfoLog &infoLog,
int registers,
unsigned int registerCount,
std::string *pixelHLSL,
std::string *vertexHLSL,
const std::vector<PackedVarying> &packedVaryings,
......@@ -813,7 +813,8 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData());
// Write the HLSL input/output declarations
const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0);
const unsigned int registersNeeded =
registerCount + (usesFragCoord ? 1u : 0u) + (usesPointCoord ? 1u : 0u);
// Two cases when writing to gl_FragColor and using ESSL 1.0:
// - with a 3.0 context, the output color is copied to channel 0
......@@ -844,7 +845,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
// gl_PointSize to be in VS_OUTPUT and GS_INPUT. Instanced point sprites doesn't need
// gl_PointSize in VS_OUTPUT.
const SemanticInfo &vertexSemantics =
getSemanticInfo(registers, outputPositionFromVS, usesFragCoord, addPointCoord,
getSemanticInfo(registerCount, outputPositionFromVS, usesFragCoord, addPointCoord,
(!useInstancedPointSpriteEmulation && usesPointSize), false);
storeUserLinkedVaryings(packedVaryings, usesPointSize, linkedVaryings);
......@@ -988,7 +989,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
pixelStream << fragmentShaderGL->getTranslatedSource();
const SemanticInfo &pixelSemantics =
getSemanticInfo(registers, outputPositionFromVS, usesFragCoord, usesPointCoord,
getSemanticInfo(registerCount, outputPositionFromVS, usesFragCoord, usesPointCoord,
(!useInstancedPointSpriteEmulation && usesPointSize), true);
pixelStream << "struct PS_INPUT\n" << generateVaryingLinkHLSL(pixelSemantics, varyingHLSL)
......@@ -1191,35 +1192,76 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
return true;
}
std::string DynamicHLSL::generateGeometryShaderHLSL(
gl::PrimitiveType primitiveType,
std::string DynamicHLSL::generateGeometryShaderPreamble(
const gl::Data &data,
const gl::Program::Data &programData,
int registers,
unsigned int registerCount,
const std::vector<PackedVarying> &packedVaryings) const
{
ASSERT(registers >= 0);
ASSERT(registerCount >= 0 && registerCount <= data.caps->maxVaryingVectors);
ASSERT(mRenderer->getMajorShaderModel() >= 4);
// Must be called during link, not from a binary load.
const ShaderD3D *vertexShader = GetImplAs<ShaderD3D>(programData.getAttachedVertexShader());
const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(programData.getAttachedFragmentShader());
ASSERT(vertexShader && fragmentShader);
bool usesFragCoord = fragmentShader->usesFragCoord();
bool usesPointCoord = fragmentShader->usesPointCoord();
bool usesPointSize = vertexShader->usesPointSize();
const SemanticInfo &inSemantics =
getSemanticInfo(registers, true, usesFragCoord, false, usesPointSize, false);
getSemanticInfo(registerCount, true, usesFragCoord, false, usesPointSize, false);
const SemanticInfo &outSemantics =
getSemanticInfo(registers, true, usesFragCoord, usesPointCoord, usesPointSize, false);
getSemanticInfo(registerCount, true, usesFragCoord, usesPointCoord, usesPointSize, false);
const std::string &varyingHLSL = generateVaryingHLSL(*data.caps, packedVaryings, usesPointSize);
std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL);
std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL);
std::stringstream preambleStream;
preambleStream << "struct GS_INPUT\n" << inLinkHLSL << "\n"
<< "struct GS_OUTPUT\n" << outLinkHLSL << "\n"
<< "void copyVertex(inout GS_OUTPUT output, GS_INPUT input)\n"
<< "{\n"
<< " output.gl_Position = input.gl_Position;\n";
if (usesPointSize)
{
preambleStream << " output.gl_PointSize = input.gl_PointSize;\n";
}
for (unsigned int r = 0; r < registerCount; ++r)
{
preambleStream << " output.v" << r << " = input.v" << r << ";\n";
}
if (usesFragCoord)
{
preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n";
}
// Only write the dx_Position if we aren't using point sprites
preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n"
<< " output.dx_Position = input.dx_Position;\n"
<< "#endif // ANGLE_POINT_SPRITE_SHADER\n"
<< "}\n";
return preambleStream.str();
}
std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
const gl::Data &data,
const gl::Program::Data &programData,
const std::string &preambleString) const
{
ASSERT(mRenderer->getMajorShaderModel() >= 4);
std::stringstream shaderStream;
const bool pointSprites = (primitiveType == PRIMITIVE_POINTS);
std::string varyingHLSL = generateVaryingHLSL(*data.caps, packedVaryings, usesPointSize);
std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL);
std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL);
const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos;
const char *inputPT = nullptr;
const char *outputPT = nullptr;
......@@ -1260,7 +1302,9 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(
if (pointSprites)
{
shaderStream << "uniform float4 dx_ViewCoords : register(c1);\n"
shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
"\n"
"uniform float4 dx_ViewCoords : register(c1);\n"
"\n"
"static float2 pointSpriteCorners[] = \n"
"{\n"
......@@ -1286,9 +1330,7 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(
<< "\n";
}
shaderStream << "struct GS_INPUT\n" << inLinkHLSL << "\n"
<< "struct GS_OUTPUT\n" << outLinkHLSL << "\n"
<< "\n"
shaderStream << preambleString << "\n"
<< "[maxvertexcount(" << maxVertexOutput << ")]\n"
<< "void main(" << inputPT << " GS_INPUT input[" << inputSize << "],"
" inout "
......@@ -1296,37 +1338,19 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(
<< "{\n"
<< " GS_OUTPUT output = (GS_OUTPUT)0;\n";
for (int vid = 0; vid < inputSize; ++vid)
for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex)
{
shaderStream << " output.gl_Position = input[" << vid << "].gl_Position;\n";
if (usesPointSize)
{
shaderStream << " output.gl_PointSize = input[" << vid << "].gl_PointSize;\n";
}
for (int r = 0; r < registers; ++r)
{
shaderStream << " output.v" << r << " = input[" << vid << "].v" << r << ";\n";
}
if (usesFragCoord)
{
shaderStream << " output.gl_FragCoord = input[" << vid << "].gl_FragCoord;\n";
}
shaderStream << " copyVertex(output, input[" << vertexIndex << "]);\n";
if (!pointSprites)
{
ASSERT(inputSize == maxVertexOutput);
shaderStream << " output.dx_Position = input[" << vid << "].dx_Position;\n"
<< " outStream.Append(output);\n";
shaderStream << " outStream.Append(output);\n";
}
}
if (pointSprites)
{
ASSERT(usesPointSize);
shaderStream << "\n"
" float4 dx_Position = input[0].dx_Position;\n"
" float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, "
......
......@@ -74,10 +74,11 @@ class DynamicHLSL : angle::NonCopyable
public:
explicit DynamicHLSL(RendererD3D *const renderer);
int packVaryings(const gl::Caps &caps,
bool packVaryings(const gl::Caps &caps,
gl::InfoLog &infoLog,
std::vector<PackedVarying> *packedVaryings,
const std::vector<std::string> &transformFeedbackVaryings);
const std::vector<std::string> &transformFeedbackVaryings,
unsigned int *registerCountOut);
std::string generateVertexShaderForInputLayout(
const std::string &sourceShader,
const gl::InputLayout &inputLayout,
......@@ -90,7 +91,7 @@ class DynamicHLSL : angle::NonCopyable
bool generateShaderLinkHLSL(const gl::Data &data,
const gl::Program::Data &programData,
gl::InfoLog &infoLog,
int registers,
unsigned int registerCount,
std::string *pixelHLSL,
std::string *vertexHLSL,
const std::vector<PackedVarying> &packedVaryings,
......@@ -98,19 +99,24 @@ class DynamicHLSL : angle::NonCopyable
std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
bool *outUsesFragDepth) const;
std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
std::string generateGeometryShaderPreamble(
const gl::Data &data,
const gl::Program::Data &programData,
int registers,
unsigned int registers,
const std::vector<PackedVarying> &packedVaryings) const;
std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
const gl::Data &data,
const gl::Program::Data &programData,
const std::string &preambleString) const;
private:
RendererD3D *const mRenderer;
struct SemanticInfo;
std::string getVaryingSemantic(bool pointSize) const;
SemanticInfo getSemanticInfo(int startRegisters,
SemanticInfo getSemanticInfo(unsigned int startRegisters,
bool position,
bool fragCoord,
bool pointCoord,
......
......@@ -260,6 +260,35 @@ bool ExpandMatrix(T *target,
return dirty;
}
gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
{
switch (drawMode)
{
// Uses the point sprite geometry shader.
case GL_POINTS:
return gl::PRIMITIVE_POINTS;
// All line drawing uses the same geometry shader.
case GL_LINES:
case GL_LINE_STRIP:
case GL_LINE_LOOP:
return gl::PRIMITIVE_LINES;
// The triangle fan primitive is emulated with strips in D3D11.
case GL_TRIANGLES:
case GL_TRIANGLE_FAN:
return gl::PRIMITIVE_TRIANGLES;
// Special case for triangle strips.
case GL_TRIANGLE_STRIP:
return gl::PRIMITIVE_TRIANGLE_STRIP;
default:
UNREACHABLE();
return gl::PRIMITIVE_TYPE_MAX;
}
}
} // anonymous namespace
D3DUniform::D3DUniform(GLenum typeIn,
......@@ -380,7 +409,7 @@ ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
: ProgramImpl(data),
mRenderer(renderer),
mDynamicHLSL(NULL),
mGeometryExecutable(NULL),
mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr),
mUsesPointSize(false),
mVertexUniformStorage(NULL),
mFragmentUniformStorage(NULL),
......@@ -663,6 +692,8 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
}
stream->readString(&mGeometryShaderPreamble);
const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
......@@ -741,21 +772,29 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
stream->skip(pixelShaderSize);
}
for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX;
++geometryExeIndex)
{
unsigned int geometryShaderSize = stream->readInt<unsigned int>();
if (geometryShaderSize > 0)
if (geometryShaderSize == 0)
{
mGeometryExecutables[geometryExeIndex] = nullptr;
continue;
}
const unsigned char *geometryShaderFunction = binary + stream->offset();
gl::Error error = mRenderer->loadExecutable(
geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
mTransformFeedbackLinkedVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &mGeometryExecutable);
bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
gl::Error error =
mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY,
mTransformFeedbackLinkedVaryings, splitAttribs,
&mGeometryExecutables[geometryExeIndex]);
if (error.isError())
{
return LinkResult(false, error);
}
if (!mGeometryExecutable)
if (!mGeometryExecutables[geometryExeIndex])
{
infoLog << "Could not create geometry shader.";
return LinkResult(false, gl::Error(GL_NO_ERROR));
......@@ -856,6 +895,8 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeInt(variable.outputIndex);
}
stream->writeString(mGeometryShaderPreamble);
stream->writeInt(mVertexExecutables.size());
for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
vertexExecutableIndex++)
......@@ -897,14 +938,17 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeBytes(pixelBlob, pixelShaderSize);
}
size_t geometryShaderSize =
(mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
stream->writeInt(geometryShaderSize);
if (mGeometryExecutable != NULL && geometryShaderSize > 0)
for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables)
{
if (geometryExe == nullptr)
{
const uint8_t *geometryBlob = mGeometryExecutable->getFunction();
stream->writeBytes(geometryBlob, geometryShaderSize);
stream->writeInt(0);
continue;
}
size_t geometryShaderSize = geometryExe->getLength();
stream->writeInt(geometryShaderSize);
stream->writeBytes(geometryExe->getFunction(), geometryShaderSize);
}
return gl::Error(GL_NO_ERROR);
......@@ -1034,10 +1078,48 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &i
return gl::Error(GL_NO_ERROR);
}
LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data,
gl::InfoLog &infoLog,
int registers,
const std::vector<PackedVarying> &packedVaryings)
gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data,
GLenum drawMode,
ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog)
{
gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
if (mGeometryExecutables[geometryShaderType] != nullptr)
{
if (outExecutable)
{
*outExecutable = mGeometryExecutables[geometryShaderType];
}
return gl::Error(GL_NO_ERROR);
}
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
geometryShaderType, data, mData, mGeometryShaderPreamble);
gl::InfoLog tempInfoLog;
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
gl::Error error = mRenderer->compileToExecutable(
*currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(),
&mGeometryExecutables[geometryShaderType]);
if (!infoLog && error.isError())
{
std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]);
}
if (outExecutable)
{
*outExecutable = mGeometryExecutables[geometryShaderType];
}
return error;
}
LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog)
{
const gl::InputLayout &defaultInputLayout =
GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
......@@ -1058,19 +1140,10 @@ LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data,
return LinkResult(false, error);
}
// Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11.
if (usesGeometryShader())
{
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
gl::PRIMITIVE_POINTS, data, mData, registers, packedVaryings);
error = mRenderer->compileToExecutable(
infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
(mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
D3DCompilerWorkarounds(), &mGeometryExecutable);
if (error.isError())
{
return LinkResult(false, error);
}
getGeometryExecutableForPrimitiveType(data, GL_POINTS, nullptr, &infoLog);
}
#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
......@@ -1099,7 +1172,7 @@ LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data,
#endif
bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable &&
(!usesGeometryShader() || mGeometryExecutable));
(!usesGeometryShader() || mGeometryExecutables[gl::PRIMITIVE_POINTS]));
return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
}
......@@ -1142,16 +1215,15 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
// Map the varyings to the register file
int registers = mDynamicHLSL->packVaryings(*data.caps, infoLog, &packedVaryings,
mData.getTransformFeedbackVaryingNames());
if (registers < 0)
unsigned int registerCount = 0;
if (!mDynamicHLSL->packVaryings(*data.caps, infoLog, &packedVaryings,
mData.getTransformFeedbackVaryingNames(), &registerCount))
{
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
std::vector<gl::LinkedVarying> linkedVaryings;
if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, &mPixelHLSL,
if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registerCount, &mPixelHLSL,
&mVertexHLSL, packedVaryings, &linkedVaryings,
&mPixelShaderKey, &mUsesFragDepth))
{
......@@ -1160,13 +1232,19 @@ LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
mUsesPointSize = vertexShaderD3D->usesPointSize();
if (mRenderer->getMajorShaderModel() >= 4)
{
mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
data, mData, registerCount, packedVaryings);
}
initSemanticIndex();
defineUniformsAndAssignRegisters();
gatherTransformFeedbackVaryings(linkedVaryings);
LinkResult result = compileProgramExecutables(data, infoLog, registers, packedVaryings);
LinkResult result = compileProgramExecutables(data, infoLog);
if (result.error.isError() || !result.linkSuccess)
{
infoLog << "Failed to create D3D shaders.";
......@@ -1849,7 +1927,11 @@ void ProgramD3D::reset()
{
SafeDeleteContainer(mVertexExecutables);
SafeDeleteContainer(mPixelExecutables);
SafeDelete(mGeometryExecutable);
for (auto &element : mGeometryExecutables)
{
SafeDelete(element);
}
mVertexHLSL.clear();
mVertexWorkarounds = D3DCompilerWorkarounds();
......@@ -1877,6 +1959,8 @@ void ProgramD3D::reset()
std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
mTransformFeedbackLinkedVaryings.clear();
mGeometryShaderPreamble.clear();
}
unsigned int ProgramD3D::getSerial() const
......
......@@ -113,7 +113,10 @@ class ProgramD3D : public ProgramImpl
gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
ShaderExecutableD3D **outExectuable,
gl::InfoLog *infoLog);
ShaderExecutableD3D *getGeometryExecutable() const { return mGeometryExecutable; }
gl::Error getGeometryExecutableForPrimitiveType(const gl::Data &data,
GLenum drawMode,
ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog);
LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
......@@ -278,10 +281,7 @@ class ProgramD3D : public ProgramImpl
const GLfloat *value,
GLenum targetUniformType);
LinkResult compileProgramExecutables(const gl::Data &data,
gl::InfoLog &infoLog,
int registers,
const std::vector<PackedVarying> &packedVaryings);
LinkResult compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog);
void gatherTransformFeedbackVaryings(const std::vector<gl::LinkedVarying> &varyings);
D3DUniform *getD3DUniformByName(const std::string &name);
......@@ -301,7 +301,7 @@ class ProgramD3D : public ProgramImpl
std::vector<VertexExecutable *> mVertexExecutables;
std::vector<PixelExecutable *> mPixelExecutables;
ShaderExecutableD3D *mGeometryExecutable;
std::vector<ShaderExecutableD3D *> mGeometryExecutables;
std::string mVertexHLSL;
D3DCompilerWorkarounds mVertexWorkarounds;
......@@ -311,6 +311,11 @@ class ProgramD3D : public ProgramImpl
bool mUsesFragDepth;
std::vector<PixelShaderOutputVariable> mPixelShaderKey;
// Common code for all dynamic geometry shaders. Consists mainly of the GS input and output
// structures, built from the linked varying info. We store the string itself instead of the
// packed varyings for simplicity.
std::string mGeometryShaderPreamble;
bool mUsesPointSize;
UniformStorageD3D *mVertexUniformStorage;
......
......@@ -195,7 +195,7 @@ gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
return error;
}
error = applyShaders(data);
error = applyShaders(data, mode);
if (error.isError())
{
return error;
......@@ -270,7 +270,7 @@ gl::Error RendererD3D::genericDrawArrays(const gl::Data &data,
return error;
}
error = applyShaders(data);
error = applyShaders(data, mode);
if (error.isError())
{
return error;
......@@ -436,13 +436,13 @@ gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode)
}
// Applies the shaders and shader constants to the Direct3D device
gl::Error RendererD3D::applyShaders(const gl::Data &data)
gl::Error RendererD3D::applyShaders(const gl::Data &data, GLenum drawMode)
{
gl::Program *program = data.state->getProgram();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
programD3D->updateCachedInputLayout(*data.state);
gl::Error error = applyShadersImpl(data);
gl::Error error = applyShadersImpl(data, drawMode);
if (error.isError())
{
return error;
......
......@@ -242,7 +242,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
protected:
virtual bool getLUID(LUID *adapterLuid) const = 0;
virtual gl::Error applyShadersImpl(const gl::Data &data) = 0;
virtual gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) = 0;
void cleanup();
......@@ -296,7 +296,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport);
gl::Error applyState(const gl::Data &data, GLenum drawMode);
gl::Error applyShaders(const gl::Data &data);
gl::Error applyShaders(const gl::Data &data, GLenum drawMode);
gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType,
const FramebufferTextureArray &framebufferTextures, size_t framebufferTextureCount);
gl::Error applyTextures(const gl::Data &data);
......
......@@ -1711,7 +1711,15 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
mDeviceContext->PSSetShader(pixelShader, NULL, 0);
// Retrieve the point sprite geometry shader
rx::ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable();
rx::ShaderExecutableD3D *geometryExe = nullptr;
error = programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe,
nullptr);
if (error.isError())
{
return error;
}
ID3D11GeometryShader *geometryShader = (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL);
mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
ASSERT(geometryShader);
......@@ -2045,7 +2053,7 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
return gl::Error(GL_NO_ERROR);
}
gl::Error Renderer11::applyShadersImpl(const gl::Data &data)
gl::Error Renderer11::applyShadersImpl(const gl::Data &data, GLenum drawMode)
{
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
const auto &inputLayout = programD3D->getCachedInputLayout();
......@@ -2065,7 +2073,13 @@ gl::Error Renderer11::applyShadersImpl(const gl::Data &data)
return error;
}
ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable();
ShaderExecutableD3D *geometryExe = nullptr;
error =
programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr);
if (error.isError())
{
return error;
}
ID3D11VertexShader *vertexShader = (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : NULL);
......@@ -2083,7 +2097,7 @@ gl::Error Renderer11::applyShadersImpl(const gl::Data &data)
{
geometryShader = (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : NULL);
}
else if (mCurRasterState.pointDrawMode)
else
{
geometryShader = (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL);
}
......
......@@ -132,7 +132,6 @@ class Renderer11 : public RendererD3D
virtual bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
gl::Error applyUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray) override;
virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances, SourceIndexData *sourceIndexInfo);
......@@ -269,7 +268,7 @@ class Renderer11 : public RendererD3D
protected:
void createAnnotator() override;
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
gl::Error applyShadersImpl(const gl::Data &data) override;
gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
private:
gl::Error drawArraysImpl(const gl::Data &data,
......
......@@ -1862,7 +1862,7 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou
return gl::Error(GL_NO_ERROR);
}
gl::Error Renderer9::applyShadersImpl(const gl::Data &data)
gl::Error Renderer9::applyShadersImpl(const gl::Data &data, GLenum /*drawMode*/)
{
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
const auto &inputLayout = programD3D->getCachedInputLayout();
......
......@@ -235,7 +235,7 @@ class Renderer9 : public RendererD3D
protected:
void createAnnotator() override;
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
gl::Error applyShadersImpl(const gl::Data &data) override;
gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
private:
gl::Error drawArraysImpl(const gl::Data &data,
......
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