| 75 | } |
| 76 | |
| 77 | struct GpuBufferImpl { |
| 78 | GpuBufferImpl(const void * data, const uintptr_t sizeBytes, const Bitfield usage) |
| 79 | : _sizeBytes(sizeBytes) { |
| 80 | _CreateBuffer(_buffer, data, sizeBytes, usage); |
| 81 | } |
| 82 | |
| 83 | ~GpuBufferImpl() { |
| 84 | if (ApplicationThread::Instance()->CurrentIsApplicationThread()) { |
| 85 | glDeleteBuffers(1, &_buffer); |
| 86 | } |
| 87 | else { |
| 88 | auto buffer = _buffer; |
| 89 | ApplicationThread::Instance()->Queue([buffer]() { GLuint buf = buffer; glDeleteBuffers(1, &buf); }); |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | void EnableAttribute(int32_t attribute, |
| 94 | int32_t sizePerElem, |
| 95 | GpuStorageType storage, |
| 96 | bool normalized, |
| 97 | uint32_t stride, |
| 98 | uint32_t offset, |
| 99 | uint32_t divisor = 0) { |
| 100 | |
| 101 | // If we exceed OpenGL's max of 4, we need to calculate a new stride that we |
| 102 | // can use in the loop below |
| 103 | if (sizePerElem > 4) { |
| 104 | // Ex: for a 4x4 float matrix this will be 64 (16 * sizeof(float)) |
| 105 | const uint32_t totalSizeBytes = _CalculateSizeBytes(sizePerElem, storage); |
| 106 | stride = stride + totalSizeBytes; |
| 107 | } |
| 108 | |
| 109 | const auto enable = [this, attribute, sizePerElem, storage, normalized, stride, offset, divisor]() { |
| 110 | // OpenGL caps each attrib to 4 elements, so if we have one that's larger |
| 111 | // then we need treat it as multiple attribs |
| 112 | for (int32_t i = 0, elem = 0; elem < sizePerElem; ++i, elem += 4) { |
| 113 | const int32_t pos = attribute + i; |
| 114 | const int32_t elemSize = (sizePerElem - elem) > 4 ? 4 : (sizePerElem - elem); |
| 115 | const uint32_t totalSizeBytes = _CalculateSizeBytes(elemSize, storage); |
| 116 | glEnableVertexAttribArray(pos); |
| 117 | glVertexAttribPointer( |
| 118 | pos, |
| 119 | elemSize, |
| 120 | _ConvertStorageType(storage), |
| 121 | normalized ? GL_TRUE : GL_FALSE, |
| 122 | stride, // Offset from one element to the next |
| 123 | (void *)(offset + i * totalSizeBytes) // one-time offset before reading first element |
| 124 | ); |
| 125 | |
| 126 | // If 0, data increments by 1 for each vertex |
| 127 | glVertexAttribDivisor(pos, divisor); |
| 128 | } |
| 129 | }; |
| 130 | |
| 131 | _enableAttributes.push_back(enable); |
| 132 | } |
| 133 | |
| 134 | void Bind(const GpuBindingPoint point) const { |
nothing calls this directly
no outgoing calls
no test coverage detected