Esempio n. 1
0
gl::GLenum DrawExecution::elementType() const
{
    Assert(m_drawImpl.indexBuffer.get(), "No index buffer set");
    Assert(m_drawImpl.indexBuffer->layout.fields().size() == 1u, "Invalid index buffer layout");

    return TypeToGLType(m_drawImpl.indexBuffer->layout.fields()[0].type());
}
Esempio n. 2
0
const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO( IPipelineState *pPSO,
                                                            IBuffer *pIndexBuffer,
                                                            VertexStreamInfo VertexStreams[],
                                                            Uint32 NumVertexStreams,
                                                            GLContextState &GLContextState )
{
    // Lock the cache
    ThreadingTools::LockHelper CacheLock(m_CacheLockFlag);

    IBuffer* VertexBuffers[MaxBufferSlots];
    for (Uint32 s = 0; s < NumVertexStreams; ++s)
        VertexBuffers[s] = nullptr;
    
    // Get layout
    auto *pPSOGL = ValidatedCast<PipelineStateGLImpl>(pPSO);

    const auto &InputLayout = pPSOGL->GetDesc().GraphicsPipeline.InputLayout;
    const LayoutElement *LayoutElems =  InputLayout.LayoutElements;
    Uint32 NumElems = InputLayout.NumElements;
    const Uint32 *TightStrides = pPSOGL->GetTightStrides();
    // Construct the key
    VAOCacheKey Key(pPSO, pIndexBuffer);
    
    {
        auto LayoutIt = LayoutElems;
        for (size_t Elem = 0; Elem < NumElems; ++Elem, ++LayoutIt)
        {
            auto BuffSlot = LayoutIt->BufferSlot;
            if (BuffSlot >= NumVertexStreams)
            {
                UNEXPECTED("Input layout requires more buffers than bound to the pipeline");
                continue;
            }
            if (BuffSlot >= MaxBufferSlots)
            {
                VERIFY(BuffSlot >= MaxBufferSlots, "Incorrect input slot");
                continue;
            }
            auto MaxUsedSlot = std::max(Key.NumUsedSlots, BuffSlot + 1);
            for (Uint32 s = Key.NumUsedSlots; s < MaxUsedSlot; ++s)
                Key.Streams[s] = VAOCacheKey::StreamAttribs{};
            Key.NumUsedSlots = MaxUsedSlot;

            auto &CurrStream = VertexStreams[BuffSlot];
            auto Stride = CurrStream.Stride ? CurrStream.Stride : TightStrides[BuffSlot];
            auto &pCurrBuf = VertexBuffers[BuffSlot];
            auto &CurrStreamKey = Key.Streams[BuffSlot];
            if (pCurrBuf == nullptr)
            {
                pCurrBuf = CurrStream.pBuffer;
                VERIFY(pCurrBuf != nullptr, "No buffer bound to slot ", BuffSlot);

                ValidatedCast<BufferGLImpl>(pCurrBuf)->BufferMemoryBarrier(
                    GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT,// Vertex data sourced from buffer objects after the barrier 
                                                       // will reflect data written by shaders prior to the barrier.
                                                       // The set of buffer objects affected by this bit is derived 
                                                       // from the GL_VERTEX_ARRAY_BUFFER_BINDING bindings
                    GLContextState);

                CurrStreamKey.pBuffer = pCurrBuf;
                CurrStreamKey.Stride = Stride;
                CurrStreamKey.Offset = CurrStream.Offset;
            }
            else
            {
                VERIFY(pCurrBuf == CurrStream.pBuffer, "Buffer no longer exists");
                VERIFY(CurrStreamKey.pBuffer == pCurrBuf, "Unexpected buffer");
                VERIFY(CurrStreamKey.Stride == Stride, "Unexpected buffer stride");
                VERIFY(CurrStreamKey.Offset == CurrStream.Offset, "Unexpected buffer offset");
            }
        }
    }

    if( pIndexBuffer )
    {
        ValidatedCast<BufferGLImpl>(pIndexBuffer)->BufferMemoryBarrier(
            GL_ELEMENT_ARRAY_BARRIER_BIT,// Vertex array indices sourced from buffer objects after the barrier 
                                         // will reflect data written by shaders prior to the barrier.
                                         // The buffer objects affected by this bit are derived from the
                                         // ELEMENT_ARRAY_BUFFER binding.
            GLContextState);
    }

    // Try to find VAO in the map
    auto It = m_Cache.find(Key);
    if( It != m_Cache.end() )
    {
        return It->second;
    }
    else
    {
        // Create new VAO
        GLObjectWrappers::GLVertexArrayObj NewVAO(true);

        // Initialize VAO
        GLContextState.BindVAO( NewVAO );
        auto LayoutIt = LayoutElems;
        for( size_t Elem = 0; Elem < NumElems; ++Elem, ++LayoutIt )
        {
            auto BuffSlot = LayoutIt->BufferSlot;
            if( BuffSlot >= NumVertexStreams || BuffSlot >= MaxBufferSlots )
            {
                UNEXPECTED( "Incorrect input buffer slot" );
                continue;
            }
            // Get buffer through the strong reference. Note that we are not
            // using pointers stored in the key for safety
            auto &CurrStream = VertexStreams[BuffSlot];
            auto Stride = CurrStream.Stride ? CurrStream.Stride : TightStrides[BuffSlot];
            auto *pBuff = VertexBuffers[BuffSlot];
            VERIFY( pBuff != nullptr, "Vertex buffer is null" );
            const BufferGLImpl *pBufferOGL = static_cast<const BufferGLImpl*>( pBuff );

            glBindBuffer(GL_ARRAY_BUFFER, pBufferOGL->m_GlBuffer);
            GLvoid* DataStartOffset = reinterpret_cast<GLvoid*>( static_cast<size_t>( CurrStream.Offset + LayoutIt->RelativeOffset ) );
            auto GlType = TypeToGLType(LayoutIt->ValueType);
            if( !LayoutIt->IsNormalized &&
                (LayoutIt->ValueType == VT_INT8  || 
                 LayoutIt->ValueType == VT_INT16 ||
                 LayoutIt->ValueType == VT_INT32 ||
                 LayoutIt->ValueType == VT_UINT8 || 
                 LayoutIt->ValueType == VT_UINT16||
                 LayoutIt->ValueType == VT_UINT32 ) )
                glVertexAttribIPointer(LayoutIt->InputIndex, LayoutIt->NumComponents, GlType, Stride, DataStartOffset );
            else
                glVertexAttribPointer(LayoutIt->InputIndex, LayoutIt->NumComponents, GlType, LayoutIt->IsNormalized, Stride, DataStartOffset );

            if( LayoutIt->Frequency == LayoutElement::FREQUENCY_PER_INSTANCE )
            {
                // If divisor is zero, then the attribute acts like normal, being indexed by the array or index 
                // buffer. If divisor is non-zero, then the current instance is divided by this divisor, and 
                // the result of that is used to access the attribute array.
                glVertexAttribDivisor(LayoutIt->InputIndex, LayoutIt->InstanceDataStepRate);
            }
	        glEnableVertexAttribArray(LayoutIt->InputIndex);
        }
        if( pIndexBuffer )
        {
            const BufferGLImpl *pIndBufferOGL = static_cast<const BufferGLImpl*>( pIndexBuffer );
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndBufferOGL->m_GlBuffer);
        }
            
        auto NewElems = m_Cache.emplace( std::make_pair(Key, std::move(NewVAO)) );
        // New element must be actually inserted
        VERIFY( NewElems.second, "New element was not inserted into the cache" ); 
        m_PSOToKey.insert( std::make_pair(Key.pPSO, Key) );
        for(Uint32 Slot = 0; Slot < Key.NumUsedSlots; ++Slot)
        {
            auto *pCurrBuff = Key.Streams[Slot].pBuffer;
            if( pCurrBuff )
                m_BuffToKey.insert( std::make_pair(pCurrBuff, Key) );
        }

        return NewElems.first->second;
    }
}
Esempio n. 3
0
void DrawExecution::perform()
{
    m_glStateManager.enableTextureCubeMapSeamless(true);

    // Apply State
    applyDepthState();
    applyBlendState();
    applyCullState();
    applyRasterizerState();
    applyStencilState();
    applyViewport();

    gl::glUseProgram(m_drawImpl.program->glProgramName);

    // Setup texture units
    for (auto b = 0u; b < m_drawImpl.samplers.size(); b++)
    {
        auto & sampler = m_drawImpl.samplers[b];
        auto * texture = sampler.texture;

        Assert(texture, "");

        if (texture->glName == 0)
        {
            texture->allocate();
        }

        gl::glActiveTexture(gl::GL_TEXTURE0 + b);
        gl::glBindTexture(texture->type, texture->glName);

        gl::glTexParameteri(texture->type, gl::GL_TEXTURE_BASE_LEVEL, texture->baseLevel);
        gl::glTexParameteri(texture->type, gl::GL_TEXTURE_MAX_LEVEL, texture->maxLevel);

        gl::glBindSampler(b, sampler.glSampler.name());
        gl::glSamplerParameteri(sampler.glSampler.name(), gl::GL_TEXTURE_MIN_FILTER, (gl::GLint)texture->minFilter);
        gl::glSamplerParameteri(sampler.glSampler.name(), gl::GL_TEXTURE_MAG_FILTER, (gl::GLint)texture->maxFilter);

        gl::glUniform1i(sampler.location, b);
    }

    // Setup RenderTarget / Framebuffer
    Assert(m_drawImpl.framebuffer.m_impl.get(), "");
    m_drawImpl.framebuffer.m_impl->bind(m_glStateManager);

    // Set uniforms
    {
        /*
            TODO
                Port to GLStateManager
        */

        for (auto & uniform : m_drawImpl.uniforms)
        {
            Assert(uniform.isAssigned, "Uniform " + m_drawImpl.program->interface.uniformByLocation(uniform.location)->name() + " not set");
            Assert(uniform.count > 0, "");

            auto count = uniform.count;
            auto * data = uniform.blob.ptr();
            auto location = uniform.location;

            switch (TypeToGLType(uniform.type))
            {
            case gl::GL_INT:
                gl::glUniform1iv(location, count, ((const gl::GLint*)data));
                break;
            case gl::GL_UNSIGNED_INT:
                gl::glUniform1uiv(location, count, ((const gl::GLuint*)data));
                break;
            case gl::GL_INT_VEC2:
            {
                auto idata = (const gl::GLint*)data;
                gl::glUniform2iv(location, count, idata);
                break;
            }
            case gl::GL_FLOAT:
                gl::glUniform1fv(location, count, ((const gl::GLfloat*)data));
                break;
            case gl::GL_FLOAT_VEC2:
            {
                auto fdata = (const gl::GLfloat*)data;
                gl::glUniform2fv(location, count, fdata);
                break;
            }
            case gl::GL_FLOAT_VEC3:
            {
                auto fdata = (const gl::GLfloat*)data;
                gl::glUniform3fv(location, count, fdata);
                break;
            }
            case gl::GL_FLOAT_VEC4:
            {
                auto fdata = (const gl::GLfloat*)data;
                gl::glUniform4fv(location, count, fdata);
                break;
            }
            case gl::GL_FLOAT_MAT4:
                gl::glUniformMatrix4fv(location, count, gl::GL_FALSE, (const gl::GLfloat*)data);
                break;
            default:
                Fail(std::string("Not implemented for type ") + uniform.type.name());
            }
        }
    }

    // Set uniform buffers
    {
        for (auto b = 0; b < m_drawImpl.uniformBuffers.size(); b++)
        {
            auto & binding = m_drawImpl.uniformBuffers[b];

            Assert(binding.engaged(), "UniformBuffer " + m_drawImpl.program->interface.uniformBlocks()[b].name() + " not bound");

            auto & buffer = *binding.get().buffer;
            auto size = buffer.count * buffer.layout.stride();

            Assert(size > binding.get().begin, "begin beyond buffer bounds");

            gl::glUniformBlockBinding(m_drawImpl.program->glProgramName, b, b);
            gl::glBindBufferRange(gl::GL_UNIFORM_BUFFER, b, buffer.glName, binding.get().begin, buffer.layout.stride());
        }
    }

    // Dispatch draw
    if (m_drawImpl.indexBuffer)
    {
        if (!m_drawImpl.instanceBuffers.empty())
        {
            drawElementsInstanced();
        }
        else
        {
            drawElements();
        }
    }
    else
    {
        if (!m_drawImpl.instanceBuffers.empty())
        {
            drawArraysInstanced();
        }
        else
        {
            drawArrays();
        }
    }
}