You're breathtaking!
This commit is contained in:
167
Source/Engine/GraphicsDevice/OpenGL/VAOCache.cpp
Normal file
167
Source/Engine/GraphicsDevice/OpenGL/VAOCache.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "VAOCache.h"
|
||||
|
||||
#if GRAPHICS_API_OPENGL
|
||||
|
||||
#include "TextureOGL.h"
|
||||
#include "BufferOGL.h"
|
||||
#include "RenderToolsOGL.h"
|
||||
#include "Shaders/GPUShaderProgramOGL.h"
|
||||
|
||||
VAOCache::VAOCache()
|
||||
: Table(2048)
|
||||
{
|
||||
}
|
||||
|
||||
VAOCache::~VAOCache()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
GLuint VAOCache::GetVAO(GPUShaderProgramVSOGL* vs, BufferOGL* indexBuffer, uint32 streamsCount, StreamData streams[])
|
||||
{
|
||||
Key key(vs, indexBuffer, streamsCount, streams);
|
||||
GLuint vao;
|
||||
|
||||
if (!Table.TryGet(key, vao))
|
||||
{
|
||||
// Create new VAO
|
||||
glGenVertexArrays(1, &vao);
|
||||
VALIDATE_OPENGL_RESULT();
|
||||
|
||||
// Bind VAO
|
||||
glBindVertexArray(vao);
|
||||
VALIDATE_OPENGL_RESULT();
|
||||
|
||||
// Initialize VAO
|
||||
for (int32 i = 0; i < vs->Layout.Count(); i++)
|
||||
{
|
||||
auto& item = vs->Layout[i];
|
||||
|
||||
auto bufferSlot = item.BufferSlot;
|
||||
if (bufferSlot >= streamsCount)
|
||||
{
|
||||
LOG(Error, "Incorrect input buffer slot");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& stream = streams[bufferSlot];
|
||||
ASSERT(stream.Buffer != nullptr && stream.Buffer->BufferId != 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, stream.Buffer->BufferId);
|
||||
VALIDATE_OPENGL_RESULT();
|
||||
|
||||
GLvoid* DataStartOffset = reinterpret_cast<GLvoid*>(static_cast<size_t>(stream.Offset + item.RelativeOffset));
|
||||
if (item.IsInteger)
|
||||
glVertexAttribIPointer(i, item.TypeCount, item.GlType, stream.Stride, DataStartOffset);
|
||||
else
|
||||
glVertexAttribPointer(i, item.TypeCount, item.GlType, item.Normalized, stream.Stride, DataStartOffset);
|
||||
VALIDATE_OPENGL_RESULT();
|
||||
|
||||
glVertexAttribDivisor(i, item.InstanceDataStepRate);
|
||||
VALIDATE_OPENGL_RESULT();
|
||||
|
||||
glEnableVertexAttribArray(i);
|
||||
VALIDATE_OPENGL_RESULT();
|
||||
}
|
||||
if (indexBuffer)
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer->BufferId);
|
||||
}
|
||||
|
||||
// Register in cache
|
||||
Table.Add(key, vao);
|
||||
}
|
||||
|
||||
return vao;
|
||||
}
|
||||
|
||||
void VAOCache::OnObjectRelease(GPUShaderProgramVSOGL* obj)
|
||||
{
|
||||
for (auto i = Table.Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
if (i->Key.HasReference(obj))
|
||||
{
|
||||
GLuint fbo = i->Value;
|
||||
glDeleteVertexArrays(1, &fbo);
|
||||
Table.Remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VAOCache::OnObjectRelease(BufferOGL* obj)
|
||||
{
|
||||
for (auto i = Table.Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
if (i->Key.HasReference(obj))
|
||||
{
|
||||
GLuint fbo = i->Value;
|
||||
glDeleteVertexArrays(1, &fbo);
|
||||
Table.Remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VAOCache::Dispose()
|
||||
{
|
||||
for (auto i = Table.Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
GLuint fbo = i->Value;
|
||||
glDeleteVertexArrays(1, &fbo);
|
||||
}
|
||||
Table.Clear();
|
||||
}
|
||||
|
||||
VAOCache::Key::Key(GPUShaderProgramVSOGL* vs, BufferOGL* indexBuffer, uint32 streamsCount, StreamData streams[])
|
||||
{
|
||||
VS = vs;
|
||||
IndexBuffer = indexBuffer;
|
||||
StreamsCount = streamsCount;
|
||||
|
||||
Hash = streamsCount * 371;
|
||||
HashCombinePointer(Hash, vs);
|
||||
HashCombinePointer(Hash, indexBuffer);
|
||||
|
||||
for (int32 i = 0; i < streamsCount; i++)
|
||||
{
|
||||
Streams[i] = streams[i];
|
||||
HashCombinePointer(Hash, streams[i].Buffer);
|
||||
HashCombine(Hash, streams[i].Offset);
|
||||
HashCombine(Hash, streams[i].Stride);
|
||||
}
|
||||
}
|
||||
|
||||
bool VAOCache::Key::HasReference(GPUShaderProgramVSOGL* obj)
|
||||
{
|
||||
return obj == VS;
|
||||
}
|
||||
|
||||
bool VAOCache::Key::HasReference(BufferOGL* obj)
|
||||
{
|
||||
for (int32 i = 0; i < ARRAY_COUNT(Streams); i++)
|
||||
{
|
||||
if (Streams[i].Buffer == obj)
|
||||
return true;
|
||||
}
|
||||
return IndexBuffer == obj;
|
||||
}
|
||||
|
||||
bool VAOCache::Key::operator==(const Key & other) const
|
||||
{
|
||||
if (Hash != 0 && other.Hash != 0 && Hash != other.Hash)
|
||||
return false;
|
||||
|
||||
if (StreamsCount != other.StreamsCount || IndexBuffer != other.IndexBuffer)
|
||||
return false;
|
||||
|
||||
for (int32 rt = 0; rt < StreamsCount; rt++)
|
||||
{
|
||||
if (Streams[rt] != other.Streams[rt])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user