void GLCpuPosInstancedArraysBench::setupSingleVbo(const GrGLInterface* gl, const SkMatrix* viewMatrices) { // Constants for our various shader programs Vertex vertices[kVerticesPerTri * kNumTri]; for (uint32_t i = 0; i < kNumTri; i++) { Vertex* v = &vertices[i * kVerticesPerTri]; v[0].fPositions.set(-1.0f, -1.0f); v[1].fPositions.set( 1.0f, -1.0f); v[2].fPositions.set( 1.0f, 1.0f); SkPoint* position = reinterpret_cast<SkPoint*>(v); viewMatrices[i].mapPointsWithStride(position, sizeof(Vertex), kVerticesPerTri); // set colors float color = i == kNumTri - 1 ? 1.0f : 0.0f; for (uint32_t j = 0; j < kVerticesPerTri; j++) { uint32_t offset = 0; v->fColors[offset++] = color; v->fColors[offset++] = 0.0f; v->fColors[offset++] = 0.0f; v++; } } GrGLuint vbo; // setup VBO GR_GL_CALL(gl, GenBuffers(1, &vbo)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, vbo)); GR_GL_CALL(gl, EnableVertexAttribArray(0)); GR_GL_CALL(gl, EnableVertexAttribArray(1)); GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Vertex), (GrGLvoid*)0)); GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Vertex), (GrGLvoid*)(sizeof(SkPoint)))); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(vertices), vertices, GR_GL_STATIC_DRAW)); fBuffers.push_back(vbo); }
void GrGpuGLShaders::onResetContext() { INHERITED::onResetContext(); fHWGeometryState.fVertexOffset = ~0; // Third party GL code may have left vertex attributes enabled. Some GL // implementations (osmesa) may read vetex attributes that are not required // by the current shader. Therefore, we have to ensure that only the // attributes we require for the current draw are enabled or we may cause an // invalid read. // Disable all vertex layout bits so that next flush will assume all // optional vertex attributes are disabled. fHWGeometryState.fVertexLayout = 0; // We always use the this attribute and assume it is always enabled. int posAttrIdx = GrGLProgram::PositionAttributeIdx(); GL_CALL(EnableVertexAttribArray(posAttrIdx)); // Disable all other vertex attributes. for (int va = 0; va < fMaxVertexAttribs; ++va) { if (va != posAttrIdx) { GL_CALL(DisableVertexAttribArray(va)); } } fHWProgramID = 0; }
void GL3CharacterRenderer::buildHead() { GL(GenVertexArrays(1, &headVao)); GL(GenBuffers(1, &headVbo)); GL(BindVertexArray(headVao)); GL(BindBuffer(GL_ARRAY_BUFFER, headVbo)); GL(VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 40, 0)); GL(VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 40, (void *) 12)); GL(VertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 40, (void *) 24)); GL(EnableVertexAttribArray(0)); GL(EnableVertexAttribArray(1)); GL(EnableVertexAttribArray(2)); GL(BindVertexArray(0)); VertexData vertexData[36]; int vertexIndices[6] = {0, 1, 2, 0, 2, 3}; int index = 0; for (int d = 0; d < 6; d++) { vec3f normal(0.0); normal[d % 3] = DIRS[d][d % 3]; vec3f vertices[4]; for (int i = 0; i < 4; i++) { vertices[i] = vec3f( (DIR_QUAD_CORNER_CYCLES_3D[d][i][0] - 0.5f) * HEAD_SIZE[0], (DIR_QUAD_CORNER_CYCLES_3D[d][i][1] - 0.5f) * HEAD_SIZE[1], (DIR_QUAD_CORNER_CYCLES_3D[d][i][2] - 0.5f) * HEAD_SIZE[2] + HEAD_Z_OFFSET ) * (1.0f / RESOLUTION); } for (int j = 0; j < 6; j++) { vertexData[index].xyz[0] = vertices[vertexIndices[j]][0]; vertexData[index].xyz[1] = vertices[vertexIndices[j]][1]; vertexData[index].xyz[2] = vertices[vertexIndices[j]][2]; vertexData[index].nxyz[0] = normal[0]; vertexData[index].nxyz[1] = normal[1]; vertexData[index].nxyz[2] = normal[2]; vertexData[index].rgba[0] = CHARACTER_COLOR[0]; vertexData[index].rgba[1] = CHARACTER_COLOR[1]; vertexData[index].rgba[2] = CHARACTER_COLOR[2]; vertexData[index].rgba[3] = 1.0f; index++; } } GL(BufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW)); GL(BindBuffer(GL_ARRAY_BUFFER, 0)); }
void GLInstancedRendering::flushInstanceAttribs(int baseInstance) { SkASSERT(fVertexArrayID); this->glGpu()->bindVertexArray(fVertexArrayID); SkASSERT(fInstanceBuffer); if (fInstanceAttribsBufferUniqueId != fInstanceBuffer->getUniqueID() || fInstanceAttribsBaseInstance != baseInstance) { Instance* offsetInBuffer = (Instance*) nullptr + baseInstance; this->glGpu()->bindBuffer(kVertex_GrBufferType, fInstanceBuffer.get()); // Info attrib. GL_CALL(EnableVertexAttribArray((int)Attrib::kInstanceInfo)); GL_CALL(VertexAttribIPointer((int)Attrib::kInstanceInfo, 1, GR_GL_UNSIGNED_INT, sizeof(Instance), &offsetInBuffer->fInfo)); GL_CALL(VertexAttribDivisor((int)Attrib::kInstanceInfo, 1)); // Shape matrix attrib. GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixX)); GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixY)); GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixX, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[0])); GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixY, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[3])); GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixX, 1)); GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixY, 1)); // Color attrib. GL_CALL(EnableVertexAttribArray((int)Attrib::kColor)); GL_CALL(VertexAttribPointer((int)Attrib::kColor, 4, GR_GL_UNSIGNED_BYTE, GR_GL_TRUE, sizeof(Instance), &offsetInBuffer->fColor)); GL_CALL(VertexAttribDivisor((int)Attrib::kColor, 1)); // Local rect attrib. GL_CALL(EnableVertexAttribArray((int)Attrib::kLocalRect)); GL_CALL(VertexAttribPointer((int)Attrib::kLocalRect, 4, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Instance), &offsetInBuffer->fLocalRect)); GL_CALL(VertexAttribDivisor((int)Attrib::kLocalRect, 1)); fInstanceAttribsBufferUniqueId = fInstanceBuffer->getUniqueID(); fInstanceAttribsBaseInstance = baseInstance; } }
void GrGpuGLShaders::resetContextHelper() { fHWGeometryState.fVertexLayout = 0; fHWGeometryState.fVertexOffset = ~0; GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION)); for (int t = 0; t < kMaxTexCoords; ++t) { GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t))); } GR_GL(EnableVertexAttribArray(POS_ATTR_LOCATION)); fHWProgramID = 0; }
void GLCpuPosInstancedArraysBench::setupInstanceVbo(const GrGLInterface* gl, const SkMatrix* viewMatrices) { // We draw all of the instances at a single place because we aren't allowed to have per vertex // per instance attributes SkPoint positions[kVerticesPerTri]; positions[0].set(-1.0f, -1.0f); positions[1].set( 1.0f, -1.0f); positions[2].set( 1.0f, 1.0f); viewMatrices[0].mapPointsWithStride(positions, sizeof(SkPoint), kVerticesPerTri); // setup colors so we can detect we are actually drawing instances(the last triangle will be // a different color) GrGLfloat colors[kVerticesPerTri * kNumTri]; for (uint32_t i = 0; i < kNumTri; i++) { // set colors uint32_t offset = i * kVerticesPerTri; float color = i == kNumTri - 1 ? 1.0f : 0.0f; colors[offset++] = color; colors[offset++] = 0.0f; colors[offset++] = 0.0f; } GrGLuint posVBO; // setup position VBO GR_GL_CALL(gl, GenBuffers(1, &posVBO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, posVBO)); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(positions), positions, GR_GL_STATIC_DRAW)); GR_GL_CALL(gl, EnableVertexAttribArray(0)); GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, 2 * sizeof(GrGLfloat), (GrGLvoid*)0)); // setup color VBO GrGLuint instanceVBO; GR_GL_CALL(gl, GenBuffers(1, &instanceVBO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, instanceVBO)); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(colors), colors, GR_GL_STATIC_DRAW)); GR_GL_CALL(gl, EnableVertexAttribArray(1)); GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, 3 * sizeof(GrGLfloat), (GrGLvoid*)0)); GR_GL_CALL(gl, VertexAttribDivisor(1, 1)); fBuffers.push_back(posVBO); fBuffers.push_back(instanceVBO); }
void GLCpuPosInstancedArraysBench::setupDoubleVbo(const GrGLInterface* gl, const SkMatrix* viewMatrices) { // Constants for our various shader programs SkPoint positions[kVerticesPerTri * kNumTri]; GrGLfloat colors[kVerticesPerTri * kNumTri * 3]; for (uint32_t i = 0; i < kNumTri; i++) { SkPoint* position = &positions[i * kVerticesPerTri]; position[0].set(-1.0f, -1.0f); position[1].set( 1.0f, -1.0f); position[2].set( 1.0f, 1.0f); viewMatrices[i].mapPointsWithStride(position, sizeof(SkPoint), kVerticesPerTri); // set colors float color = i == kNumTri - 1 ? 1.0f : 0.0f; uint32_t offset = i * kVerticesPerTri * 3; for (uint32_t j = 0; j < kVerticesPerTri; j++) { colors[offset++] = color; colors[offset++] = 0.0f; colors[offset++] = 0.0f; } } GrGLuint posVBO, colorVBO; // setup position VBO GR_GL_CALL(gl, GenBuffers(1, &posVBO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, posVBO)); GR_GL_CALL(gl, EnableVertexAttribArray(0)); GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, 2 * sizeof(GrGLfloat), (GrGLvoid*)0)); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(positions), positions, GR_GL_STATIC_DRAW)); // setup color VBO GR_GL_CALL(gl, GenBuffers(1, &colorVBO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, colorVBO)); GR_GL_CALL(gl, EnableVertexAttribArray(1)); GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, 3 * sizeof(GrGLfloat), (GrGLvoid*)0)); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(colors), colors, GR_GL_STATIC_DRAW)); fBuffers.push_back(posVBO); fBuffers.push_back(colorVBO); }
int rb_vertex_attrib_array (struct rb_vertex_array* array, struct rb_buffer* buffer, int count, const struct rb_buffer_attrib* attrib) { intptr_t offset = 0; int i = 0; int err = 0; if(!array || !buffer || !attrib || count < 0 || buffer->target != GL_ARRAY_BUFFER) goto error; OGL(BindVertexArray(array->name)); OGL(BindBuffer(buffer->target, buffer->name)); for(i=0; i < count; ++i) { if(attrib[i].type == RB_UNKNOWN_TYPE) { OGL(BindBuffer (buffer->target, array->ctxt->state_cache.buffer_binding[buffer->binding])); goto error; } offset = attrib[i].offset; OGL(EnableVertexAttribArray(attrib[i].index)); OGL(VertexAttribPointer (attrib[i].index, ogl3_attrib_nb_components(attrib[i].type), GL_FLOAT, GL_FALSE, attrib[i].stride, (void*)offset)); } OGL(BindVertexArray(array->ctxt->state_cache.vertex_array_binding)); OGL(BindBuffer (buffer->target, array->ctxt->state_cache.buffer_binding[buffer->binding])); exit: return err; error: err = -1; goto exit; }
void GLVec4ScalarBench::setupSingleVbo(const GrGLInterface* gl, const SkMatrix* viewMatrices) { // triangles drawn will alternate between the top-right half of the screen and the bottom-left // half of the screen Vertex vertices[kVerticesPerTri * kNumTriPerDraw]; for (uint32_t i = 0; i < kNumTriPerDraw; i++) { Vertex* v = &vertices[i * kVerticesPerTri]; if (i % 2 == 0) { v[0].fPositions.set(-1.0f, -1.0f); v[1].fPositions.set( 1.0f, -1.0f); v[2].fPositions.set( 1.0f, 1.0f); } else { v[0].fPositions.set(-1.0f, -1.0f); v[1].fPositions.set( 1.0f, 1.0f); v[2].fPositions.set( -1.0f, 1.0f); } SkPoint* position = reinterpret_cast<SkPoint*>(v); viewMatrices[i].mapPointsWithStride(position, sizeof(Vertex), kVerticesPerTri); GrGLfloat color[3] = {1.0f, 0.0f, 1.0f}; for (uint32_t j = 0; j < kVerticesPerTri; j++) { v->fColors[0] = color[0]; v->fColors[1] = color[1]; v->fColors[2] = color[2]; v++; } } GR_GL_CALL(gl, GenBuffers(1, &fVboId)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, fVboId)); GR_GL_CALL(gl, EnableVertexAttribArray(0)); GR_GL_CALL(gl, EnableVertexAttribArray(1)); GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Vertex), (GrGLvoid*)0)); GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Vertex), (GrGLvoid*)(sizeof(SkPoint)))); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(vertices), vertices, GR_GL_STATIC_DRAW)); }
void GrGLAttribArrayState::set(const GrGpuGL* gpu, int index, GrGLVertexBuffer* buffer, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, GrGLvoid* offset) { SkASSERT(index >= 0 && index < fAttribArrayStates.count()); AttribArrayState* array = &fAttribArrayStates[index]; if (!array->fEnableIsValid || !array->fEnabled) { GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index)); array->fEnableIsValid = true; array->fEnabled = true; } if (!array->fAttribPointerIsValid || array->fVertexBufferID != buffer->bufferID() || array->fSize != size || array->fNormalized != normalized || array->fStride != stride || array->fOffset != offset) { buffer->bind(); GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, size, type, normalized, stride, offset)); array->fAttribPointerIsValid = true; array->fVertexBufferID = buffer->bufferID(); array->fSize = size; array->fNormalized = normalized; array->fStride = stride; array->fOffset = offset; } }
void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { int newColorOffset; int newCoverageOffset; int newTexCoordOffsets[GrDrawState::kMaxTexCoords]; int newEdgeOffset; GrVertexLayout currLayout = this->getVertexLayout(); GrGLsizei newStride = GrDrawState::VertexSizeAndOffsetsByIdx(currLayout, newTexCoordOffsets, &newColorOffset, &newCoverageOffset, &newEdgeOffset); int oldColorOffset; int oldCoverageOffset; int oldTexCoordOffsets[GrDrawState::kMaxTexCoords]; int oldEdgeOffset; GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout, oldTexCoordOffsets, &oldColorOffset, &oldCoverageOffset, &oldEdgeOffset); int extraVertexOffset; this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset); GrGLenum scalarType; bool texCoordNorm; if (currLayout & GrDrawState::kTextFormat_VertexLayoutBit) { scalarType = TEXT_COORDS_GL_TYPE; texCoordNorm = SkToBool(TEXT_COORDS_ARE_NORMALIZED); } else { scalarType = GR_GL_FLOAT; texCoordNorm = false; } size_t vertexOffset = (info.startVertex() + extraVertexOffset) * newStride; // all the Pointers must be set if any of these are true bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || vertexOffset != fHWGeometryState.fVertexOffset || newStride != oldStride; // position and tex coord offsets change if above conditions are true // or the type/normalization changed based on text vs nontext type coords. bool posAndTexChange = allOffsetsChange || (((TEXT_COORDS_GL_TYPE != GR_GL_FLOAT) || TEXT_COORDS_ARE_NORMALIZED) && (GrDrawState::kTextFormat_VertexLayoutBit & (fHWGeometryState.fVertexLayout ^ currLayout))); if (posAndTexChange) { int idx = GrGLProgram::PositionAttributeIdx(); GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride, (GrGLvoid*)vertexOffset)); fHWGeometryState.fVertexOffset = vertexOffset; } for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { if (newTexCoordOffsets[t] > 0) { GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); int idx = GrGLProgram::TexCoordAttributeIdx(t); if (oldTexCoordOffsets[t] <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, newStride, texCoordOffset)); } else if (posAndTexChange || newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, newStride, texCoordOffset)); } } else if (oldTexCoordOffsets[t] > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t))); } } if (newColorOffset > 0) { GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); int idx = GrGLProgram::ColorAttributeIdx(); if (oldColorOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } else if (allOffsetsChange || newColorOffset != oldColorOffset) { GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } } else if (oldColorOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx())); } if (newCoverageOffset > 0) { GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset); int idx = GrGLProgram::CoverageAttributeIdx(); if (oldCoverageOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, coverageOffset)); } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) { GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, coverageOffset)); } } else if (oldCoverageOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx())); } if (newEdgeOffset > 0) { GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset); int idx = GrGLProgram::EdgeAttributeIdx(); if (oldEdgeOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 4, scalarType, false, newStride, edgeOffset)); } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) { GL_CALL(VertexAttribPointer(idx, 4, scalarType, false, newStride, edgeOffset)); } } else if (oldEdgeOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx())); } fHWGeometryState.fVertexLayout = currLayout; fHWGeometryState.fArrayPtrsDirty = false; }
void cShaderProgram::EnableVertexAttribArray( const std::string& Name ) { EnableVertexAttribArray( AttributeLocation( Name ) ); }
GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index) { CONTEXT_EXEC(EnableVertexAttribArray(index)); }
void GrGpuGLShaders::setupGeometry(int* startVertex, int* startIndex, int vertexCount, int indexCount) { int newColorOffset; int newTexCoordOffsets[kMaxTexCoords]; GrGLsizei newStride = VertexSizeAndOffsetsByIdx(fGeometrySrc.fVertexLayout, newTexCoordOffsets, &newColorOffset); int oldColorOffset; int oldTexCoordOffsets[kMaxTexCoords]; GrGLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout, oldTexCoordOffsets, &oldColorOffset); bool indexed = NULL != startIndex; int extraVertexOffset; int extraIndexOffset; setBuffers(indexed, &extraVertexOffset, &extraIndexOffset); GrGLenum scalarType; bool texCoordNorm; if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) { scalarType = GrGLTextType; texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED; } else { scalarType = GrGLType; texCoordNorm = false; } size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride; *startVertex = 0; if (indexed) { *startIndex += extraIndexOffset; } // all the Pointers must be set if any of these are true bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || vertexOffset != fHWGeometryState.fVertexOffset || newStride != oldStride; // position and tex coord offsets change if above conditions are true // or the type/normalization changed based on text vs nontext type coords. bool posAndTexChange = allOffsetsChange || (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) && (kTextFormat_VertexLayoutBit & (fHWGeometryState.fVertexLayout ^ fGeometrySrc.fVertexLayout))); if (posAndTexChange) { GR_GL(VertexAttribPointer(POS_ATTR_LOCATION, 2, scalarType, false, newStride, (GrGLvoid*)vertexOffset)); fHWGeometryState.fVertexOffset = vertexOffset; } for (int t = 0; t < kMaxTexCoords; ++t) { if (newTexCoordOffsets[t] > 0) { GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); if (oldTexCoordOffsets[t] <= 0) { GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION(t))); GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType, texCoordNorm, newStride, texCoordOffset)); } else if (posAndTexChange || newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType, texCoordNorm, newStride, texCoordOffset)); } } else if (oldTexCoordOffsets[t] > 0) { GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t))); } } if (newColorOffset > 0) { GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); if (oldColorOffset <= 0) { GR_GL(EnableVertexAttribArray(COL_ATTR_LOCATION)); GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } else if (allOffsetsChange || newColorOffset != oldColorOffset) { GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } } else if (oldColorOffset > 0) { GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION)); } fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout; fHWGeometryState.fArrayPtrsDirty = false; }
void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) { // Count what there is to draw. BatchList::Iter iter; iter.init(this->trackedBatches(), BatchList::Iter::kHead_IterStart); int numGLInstances = 0; int numGLDrawCmds = 0; while (Batch* b = iter.get()) { GLBatch* batch = static_cast<GLBatch*>(b); iter.next(); numGLInstances += batch->fNumDraws; numGLDrawCmds += batch->numGLCommands(); } if (!numGLDrawCmds) { return; } SkASSERT(numGLInstances); // Lazily create a vertex array object. if (!fVertexArrayID) { GL_CALL(GenVertexArrays(1, &fVertexArrayID)); if (!fVertexArrayID) { return; } this->glGpu()->bindVertexArray(fVertexArrayID); // Attach our index buffer to the vertex array. SkASSERT(!this->indexBuffer()->isCPUBacked()); GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, static_cast<const GrGLBuffer*>(this->indexBuffer())->bufferID())); // Set up the non-instanced attribs. this->glGpu()->bindBuffer(kVertex_GrBufferType, this->vertexBuffer()); GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeCoords)); GL_CALL(VertexAttribPointer((int)Attrib::kShapeCoords, 2, GR_GL_FLOAT, GR_GL_FALSE, sizeof(ShapeVertex), (void*) offsetof(ShapeVertex, fX))); GL_CALL(EnableVertexAttribArray((int)Attrib::kVertexAttrs)); GL_CALL(VertexAttribIPointer((int)Attrib::kVertexAttrs, 1, GR_GL_INT, sizeof(ShapeVertex), (void*) offsetof(ShapeVertex, fAttrs))); SkASSERT(SK_InvalidUniqueID == fInstanceAttribsBufferUniqueId); } // Create and map instance and draw-indirect buffers. SkASSERT(!fInstanceBuffer); fInstanceBuffer.reset( rp->createBuffer(sizeof(Instance) * numGLInstances, kVertex_GrBufferType, kDynamic_GrAccessPattern, GrResourceProvider::kNoPendingIO_Flag | GrResourceProvider::kRequireGpuMemory_Flag)); if (!fInstanceBuffer) { return; } SkASSERT(!fDrawIndirectBuffer); fDrawIndirectBuffer.reset( rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds, kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern, GrResourceProvider::kNoPendingIO_Flag | GrResourceProvider::kRequireGpuMemory_Flag)); if (!fDrawIndirectBuffer) { return; } Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map()); int glInstancesIdx = 0; auto* glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndirectBuffer->map()); int glDrawCmdsIdx = 0; bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport(); if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) { fGLDrawCmdsInfo.reset(numGLDrawCmds); } // Generate the instance and draw-indirect buffer contents based on the tracked batches. iter.init(this->trackedBatches(), BatchList::Iter::kHead_IterStart); while (Batch* b = iter.get()) { GLBatch* batch = static_cast<GLBatch*>(b); iter.next(); batch->fEmulatedBaseInstance = baseInstanceSupport ? 0 : glInstancesIdx; batch->fGLDrawCmdsIdx = glDrawCmdsIdx; const Batch::Draw* draw = batch->fHeadDraw; SkASSERT(draw); do { int instanceCount = 0; IndexRange geometry = draw->fGeometry; SkASSERT(!geometry.isEmpty()); do { glMappedInstances[glInstancesIdx + instanceCount++] = draw->fInstance; draw = draw->fNext; } while (draw && draw->fGeometry == geometry); GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx]; glCmd.fCount = geometry.fCount; glCmd.fInstanceCount = instanceCount; glCmd.fFirstIndex = geometry.fStart; glCmd.fBaseVertex = 0; glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0; if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) { fGLDrawCmdsInfo[glDrawCmdsIdx].fInstanceCount = instanceCount; #if GR_GL_LOG_INSTANCED_BATCHES fGLDrawCmdsInfo[glDrawCmdsIdx].fGeometry = geometry; #endif } glInstancesIdx += instanceCount; ++glDrawCmdsIdx; } while (draw); } SkASSERT(glDrawCmdsIdx == numGLDrawCmds); fDrawIndirectBuffer->unmap(); SkASSERT(glInstancesIdx == numGLInstances); fInstanceBuffer->unmap(); }
void GLGpuPosInstancedArraysBench::setup(const GrGLInterface* gl) { setup_framebuffer(gl, kScreenWidth, kScreenHeight); // compile and use shaders GrGLint shaderProgram = compile_shader(gl, gpu_vertex_shader, fragment_shader); // translations int index = 0; GrGLfloat viewMatrices[fNumQuads * fSkMatrixNumCells]; setup_matrices(fNumQuads, [&index, &viewMatrices](const SkMatrix& m) { GrGLGetMatrix<3>(&viewMatrices[index], m); index += fSkMatrixNumCells; }); // Constants for our various shader programs GrGLfloat quad_vertices[] = { // Positions // Colors -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; // update vertex data GrGLuint quadVAO, quadVBO; GR_GL_CALL(gl, GenVertexArrays(1, &quadVAO)); GR_GL_CALL(gl, GenBuffers(1, &quadVBO)); GR_GL_CALL(gl, BindVertexArray(quadVAO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, quadVBO)); GR_GL_CALL(gl, EnableVertexAttribArray(0)); GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, 5 * sizeof(GrGLfloat), (GrGLvoid*)0)); GR_GL_CALL(gl, EnableVertexAttribArray(1)); GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, 5 * sizeof(GrGLfloat), (GrGLvoid*)(2 * sizeof(GrGLfloat)))); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_vertices, GR_GL_STATIC_DRAW)); // Also set instance data GrGLuint instanceVBO; GR_GL_CALL(gl, GenBuffers(1, &instanceVBO)); GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, instanceVBO)); GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(GrGLfloat) * fSkMatrixNumCells * fNumQuads, &viewMatrices[0], GR_GL_STATIC_DRAW)); GR_GL_CALL(gl, EnableVertexAttribArray(2)); GR_GL_CALL(gl, EnableVertexAttribArray(3)); GR_GL_CALL(gl, EnableVertexAttribArray(4)); GR_GL_CALL(gl, VertexAttribPointer(2, 3, GR_GL_FLOAT, GR_GL_FALSE, 9 * sizeof(GrGLfloat), (GrGLvoid*)0)); GR_GL_CALL(gl, VertexAttribPointer(3, 3, GR_GL_FLOAT, GR_GL_FALSE, 9 * sizeof(GrGLfloat), (GrGLvoid*)(3 * sizeof(GrGLfloat)))); GR_GL_CALL(gl, VertexAttribPointer(4, 3, GR_GL_FLOAT, GR_GL_FALSE, 9 * sizeof(GrGLfloat), (GrGLvoid*)(6 * sizeof(GrGLfloat)))); GR_GL_CALL(gl, VertexAttribDivisor(2, 1)); GR_GL_CALL(gl, VertexAttribDivisor(3, 1)); GR_GL_CALL(gl, VertexAttribDivisor(4, 1)); // draw GR_GL_CALL(gl, ClearColor(0.03f, 0.03f, 0.03f, 1.0f)); GR_GL_CALL(gl, Clear(GR_GL_COLOR_BUFFER_BIT)); // set us up to draw GR_GL_CALL(gl, UseProgram(shaderProgram)); GR_GL_CALL(gl, BindVertexArray(quadVAO)); }
void GrGpuGLShaders::setupGeometry(int* startVertex, int* startIndex, int vertexCount, int indexCount) { int newColorOffset; int newCoverageOffset; int newTexCoordOffsets[GrDrawState::kMaxTexCoords]; int newEdgeOffset; GrGLsizei newStride = VertexSizeAndOffsetsByIdx( this->getGeomSrc().fVertexLayout, newTexCoordOffsets, &newColorOffset, &newCoverageOffset, &newEdgeOffset); int oldColorOffset; int oldCoverageOffset; int oldTexCoordOffsets[GrDrawState::kMaxTexCoords]; int oldEdgeOffset; GrGLsizei oldStride = VertexSizeAndOffsetsByIdx( fHWGeometryState.fVertexLayout, oldTexCoordOffsets, &oldColorOffset, &oldCoverageOffset, &oldEdgeOffset); bool indexed = NULL != startIndex; int extraVertexOffset; int extraIndexOffset; this->setBuffers(indexed, &extraVertexOffset, &extraIndexOffset); GrGLenum scalarType; bool texCoordNorm; if (this->getGeomSrc().fVertexLayout & kTextFormat_VertexLayoutBit) { scalarType = GrGLTextType; texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED; } else { scalarType = GrGLType; texCoordNorm = false; } size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride; *startVertex = 0; if (indexed) { *startIndex += extraIndexOffset; } // all the Pointers must be set if any of these are true bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || vertexOffset != fHWGeometryState.fVertexOffset || newStride != oldStride; // position and tex coord offsets change if above conditions are true // or the type/normalization changed based on text vs nontext type coords. bool posAndTexChange = allOffsetsChange || (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) && (kTextFormat_VertexLayoutBit & (fHWGeometryState.fVertexLayout ^ this->getGeomSrc().fVertexLayout))); if (posAndTexChange) { int idx = GrGLProgram::PositionAttributeIdx(); GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride, (GrGLvoid*)vertexOffset)); fHWGeometryState.fVertexOffset = vertexOffset; } for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { if (newTexCoordOffsets[t] > 0) { GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); int idx = GrGLProgram::TexCoordAttributeIdx(t); if (oldTexCoordOffsets[t] <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, newStride, texCoordOffset)); } else if (posAndTexChange || newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, newStride, texCoordOffset)); } } else if (oldTexCoordOffsets[t] > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t))); } } if (newColorOffset > 0) { GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); int idx = GrGLProgram::ColorAttributeIdx(); if (oldColorOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } else if (allOffsetsChange || newColorOffset != oldColorOffset) { GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset)); } } else if (oldColorOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx())); } if (newCoverageOffset > 0) { // bind a single channel, they should all have the same value. GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset); int idx = GrGLProgram::CoverageAttributeIdx(); if (oldCoverageOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 1, GR_GL_UNSIGNED_BYTE, true, newStride, coverageOffset)); } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) { GL_CALL(VertexAttribPointer(idx, 1, GR_GL_UNSIGNED_BYTE, true, newStride, coverageOffset)); } } else if (oldCoverageOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx())); } if (newEdgeOffset > 0) { GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset); int idx = GrGLProgram::EdgeAttributeIdx(); if (oldEdgeOffset <= 0) { GL_CALL(EnableVertexAttribArray(idx)); GL_CALL(VertexAttribPointer(idx, 4, scalarType, false, newStride, edgeOffset)); } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) { GL_CALL(VertexAttribPointer(idx, 4, scalarType, false, newStride, edgeOffset)); } } else if (oldEdgeOffset > 0) { GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx())); } fHWGeometryState.fVertexLayout = this->getGeomSrc().fVertexLayout; fHWGeometryState.fArrayPtrsDirty = false; }