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 @@ ...@@ -17,6 +17,7 @@
#include "main.h" #include "main.h"
#include "Buffer.h" #include "Buffer.h"
#include "Shader.h" #include "Shader.h"
#include "TransformFeedback.h"
#include "utilities.h" #include "utilities.h"
#include "common/debug.h" #include "common/debug.h"
#include "Shader/PixelShader.hpp" #include "Shader/PixelShader.hpp"
...@@ -1182,6 +1183,90 @@ namespace es2 ...@@ -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() bool Program::linkVaryings()
{ {
for(glsl::VaryingList::iterator input = fragmentShader->varyings.begin(); input != fragmentShader->varyings.end(); ++input) for(glsl::VaryingList::iterator input = fragmentShader->varyings.begin(); input != fragmentShader->varyings.end(); ++input)
......
...@@ -171,6 +171,7 @@ namespace es2 ...@@ -171,6 +171,7 @@ namespace es2
void dirtyAllUniforms(); void dirtyAllUniforms();
void applyUniforms(); void applyUniforms();
void applyUniformBuffers(BufferBinding* uniformBuffers); void applyUniformBuffers(BufferBinding* uniformBuffers);
void applyTransformFeedback(TransformFeedback* transformFeedback);
void link(); void link();
bool isLinked() const; bool isLinked() const;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
namespace es2 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; mGenericBuffer = NULL;
} }
...@@ -60,6 +60,19 @@ int TransformFeedback::getSize(GLuint index) const ...@@ -60,6 +60,19 @@ int TransformFeedback::getSize(GLuint index) const
return mBuffer[index].getSize(); return mBuffer[index].getSize();
} }
void TransformFeedback::addVertexOffset(int count)
{
if(isActive() && !isPaused())
{
mVertexOffset += count;
}
}
int TransformFeedback::vertexOffset() const
{
return mVertexOffset;
}
bool TransformFeedback::isActive() const bool TransformFeedback::isActive() const
{ {
return mActive; return mActive;
...@@ -84,6 +97,7 @@ void TransformFeedback::end() ...@@ -84,6 +97,7 @@ void TransformFeedback::end()
{ {
mActive = false; mActive = false;
mPaused = false; mPaused = false;
mVertexOffset = 0;
} }
void TransformFeedback::setPaused(bool paused) void TransformFeedback::setPaused(bool paused)
......
...@@ -27,10 +27,11 @@ namespace es2 ...@@ -27,10 +27,11 @@ namespace es2
class TransformFeedback : public gl::NamedObject class TransformFeedback : public gl::NamedObject
{ {
public: public:
// FIXME: Change this when implementing transform feedback
TransformFeedback(GLuint name); TransformFeedback(GLuint name);
~TransformFeedback(); ~TransformFeedback();
BufferBinding* getBuffers() { return mBuffer; }
Buffer* getGenericBuffer() const; Buffer* getGenericBuffer() const;
Buffer* getBuffer(GLuint index) const; Buffer* getBuffer(GLuint index) const;
GLuint getGenericBufferName() const; GLuint getGenericBufferName() const;
...@@ -40,6 +41,7 @@ public: ...@@ -40,6 +41,7 @@ public:
bool isActive() const; bool isActive() const;
bool isPaused() const; bool isPaused() const;
GLenum primitiveMode() const; GLenum primitiveMode() const;
int vertexOffset() const;
void setGenericBuffer(Buffer* buffer); void setGenericBuffer(Buffer* buffer);
void setBuffer(GLuint index, Buffer* buffer); void setBuffer(GLuint index, Buffer* buffer);
...@@ -48,6 +50,7 @@ public: ...@@ -48,6 +50,7 @@ public:
void begin(GLenum primitiveMode); void begin(GLenum primitiveMode);
void end(); void end();
void setPaused(bool paused); void setPaused(bool paused);
void addVertexOffset(int count);
private: private:
gl::BindingPointer<Buffer> mGenericBuffer; gl::BindingPointer<Buffer> mGenericBuffer;
...@@ -56,6 +59,7 @@ private: ...@@ -56,6 +59,7 @@ private:
bool mActive; bool mActive;
bool mPaused; bool mPaused;
GLenum mPrimitiveMode; 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