Commit 0704728b by Alexis Hetu Committed by Alexis Hétu

Transform feedback buffer assignment

This cl adds a utility function that assigns the correct buffer for each linked transform feedback variable. All the information about location and size is sent to the VertexProcessor for use during rendering. Change-Id: I942805250804f56805de1fc117024c20976e83a0 Reviewed-on: https://swiftshader-review.googlesource.com/5174Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 2ff2948b
......@@ -17,6 +17,7 @@
#include "main.h"
#include "Buffer.h"
#include "Shader.h"
#include "TransformFeedback.h"
#include "utilities.h"
#include "common/debug.h"
#include "Shader/PixelShader.hpp"
......@@ -1182,6 +1183,90 @@ namespace es2
}
}
void Program::applyTransformFeedback(TransformFeedback* transformFeedback)
{
// Make sure the flags will fit in a 64 bit unsigned int variable
ASSERT(sw::max<int>(MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS) <= 64);
BufferBinding* transformFeedbackBuffers = (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused()) ? transformFeedback->getBuffers() : nullptr;
uint64_t enableTransformFeedback = 0;
if(!transformFeedbackBuffers)
{
for(unsigned int index = 0; index < sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++index)
{
device->VertexProcessor::setTransformFeedbackBuffer(index, nullptr, 0, 0, 0, 0, 0);
}
device->VertexProcessor::enableTransformFeedback(enableTransformFeedback);
return;
}
unsigned int maxVaryings = transformFeedbackLinkedVaryings.size();
switch(transformFeedbackBufferMode)
{
case GL_SEPARATE_ATTRIBS:
{
maxVaryings = sw::min(maxVaryings, (unsigned int)MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
// Attribs go to separate buffers
for(unsigned int index = 0; index < maxVaryings; ++index)
{
int size = transformFeedbackLinkedVaryings[index].size;
int rowCount = VariableRowCount(transformFeedbackLinkedVaryings[index].type);
int colCount = VariableColumnCount(transformFeedbackLinkedVaryings[index].type);
int nbRegs = rowCount > 1 ? colCount * size : size;
int nbComponentsPerReg = rowCount > 1 ? rowCount : colCount;
int componentStride = rowCount * colCount * size;
int baseOffset = transformFeedback->vertexOffset() * componentStride * sizeof(float);
device->VertexProcessor::setTransformFeedbackBuffer(index,
transformFeedbackBuffers[index].get()->getResource(),
transformFeedbackBuffers[index].getOffset() + baseOffset,
transformFeedbackLinkedVaryings[index].reg * 4 + transformFeedbackLinkedVaryings[index].col,
nbRegs, nbComponentsPerReg, componentStride);
enableTransformFeedback |= 1ULL << index;
}
}
break;
case GL_INTERLEAVED_ATTRIBS:
{
// OpenGL ES 3.0.4 spec, section 2.15.2:
// In INTERLEAVED_ATTRIBS mode, the values of one or more output variables
// written by a vertex shader are written, interleaved, into the buffer object
// bound to the first transform feedback binding point (index = 0).
sw::Resource* resource = transformFeedbackBuffers[0].get()->getResource();
int componentStride = totalLinkedVaryingsComponents;
int baseOffset = transformFeedbackBuffers[0].getOffset() + (transformFeedback->vertexOffset() * componentStride * sizeof(float));
maxVaryings = sw::min(maxVaryings, (unsigned int)sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
size_t totalComponents = 0;
for(unsigned int index = 0; index < maxVaryings; ++index)
{
int size = transformFeedbackLinkedVaryings[index].size;
int rowCount = VariableRowCount(transformFeedbackLinkedVaryings[index].type);
int colCount = VariableColumnCount(transformFeedbackLinkedVaryings[index].type);
int nbRegs = rowCount > 1 ? colCount * size : size;
int nbComponentsPerReg = rowCount > 1 ? rowCount : colCount;
device->VertexProcessor::setTransformFeedbackBuffer(index, resource,
baseOffset + (totalComponents * sizeof(float)),
transformFeedbackLinkedVaryings[index].reg * 4 + transformFeedbackLinkedVaryings[index].col,
nbRegs, nbComponentsPerReg, componentStride);
totalComponents += rowCount * colCount * size;
enableTransformFeedback |= 1ULL << index;
}
}
break;
default:
UNREACHABLE(transformFeedbackBufferMode);
break;
}
// Unset all other transform feedback buffers
for(unsigned int index = maxVaryings; index < sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++index)
{
device->VertexProcessor::setTransformFeedbackBuffer(index, nullptr, 0, 0, 0, 0, 0);
}
device->VertexProcessor::enableTransformFeedback(enableTransformFeedback);
}
bool Program::linkVaryings()
{
for(glsl::VaryingList::iterator input = fragmentShader->varyings.begin(); input != fragmentShader->varyings.end(); ++input)
......
......@@ -171,6 +171,7 @@ namespace es2
void dirtyAllUniforms();
void applyUniforms();
void applyUniformBuffers(BufferBinding* uniformBuffers);
void applyTransformFeedback(TransformFeedback* transformFeedback);
void link();
bool isLinked() const;
......
......@@ -16,7 +16,7 @@
namespace es2
{
TransformFeedback::TransformFeedback(GLuint name) : NamedObject(name), mActive(false), mPaused(false)
TransformFeedback::TransformFeedback(GLuint name) : NamedObject(name), mActive(false), mPaused(false), mVertexOffset(0)
{
mGenericBuffer = NULL;
}
......@@ -60,6 +60,19 @@ int TransformFeedback::getSize(GLuint index) const
return mBuffer[index].getSize();
}
void TransformFeedback::addVertexOffset(int count)
{
if(isActive() && !isPaused())
{
mVertexOffset += count;
}
}
int TransformFeedback::vertexOffset() const
{
return mVertexOffset;
}
bool TransformFeedback::isActive() const
{
return mActive;
......@@ -84,6 +97,7 @@ void TransformFeedback::end()
{
mActive = false;
mPaused = false;
mVertexOffset = 0;
}
void TransformFeedback::setPaused(bool paused)
......
......@@ -27,10 +27,11 @@ namespace es2
class TransformFeedback : public gl::NamedObject
{
public:
// FIXME: Change this when implementing transform feedback
TransformFeedback(GLuint name);
~TransformFeedback();
BufferBinding* getBuffers() { return mBuffer; }
Buffer* getGenericBuffer() const;
Buffer* getBuffer(GLuint index) const;
GLuint getGenericBufferName() const;
......@@ -40,6 +41,7 @@ public:
bool isActive() const;
bool isPaused() const;
GLenum primitiveMode() const;
int vertexOffset() const;
void setGenericBuffer(Buffer* buffer);
void setBuffer(GLuint index, Buffer* buffer);
......@@ -48,6 +50,7 @@ public:
void begin(GLenum primitiveMode);
void end();
void setPaused(bool paused);
void addVertexOffset(int count);
private:
gl::BindingPointer<Buffer> mGenericBuffer;
......@@ -56,6 +59,7 @@ private:
bool mActive;
bool mPaused;
GLenum mPrimitiveMode;
int mVertexOffset;
};
}
......
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