Cogs.Core
RenderMesh.cpp
1#include "RenderMesh.h"
2#include "RenderEffect.h"
3
4#include "Rendering/IGraphicsDevice.h"
5#include "Rendering/IContext.h"
6#include "Rendering/IBuffers.h"
7#include "Rendering/ICapabilities.h"
8#include "Rendering/VertexFormat.h"
9
10#include "Resources/VertexFormats.h"
11#include "Resources/Mesh.h"
12#include "Resources/Buffer.h"
13
14#include "Foundation/Logging/Logger.h"
15
16#include "Renderer.h"
17
18namespace
19{
20 using namespace Cogs::Core;
21
22 Cogs::Logging::Log logger = Cogs::Logging::getLogger("RenderMesh");
23
24
25 Cogs::BufferHandle updateStream(Cogs::IBuffers* buffers, Mesh* mesh, Cogs::Core::DataStream& stream, Cogs::BindFlags::EBindFlags bindflags, bool doSet)
26 {
27 // Note: Here the stream more or less owns the buffer, this won't work
28 // if buffers are shared across streams. But then we need something else
29 // like a RenderBufferManager to manage lifetime. But for now, it looks
30 // like there is always only one stream per buffer
31
33
34 if (stream.buffer->isResident()) {
35 Cogs::BufferHandle handle = Cogs::BufferHandle(intptr_t(buffer->getAttachedResource()));
36 assert(handle && "Resident buffer without handle");
37 buffers->releaseBuffer(handle);
38 buffer->unsetFlag(ResourceFlags::Resident);
39 buffer->attachResource(nullptr);
40 }
41
42 if (doSet && !buffer->empty()) {
43 Cogs::BufferHandle handle = buffers->loadBuffer((const uint8_t*)buffer->data(), buffer->size(), Cogs::Usage::Static, Cogs::AccessMode::None, bindflags, stream.stride);
44 if (Cogs::StringView name = mesh->getName(); !name.empty()) {
45 buffers->annotate(handle, name);
46 }
47 else {
48 buffers->annotate(handle, "RenderMesh");
49 }
50 buffer->setResident();
51 buffer->attachResource((RenderResource*)(intptr_t)handle.handle);
52 return handle;
53 }
54
56 }
57
58}
59
60
61Cogs::Core::RenderMesh::RenderMesh()
62{
63 type = RenderResourceType::RenderMesh;
64
65 for (size_t i = 0; i < MeshStreamsLayout::maxStreams; ++i) {
67 vertexBuffers[i] = VertexBufferHandle::NoHandle;
68 vertexOffsets[i] = 0;
69 vertexStrides[i] = 0;
70 }
71}
72
73
74Cogs::VertexArrayObjectHandle Cogs::Core::RenderMesh::getVertexArrayObject(IGraphicsDevice* device, const RenderEffect* renderEffect) const
75{
76 Cogs::IBuffers* buffers = device->getBuffers();
77 if (!renderEffect || !HandleIsValid(renderEffect->effectHandle)) {
78 LOG_ERROR(logger, "Trying to get a VAO for an invalid effect");
80 }
81
82 RenderResource::Id effectId = renderEffect->getIdentity();
83 if (auto it = vaos.find(effectId); it != vaos.end()) {
84 return it->second;
85 }
86
87 std::array<const VertexFormat*, MeshStreamsLayout::maxStreams> formats;
88 for (size_t i = 0; i < streamsLayout.numStreams; i++) {
89 formats[i] = Cogs::VertexFormats::getVertexFormat(streamsLayout.vertexFormats[i]);
90 }
91
92 Cogs::VertexArrayObjectHandle vao = buffers->loadVertexArrayObject(renderEffect->effectHandle,
93 vertexBuffers, streamsLayout.numStreams, formats.data(), vertexStrides, vertexOffsets,
94 indexBuffer, indexStride);
95 vaos.insert(std::make_pair(effectId, vao));
96 return vao;
97}
98
99
100Cogs::Core::ActivationResult Cogs::Core::RenderMesh::update(Mesh * mesh, IGraphicsDevice * device, RenderResources * /*resources*/)
101{
102 bool changed = false;
103 auto buffers = device->getBuffers();
104 bool supportUint32Indices = device->getCapabilities()->getDeviceCapabilities().UnsignedIntIndexes;
105
107 streamsLayout.numStreams = 0;
108 numVertexes = mesh->getCount();
109
110 for (size_t i = 0; i < VertexDataType::LastVertexType; ++i) {
112
113 if (mesh->hasStream(type)) {
114 Cogs::Core::DataStream& stream = mesh->getStream(type);
116 if (mesh->streamsUpdated & uint16_t(1 << i)) {
117 handle = updateStream(buffers, mesh, stream, Cogs::BindFlags::VertexBuffer, true);
118 }
119 else if (stream.buffer->isResident()) {
120 handle = Cogs::BufferHandle(intptr_t(stream.buffer->getAttachedResource()));
121 }
122
123 if (HandleIsValid(handle)) {
124 vertexBuffers[streamsLayout.numStreams] = handle;
125 vertexOffsets[streamsLayout.numStreams] = stream.offset;
126 vertexStrides[streamsLayout.numStreams] = stream.stride;
127 streamsLayout.vertexFormats[streamsLayout.numStreams] = stream.format;
128 streamsLayout.numStreams++;
129 }
130 }
131 }
132
133 mesh->streamsUpdated = 0;
135 changed = true;
136 }
137
139 if (mesh->hasStream(VertexDataType::Indexes)) {
140 DataStream& stream = mesh->getStream(VertexDataType::Indexes);
141 if (!supportUint32Indices && indexStride == 4) {
142 LOG_ERROR_ONCE(logger, "Mesh indices are uint32 which is not supported by graphics device");
143 indexBuffer = IndexBufferHandle::NoHandle;
144 }
145 else {
146 indexBuffer = updateStream(buffers, mesh, stream, Cogs::BindFlags::IndexBuffer, mesh->isIndexed());
147 indexOffset = stream.offset;
148 indexStride = stream.stride;
149 }
150 }
151 else {
152 indexBuffer = IndexBufferHandle::NoHandle;
153 }
155 changed = true;
156 }
157
158 if (changed) {
159 streamsLayout.updateHash();
160
161 for (auto& it : vaos) {
162 buffers->releaseVertexArrayObject(it.second);
163 }
164 vaos.clear();
165 }
166
167 numVertexes = mesh->getCount();
168
169 setActive();
170
172}
173
174void Cogs::Core::RenderMesh::release(Renderer * renderer)
175{
176 Cogs::IBuffers* buffers = renderer->getDevice()->getBuffers();
177
178 for (auto& it : vaos) {
179 buffers->releaseVertexArrayObject(it.second);
180 }
181 vaos.clear();
182
183 setReleased();
184}
Contains render resources used by the renderer.
Core renderer system.
Definition: Renderer.h:28
IGraphicsDevice * getDevice() override
Get the graphics device used by the renderer.
Definition: Renderer.h:45
Represents a graphics device used to manage graphics resources and issue drawing commands.
virtual ICapabilities * getCapabilities()=0
Get a pointer to the capability management interface used to query the graphics device capability fla...
virtual IBuffers * getBuffers()=0
Get a pointer to the buffer management interface.
Log implementation class.
Definition: LogManager.h:139
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:24
constexpr bool empty() const noexcept
Check if the string is empty.
Definition: StringView.h:122
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
ActivationResult
Defines results for resource activation.
Definition: ResourceBase.h:14
@ Success
Resource activated successfully.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
@ None
The buffer can not be either read from or written to by the CPU after creation.
Definition: Flags.h:46
EBindFlags
Bind flags enumeration.
Definition: Flags.h:64
@ VertexBuffer
The buffer can be bound as input to the vertex shader stage as a vertex buffer.
Definition: Flags.h:68
@ IndexBuffer
The buffer can be bound as input to the vertex shader stage as an index buffer.
Definition: Flags.h:70
bool empty() const
If the buffer is empty. Note that an empty buffer may still have reserved storage.
Definition: Buffer.h:65
size_t size() const
Size of the buffer in bytes.
Definition: Buffer.h:62
void * data()
Get a pointer to the buffer data.
Definition: Buffer.h:74
Contains a stream of data used by Mesh resources.
Definition: Mesh.h:80
uint32_t offset
Byte offset from the start of the buffer.
Definition: Mesh.h:102
VertexFormatHandle format
A pointer to the format describing the contents of the byte buffer.
Definition: Mesh.h:99
uint32_t stride
Element stride.
Definition: Mesh.h:105
Cogs::Core::ResourceBufferHandle buffer
Data buffer.
Definition: Mesh.h:96
@ StreamsChanged
One or more of the data streams in the mesh changed.
Definition: Mesh.h:59
@ IndexesChanged
The index data of the mesh changed.
Definition: Mesh.h:61
VertexFormatHandle vertexFormats[maxStreams]
static constexpr size_t maxStreams
Meshes contain streams of vertex data in addition to index data and options defining geometry used fo...
Definition: Mesh.h:265
bool isIndexed() const
If the mesh uses indexed geometry.
Definition: Mesh.h:953
constexpr bool isMeshFlagSet(MeshFlags::EMeshFlags flag) const
Check if the given mesh flag(s) is set.
Definition: Mesh.h:683
bool hasStream(VertexDataType::EVertexDataType type) const
Check if the Mesh has a DataStream for the given type.
Definition: Mesh.h:933
void unsetMeshFlag(MeshFlags::EMeshFlags flag)
Unset the given mesh flag.
Definition: Mesh.h:671
DataStream & getStream(const VertexDataType::EVertexDataType dataType)
Get the stream corresponding to the given dataType.
Definition: Mesh.cpp:85
uint32_t getCount() const
Get the vertex count of the mesh.
Definition: Mesh.h:1012
StringView getName() const
Get the name of the resource.
Definition: ResourceBase.h:307
void unsetFlag(ResourceFlags flag)
Unset the given flag.
Definition: ResourceBase.h:236
void attachResource(RenderResource *attachment)
Attach the given GPU resource to the resource.
Definition: ResourceBase.h:261
RenderResource * getAttachedResource() const
Get the attached resource.
Definition: ResourceBase.h:275
EVertexDataType
Contains data types.
Definition: Mesh.h:26
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:77
handle_type handle
Internal resource handle.
Definition: Common.h:74
Provides buffer management functionality.
Definition: IBuffers.h:13
virtual VertexArrayObjectHandle loadVertexArrayObject(const EffectHandle effectHandle, const VertexBufferHandle *vertexBufferHandles, const size_t vertexBufferCount, const VertexFormat *const *vertexFormats=nullptr, const uint32_t *vertexBufferStrides=nullptr, const uint32_t *vertexBufferOffsets=nullptr, const IndexBufferHandle indexBufferHandle=IndexBufferHandle::NoHandle, uint32_t indexBufferStride=0)=0
Create a vertex array object that encapsulates binding of a set of vertex buffers and an optional ind...
virtual void annotate(BufferHandle handle, const StringView &name)
Associate a name with an object for use in graphics debugging.
Definition: IBuffers.h:17
virtual BufferHandle loadBuffer(const void *data, const size_t size, Usage::EUsage usage, uint32_t accessMode, uint32_t bindFlags, uint32_t stride=0)=0
Loads a new buffer using the given data to populate the buffer.
virtual void releaseBuffer(BufferHandle bufferHandle)=0
Releases the buffer with the given bufferHandle.
virtual void releaseVertexArrayObject(VertexArrayObjectHandle vertexArrayObjectHandle)=0
Releases the vertex array object with the given handle.
virtual const GraphicsDeviceCapabilities & getDeviceCapabilities() const
Gets the device capabilities in a structure.
@ Static
Buffer will be loaded once and used to render many subsequent frames without any updates.
Definition: Flags.h:28