You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
12 KiB
309 lines
12 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Quality Program OpenGL (ES) Module
|
|
* -----------------------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief sglr-rsg adaptation.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "glsRandomShaderProgram.hpp"
|
|
#include "rsgShader.hpp"
|
|
|
|
namespace deqp
|
|
{
|
|
namespace gls
|
|
{
|
|
|
|
using std::vector;
|
|
|
|
static rr::GenericVecType mapToGenericVecType (const rsg::VariableType& varType)
|
|
{
|
|
if (varType.isFloatOrVec())
|
|
return rr::GENERICVECTYPE_FLOAT;
|
|
else if (varType.isIntOrVec())
|
|
return rr::GENERICVECTYPE_INT32;
|
|
else
|
|
{
|
|
DE_ASSERT(false);
|
|
return rr::GENERICVECTYPE_LAST;
|
|
}
|
|
}
|
|
|
|
static glu::DataType mapToBasicType (const rsg::VariableType& varType)
|
|
{
|
|
if (varType.isFloatOrVec() || varType.isIntOrVec() || varType.isBoolOrVec())
|
|
{
|
|
const glu::DataType scalarType = varType.isFloatOrVec() ? glu::TYPE_FLOAT :
|
|
varType.isIntOrVec() ? glu::TYPE_INT :
|
|
varType.isBoolOrVec() ? glu::TYPE_BOOL : glu::TYPE_LAST;
|
|
const int numComps = varType.getNumElements();
|
|
|
|
DE_ASSERT(de::inRange(numComps, 1, 4));
|
|
return glu::DataType(scalarType + numComps - 1);
|
|
}
|
|
else if (varType.getBaseType() == rsg::VariableType::TYPE_SAMPLER_2D)
|
|
return glu::TYPE_SAMPLER_2D;
|
|
else if (varType.getBaseType() == rsg::VariableType::TYPE_SAMPLER_CUBE)
|
|
return glu::TYPE_SAMPLER_CUBE;
|
|
else
|
|
{
|
|
DE_ASSERT(false);
|
|
return glu::TYPE_LAST;
|
|
}
|
|
}
|
|
|
|
static void generateProgramDeclaration (sglr::pdec::ShaderProgramDeclaration& decl, const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
|
|
{
|
|
decl << sglr::pdec::VertexSource(vertexShader.getSource())
|
|
<< sglr::pdec::FragmentSource(fragmentShader.getSource());
|
|
|
|
for (vector<rsg::ShaderInput*>::const_iterator vtxInIter = vertexShader.getInputs().begin(); vtxInIter != vertexShader.getInputs().end(); ++vtxInIter)
|
|
{
|
|
const rsg::ShaderInput* vertexInput = *vtxInIter;
|
|
decl << sglr::pdec::VertexAttribute(vertexInput->getVariable()->getName(), mapToGenericVecType(vertexInput->getVariable()->getType()));
|
|
}
|
|
|
|
for (vector<rsg::ShaderInput*>::const_iterator fragInIter = fragmentShader.getInputs().begin(); fragInIter != fragmentShader.getInputs().end(); ++fragInIter)
|
|
{
|
|
const rsg::ShaderInput* fragInput = *fragInIter;
|
|
decl << sglr::pdec::VertexToFragmentVarying(mapToGenericVecType(fragInput->getVariable()->getType()));
|
|
}
|
|
|
|
for (int uniformNdx = 0; uniformNdx < numUnifiedUniforms; uniformNdx++)
|
|
{
|
|
const rsg::ShaderInput* uniform = unifiedUniforms[uniformNdx];
|
|
decl << sglr::pdec::Uniform(uniform->getVariable()->getName(), mapToBasicType(uniform->getVariable()->getType()));
|
|
}
|
|
|
|
decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
|
|
}
|
|
|
|
static sglr::pdec::ShaderProgramDeclaration generateProgramDeclaration (const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
|
|
{
|
|
sglr::pdec::ShaderProgramDeclaration decl;
|
|
generateProgramDeclaration(decl, vertexShader, fragmentShader, numUnifiedUniforms, unifiedUniforms);
|
|
return decl;
|
|
}
|
|
|
|
static const rsg::Variable* findShaderOutputByName (const rsg::Shader& shader, const char* name)
|
|
{
|
|
vector<const rsg::Variable*> outputs;
|
|
shader.getOutputs(outputs);
|
|
|
|
for (vector<const rsg::Variable*>::const_iterator iter = outputs.begin(); iter != outputs.end(); ++iter)
|
|
{
|
|
if (deStringEqual((*iter)->getName(), name))
|
|
return *iter;
|
|
}
|
|
|
|
return DE_NULL;
|
|
}
|
|
|
|
static const rsg::Variable* findShaderOutputByLocation (const rsg::Shader& shader, int location)
|
|
{
|
|
vector<const rsg::Variable*> outputs;
|
|
shader.getOutputs(outputs);
|
|
|
|
for (vector<const rsg::Variable*>::const_iterator iter = outputs.begin(); iter != outputs.end(); iter++)
|
|
{
|
|
if ((*iter)->getLayoutLocation() == location)
|
|
return *iter;
|
|
}
|
|
|
|
return DE_NULL;
|
|
}
|
|
|
|
RandomShaderProgram::RandomShaderProgram (const rsg::Shader& vertexShader, const rsg::Shader& fragmentShader, int numUnifiedUniforms, const rsg::ShaderInput* const* unifiedUniforms)
|
|
: sglr::ShaderProgram (generateProgramDeclaration(vertexShader, fragmentShader, numUnifiedUniforms, unifiedUniforms))
|
|
, m_vertexShader (vertexShader)
|
|
, m_fragmentShader (fragmentShader)
|
|
, m_numUnifiedUniforms (numUnifiedUniforms)
|
|
, m_unifiedUniforms (unifiedUniforms)
|
|
, m_positionVar (findShaderOutputByName(vertexShader, "gl_Position"))
|
|
, m_fragColorVar (findShaderOutputByLocation(fragmentShader, 0))
|
|
, m_execCtx (m_sampler2DMap, m_samplerCubeMap)
|
|
{
|
|
TCU_CHECK_INTERNAL(m_positionVar && m_positionVar->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT && m_positionVar->getType().getNumElements() == 4);
|
|
TCU_CHECK_INTERNAL(m_fragColorVar && m_fragColorVar->getType().getBaseType() == rsg::VariableType::TYPE_FLOAT && m_fragColorVar->getType().getNumElements() == 4);
|
|
|
|
// Build list of vertex outputs.
|
|
for (vector<rsg::ShaderInput*>::const_iterator fragInIter = fragmentShader.getInputs().begin(); fragInIter != fragmentShader.getInputs().end(); ++fragInIter)
|
|
{
|
|
const rsg::ShaderInput* fragInput = *fragInIter;
|
|
const rsg::Variable* vertexOutput = findShaderOutputByName(vertexShader, fragInput->getVariable()->getName());
|
|
|
|
TCU_CHECK_INTERNAL(vertexOutput);
|
|
m_vertexOutputs.push_back(vertexOutput);
|
|
}
|
|
}
|
|
|
|
void RandomShaderProgram::refreshUniforms (void) const
|
|
{
|
|
DE_ASSERT(m_numUnifiedUniforms == (int)m_uniforms.size());
|
|
|
|
for (int uniformNdx = 0; uniformNdx < m_numUnifiedUniforms; uniformNdx++)
|
|
{
|
|
const rsg::Variable* uniformVar = m_unifiedUniforms[uniformNdx]->getVariable();
|
|
const rsg::VariableType& uniformType = uniformVar->getType();
|
|
const sglr::UniformSlot& uniformSlot = m_uniforms[uniformNdx];
|
|
|
|
m_execCtx.getValue(uniformVar) = rsg::ConstValueAccess(uniformType, (const rsg::Scalar*)&uniformSlot.value).value();
|
|
}
|
|
}
|
|
|
|
void RandomShaderProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
|
|
{
|
|
// \todo [2013-12-13 pyry] Do only when necessary.
|
|
refreshUniforms();
|
|
|
|
int packetOffset = 0;
|
|
|
|
while (packetOffset < numPackets)
|
|
{
|
|
const int numToExecute = de::min(numPackets-packetOffset, (int)rsg::EXEC_VEC_WIDTH);
|
|
|
|
// Fetch attributes.
|
|
for (int attribNdx = 0; attribNdx < (int)m_vertexShader.getInputs().size(); ++attribNdx)
|
|
{
|
|
const rsg::Variable* attribVar = m_vertexShader.getInputs()[attribNdx]->getVariable();
|
|
const rsg::VariableType& attribType = attribVar->getType();
|
|
const int numComponents = attribType.getNumElements();
|
|
rsg::ExecValueAccess access = m_execCtx.getValue(attribVar);
|
|
|
|
DE_ASSERT(attribType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
|
|
|
|
for (int ndx = 0; ndx < numToExecute; ndx++)
|
|
{
|
|
const int packetNdx = ndx+packetOffset;
|
|
const rr::VertexPacket* packet = packets[packetNdx];
|
|
const tcu::Vec4 attribValue = rr::readVertexAttribFloat(inputs[attribNdx], packet->instanceNdx, packet->vertexNdx);
|
|
|
|
access.component(0).asFloat(ndx) = attribValue[0];
|
|
if (numComponents >= 2) access.component(1).asFloat(ndx) = attribValue[1];
|
|
if (numComponents >= 3) access.component(2).asFloat(ndx) = attribValue[2];
|
|
if (numComponents >= 4) access.component(3).asFloat(ndx) = attribValue[3];
|
|
}
|
|
}
|
|
|
|
m_vertexShader.execute(m_execCtx);
|
|
|
|
// Store position
|
|
{
|
|
const rsg::ExecConstValueAccess access = m_execCtx.getValue(m_positionVar);
|
|
|
|
for (int ndx = 0; ndx < numToExecute; ndx++)
|
|
{
|
|
const int packetNdx = ndx+packetOffset;
|
|
rr::VertexPacket* packet = packets[packetNdx];
|
|
|
|
packet->position[0] = access.component(0).asFloat(ndx);
|
|
packet->position[1] = access.component(1).asFloat(ndx);
|
|
packet->position[2] = access.component(2).asFloat(ndx);
|
|
packet->position[3] = access.component(3).asFloat(ndx);
|
|
}
|
|
}
|
|
|
|
// Other varyings
|
|
for (int varNdx = 0; varNdx < (int)m_vertexOutputs.size(); varNdx++)
|
|
{
|
|
const rsg::Variable* var = m_vertexOutputs[varNdx];
|
|
const rsg::VariableType& varType = var->getType();
|
|
const int numComponents = varType.getNumElements();
|
|
const rsg::ExecConstValueAccess access = m_execCtx.getValue(var);
|
|
|
|
DE_ASSERT(varType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
|
|
|
|
for (int ndx = 0; ndx < numToExecute; ndx++)
|
|
{
|
|
const int packetNdx = ndx+packetOffset;
|
|
rr::VertexPacket* const packet = packets[packetNdx];
|
|
float* const dst = packet->outputs[varNdx].getAccess<float>();
|
|
|
|
dst[0] = access.component(0).asFloat(ndx);
|
|
if (numComponents >= 2) dst[1] = access.component(1).asFloat(ndx);
|
|
if (numComponents >= 3) dst[2] = access.component(2).asFloat(ndx);
|
|
if (numComponents >= 4) dst[3] = access.component(3).asFloat(ndx);
|
|
}
|
|
}
|
|
|
|
packetOffset += numToExecute;
|
|
}
|
|
}
|
|
|
|
void RandomShaderProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
|
|
{
|
|
const rsg::ExecConstValueAccess fragColorAccess = m_execCtx.getValue(m_fragColorVar);
|
|
int packetOffset = 0;
|
|
|
|
DE_STATIC_ASSERT(rsg::EXEC_VEC_WIDTH % rr::NUM_FRAGMENTS_PER_PACKET == 0);
|
|
|
|
while (packetOffset < numPackets)
|
|
{
|
|
const int numPacketsToExecute = de::min(numPackets-packetOffset, (int)rsg::EXEC_VEC_WIDTH / (int)rr::NUM_FRAGMENTS_PER_PACKET);
|
|
|
|
// Interpolate varyings.
|
|
for (int varNdx = 0; varNdx < (int)m_fragmentShader.getInputs().size(); ++varNdx)
|
|
{
|
|
const rsg::Variable* var = m_fragmentShader.getInputs()[varNdx]->getVariable();
|
|
const rsg::VariableType& varType = var->getType();
|
|
const int numComponents = varType.getNumElements();
|
|
rsg::ExecValueAccess access = m_execCtx.getValue(var);
|
|
|
|
DE_ASSERT(varType.isFloatOrVec() && de::inRange(numComponents, 1, 4));
|
|
|
|
for (int packetNdx = 0; packetNdx < numPacketsToExecute; packetNdx++)
|
|
{
|
|
const rr::FragmentPacket& packet = packets[packetOffset+packetNdx];
|
|
|
|
for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++)
|
|
{
|
|
const tcu::Vec4 varValue = rr::readVarying<float>(packet, context, varNdx, fragNdx);
|
|
const int dstNdx = packetNdx*rr::NUM_FRAGMENTS_PER_PACKET + fragNdx;
|
|
|
|
access.component(0).asFloat(dstNdx) = varValue[0];
|
|
if (numComponents >= 2) access.component(1).asFloat(dstNdx) = varValue[1];
|
|
if (numComponents >= 3) access.component(2).asFloat(dstNdx) = varValue[2];
|
|
if (numComponents >= 4) access.component(3).asFloat(dstNdx) = varValue[3];
|
|
}
|
|
}
|
|
}
|
|
|
|
m_fragmentShader.execute(m_execCtx);
|
|
|
|
// Store color
|
|
for (int packetNdx = 0; packetNdx < numPacketsToExecute; packetNdx++)
|
|
{
|
|
for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; fragNdx++)
|
|
{
|
|
const int srcNdx = packetNdx*rr::NUM_FRAGMENTS_PER_PACKET + fragNdx;
|
|
const tcu::Vec4 color (fragColorAccess.component(0).asFloat(srcNdx),
|
|
fragColorAccess.component(1).asFloat(srcNdx),
|
|
fragColorAccess.component(2).asFloat(srcNdx),
|
|
fragColorAccess.component(3).asFloat(srcNdx));
|
|
|
|
rr::writeFragmentOutput(context, packetOffset+packetNdx, fragNdx, 0, color);
|
|
}
|
|
}
|
|
|
|
packetOffset += numPacketsToExecute;
|
|
}
|
|
}
|
|
|
|
} // gls
|
|
} // deqp
|