gl::Error StateManager11::updateCurrentValueAttribs(const gl::State &state, VertexDataManager *vertexDataManager) { const auto &activeAttribsMask = state.getProgram()->getActiveAttribLocationsMask(); const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs); const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes(); for (auto attribIndex : angle::IterateBitSet(dirtyActiveAttribs)) { if (vertexAttributes[attribIndex].enabled) continue; mDirtyCurrentValueAttribs.reset(attribIndex); const auto ¤tValue = state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)); auto currentValueAttrib = &mCurrentValueAttribs[attribIndex]; currentValueAttrib->currentValueType = currentValue.Type; currentValueAttrib->attribute = &vertexAttributes[attribIndex]; gl::Error error = vertexDataManager->storeCurrentValue(currentValue, currentValueAttrib, static_cast<size_t>(attribIndex)); if (error.isError()) { return error; } } return gl::Error(GL_NO_ERROR); }
gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, std::vector<TranslatedAttribute> *translatedAttribs, GLsizei instances) { if (!mStreamingBuffer) { return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); } // Compute active enabled and active disable attributes, for speed. // TODO(jmadill): don't recompute if there was no state change const gl::VertexArray *vertexArray = state.getVertexArray(); const gl::Program *program = state.getProgram(); const auto &vertexAttributes = vertexArray->getVertexAttributes(); mActiveEnabledAttributes.clear(); mActiveDisabledAttributes.clear(); translatedAttribs->clear(); for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) { if (program->isAttribLocationActive(attribIndex)) { // Resize automatically puts in empty attribs translatedAttribs->resize(attribIndex + 1); TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex]; // Record the attribute now translated->active = true; translated->attribute = &vertexAttributes[attribIndex]; translated->currentValueType = state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)).Type; translated->divisor = vertexAttributes[attribIndex].divisor; if (vertexAttributes[attribIndex].enabled) { mActiveEnabledAttributes.push_back(translated); } else { mActiveDisabledAttributes.push_back(attribIndex); } } } // Reserve the required space in the buffers for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { gl::Error error = reserveSpaceForAttrib(*activeAttrib, count, instances); if (error.isError()) { return error; } } // Perform the vertex data translations for (TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { gl::Error error = storeAttribute(activeAttrib, start, count, instances); if (error.isError()) { hintUnmapAllResources(vertexAttributes); return error; } } for (size_t attribIndex : mActiveDisabledAttributes) { if (mCurrentValueCache[attribIndex].buffer == nullptr) { mCurrentValueCache[attribIndex].buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); } gl::Error error = storeCurrentValue( state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)), &(*translatedAttribs)[attribIndex], &mCurrentValueCache[attribIndex]); if (error.isError()) { hintUnmapAllResources(vertexAttributes); return error; } } // Commit all the static vertex buffers. This fixes them in size/contents, and forces ANGLE // to use a new static buffer (or recreate the static buffers) next time for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) { const gl::VertexAttribute &attrib = vertexAttributes[attribIndex]; gl::Buffer *buffer = attrib.buffer.get(); BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer(attrib) : nullptr; if (staticBuffer) { staticBuffer->commit(); } } // Hint to unmap all the resources hintUnmapAllResources(vertexAttributes); for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { gl::Buffer *buffer = activeAttrib->attribute->buffer.get(); if (buffer) { BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); size_t typeSize = ComputeVertexAttributeTypeSize(*activeAttrib->attribute); bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize)); } } return gl::Error(GL_NO_ERROR); }
gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, std::vector<TranslatedAttribute> *translatedAttribs, GLsizei instances) { ASSERT(mStreamingBuffer); const gl::VertexArray *vertexArray = state.getVertexArray(); const auto &vertexAttributes = vertexArray->getVertexAttributes(); mDynamicAttribsMaskCache.reset(); const gl::Program *program = state.getProgram(); translatedAttribs->clear(); for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) { // Skip attrib locations the program doesn't use. if (!program->isAttribLocationActive(attribIndex)) continue; const auto &attrib = vertexAttributes[attribIndex]; // Resize automatically puts in empty attribs translatedAttribs->resize(attribIndex + 1); TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex]; auto currentValueData = state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)); // Record the attribute now translated->active = true; translated->attribute = &attrib; translated->currentValueType = currentValueData.Type; translated->divisor = attrib.divisor; switch (ClassifyAttributeStorage(attrib)) { case VertexStorageType::STATIC: { // Store static attribute. gl::Error error = StoreStaticAttrib(translated, start, count, instances); if (error.isError()) { return error; } break; } case VertexStorageType::DYNAMIC: // Dynamic attributes must be handled together. mDynamicAttribsMaskCache.set(attribIndex); break; case VertexStorageType::DIRECT: // Update translated data for direct attributes. StoreDirectAttrib(translated, start); break; case VertexStorageType::CURRENT_VALUE: { gl::Error error = storeCurrentValue(currentValueData, translated, attribIndex); if (error.isError()) { return error; } break; } default: UNREACHABLE(); break; } } if (mDynamicAttribsMaskCache.none()) { gl::Error(GL_NO_ERROR); } return storeDynamicAttribs(translatedAttribs, mDynamicAttribsMaskCache, start, count, instances); }
void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) { // TODO(jmadill): Investigate only syncing vertex state for active attributes for (auto dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits)) { switch (dirtyBit) { case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: setScissorTestEnabled(state.isScissorTestEnabled()); break; case gl::State::DIRTY_BIT_SCISSOR: setScissor(state.getScissor()); break; case gl::State::DIRTY_BIT_VIEWPORT: setViewport(state.getViewport()); break; case gl::State::DIRTY_BIT_DEPTH_RANGE: setDepthRange(state.getNearPlane(), state.getFarPlane()); break; case gl::State::DIRTY_BIT_BLEND_ENABLED: setBlendEnabled(state.isBlendEnabled()); break; case gl::State::DIRTY_BIT_BLEND_COLOR: setBlendColor(state.getBlendColor()); break; case gl::State::DIRTY_BIT_BLEND_FUNCS: { const auto &blendState = state.getBlendState(); setBlendFuncs(blendState.sourceBlendRGB, blendState.destBlendRGB, blendState.sourceBlendAlpha, blendState.destBlendAlpha); break; } case gl::State::DIRTY_BIT_BLEND_EQUATIONS: { const auto &blendState = state.getBlendState(); setBlendEquations(blendState.blendEquationRGB, blendState.blendEquationAlpha); break; } case gl::State::DIRTY_BIT_COLOR_MASK: { const auto &blendState = state.getBlendState(); setColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, blendState.colorMaskBlue, blendState.colorMaskAlpha); break; } case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled()); break; case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED: setSampleCoverageEnabled(state.isSampleCoverageEnabled()); break; case gl::State::DIRTY_BIT_SAMPLE_COVERAGE: setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert()); break; case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: setDepthTestEnabled(state.isDepthTestEnabled()); break; case gl::State::DIRTY_BIT_DEPTH_FUNC: setDepthFunc(state.getDepthStencilState().depthFunc); break; case gl::State::DIRTY_BIT_DEPTH_MASK: setDepthMask(state.getDepthStencilState().depthMask); break; case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: setStencilTestEnabled(state.isStencilTestEnabled()); break; case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: { const auto &depthStencilState = state.getDepthStencilState(); setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(), depthStencilState.stencilMask); break; } case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: { const auto &depthStencilState = state.getDepthStencilState(); setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(), depthStencilState.stencilBackMask); break; } case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: { const auto &depthStencilState = state.getDepthStencilState(); setStencilFrontOps(depthStencilState.stencilFail, depthStencilState.stencilPassDepthFail, depthStencilState.stencilPassDepthPass); break; } case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: { const auto &depthStencilState = state.getDepthStencilState(); setStencilBackOps(depthStencilState.stencilBackFail, depthStencilState.stencilBackPassDepthFail, depthStencilState.stencilBackPassDepthPass); break; } case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask); break; case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask); break; case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: setCullFaceEnabled(state.isCullFaceEnabled()); break; case gl::State::DIRTY_BIT_CULL_FACE: setCullFace(state.getRasterizerState().cullMode); break; case gl::State::DIRTY_BIT_FRONT_FACE: setFrontFace(state.getRasterizerState().frontFace); break; case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled()); break; case gl::State::DIRTY_BIT_POLYGON_OFFSET: { const auto &rasterizerState = state.getRasterizerState(); setPolygonOffset(rasterizerState.polygonOffsetFactor, rasterizerState.polygonOffsetUnits); break; } case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED: setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled()); break; case gl::State::DIRTY_BIT_LINE_WIDTH: setLineWidth(state.getLineWidth()); break; case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED: setPrimitiveRestartEnabled(state.isPrimitiveRestartEnabled()); break; case gl::State::DIRTY_BIT_CLEAR_COLOR: setClearColor(state.getColorClearValue()); break; case gl::State::DIRTY_BIT_CLEAR_DEPTH: setClearDepth(state.getDepthClearValue()); break; case gl::State::DIRTY_BIT_CLEAR_STENCIL: setClearStencil(state.getStencilClearValue()); break; case gl::State::DIRTY_BIT_UNPACK_ALIGNMENT: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_PACK_ALIGNMENT: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_PACK_REVERSE_ROW_ORDER: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_PACK_ROW_LENGTH: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_PACK_SKIP_ROWS: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_PACK_SKIP_PIXELS: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_DITHER_ENABLED: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_GENERATE_MIPMAP_HINT: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_SHADER_DERIVATIVE_HINT: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_OBJECT: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_OBJECT: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_VERTEX_ARRAY_OBJECT: state.getVertexArray()->syncImplState(); break; case gl::State::DIRTY_BIT_PROGRAM_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_PROGRAM_OBJECT: // TODO(jmadill): implement this break; default: { ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 && dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX); size_t attribIndex = static_cast<size_t>(dirtyBit) - gl::State::DIRTY_BIT_CURRENT_VALUE_0; setAttributeCurrentData(attribIndex, state.getVertexAttribCurrentValue( static_cast<unsigned int>(attribIndex))); break; } } mLocalDirtyBits.reset(); } }
gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) { if (!mStreamingBuffer) { return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); } const gl::VertexArray *vertexArray = state.getVertexArray(); const std::vector<gl::VertexAttribute> &vertexAttributes = vertexArray->getVertexAttributes(); // Invalidate static buffers that don't contain matching attributes for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) { translated[attributeIndex].active = (state.getProgram()->getSemanticIndex(attributeIndex) != -1); if (translated[attributeIndex].active && vertexAttributes[attributeIndex].enabled) { prepareStaticBufferForAttribute(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex)); } } // Reserve the required space in the buffers for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { if (translated[i].active && vertexAttributes[i].enabled) { gl::Error error = reserveSpaceForAttrib(vertexAttributes[i], state.getVertexAttribCurrentValue(i), count, instances); if (error.isError()) { return error; } } } // Perform the vertex data translations for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { const gl::VertexAttribute &curAttrib = vertexAttributes[i]; if (translated[i].active) { if (curAttrib.enabled) { gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], start, count, instances); if (error.isError()) { hintUnmapAllResources(vertexAttributes); return error; } } else { if (!mCurrentValueBuffer[i]) { mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); } gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], &mCurrentValue[i], &mCurrentValueOffsets[i], mCurrentValueBuffer[i]); if (error.isError()) { hintUnmapAllResources(vertexAttributes); return error; } } } } // Hint to unmap all the resources hintUnmapAllResources(vertexAttributes); for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { const gl::VertexAttribute &curAttrib = vertexAttributes[i]; if (translated[i].active && curAttrib.enabled) { gl::Buffer *buffer = curAttrib.buffer.get(); if (buffer) { BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); bufferImpl->promoteStaticVertexUsageForAttrib(curAttrib, count * ComputeVertexAttributeTypeSize(curAttrib)); } } } return gl::Error(GL_NO_ERROR); }