1#include "RenderTargetsGL20.h"
2#include "TexturesGL20.h"
4#include "Foundation/Logging/Logger.h"
10 bool checkFrameBuffer()
12 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
14 if (status == GL_FRAMEBUFFER_UNDEFINED) {
return false; }
15 else if (status == GL_FRAMEBUFFER_UNSUPPORTED) {
16 LOG_ERROR(logger,
"FBO contains unsupported image formats.");
18 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
19 LOG_ERROR(logger,
"FBO incomplete, missing any image attachments.");
21 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) {
22 LOG_ERROR(logger,
"FBO incomplete, missing complete attachments.");
24 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER) {
25 LOG_ERROR(logger,
"FBO incomplete, draw buffer.");
27 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER) {
28 LOG_ERROR(logger,
"FBO incomplete, read buffer.");
30 }
else if (status == GL_FRAMEBUFFER_UNSUPPORTED) {
31 LOG_ERROR(logger,
"FBO incomplete, unsupported combination of internal formats.");
33 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) {
34 LOG_ERROR(logger,
"FBO incomplete, multisample.");
36 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS) {
37 LOG_ERROR(logger,
"FBO incomplete, layers.");
40 assert(status == GL_FRAMEBUFFER_COMPLETE);
46Cogs::RenderTargetsGL20::~RenderTargetsGL20()
48 if (this->renderTargets.size()) {
49 LOG_WARNING(logger,
"Render targets resources not empty. %zu resources left.", this->renderTargets.size());
51 if (this->depthStencils.size()) {
52 LOG_WARNING(logger,
"Depth stencil target resources not empty. %zu resources left.", this->depthStencils.size());
60 glGenFramebuffers(1, &renderTarget.frameBuffer);
61 glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.frameBuffer);
63 renderTarget.numTextures = numViews;
65 for (
size_t i = 0; i < numViews; ++i) {
67 GLenum target = texture.type;
68 renderTarget.textures[i] = renderTargetViews[i].
texture;
70 if(target == GL_TEXTURE_CUBE_MAP){
71 GLint face = renderTargetViews[i].
layerIndex%6;
72 GLint layer = renderTargetViews[i].
layerIndex/6;
74 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 +
static_cast<GLint
>(i),
75 GL_TEXTURE_CUBE_MAP_POSITIVE_X+face,
76 texture.textureId, renderTargetViews[i].
layerIndex);
77 }
else if(target == GL_TEXTURE_CUBE_MAP_ARRAY || target == GL_TEXTURE_2D_ARRAY) {
78 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 +
static_cast<GLint
>(i),
82 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 +
static_cast<GLint
>(i),
83 target, texture.textureId, renderTargetViews[i].
levelIndex);
87 if (numViews && !checkFrameBuffer()) {
91 glBindFramebuffer(GL_FRAMEBUFFER, 0);
93 return this->renderTargets.addResource(renderTarget);
98 auto & renderTarget = this->renderTargets[renderTargetHandle];
100 glDeleteFramebuffers(1, &renderTarget.frameBuffer);
102 this->renderTargets.removeResource(renderTargetHandle);
108 TextureGL20 & texture = this->textures->textures[renderTarget.textures[0]];
110 GLuint depthRenderBuffer;
111 glGenRenderbuffers(1, &depthRenderBuffer);
112 glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
114 GLenum format = GL_DEPTH_COMPONENT32F;
115 if (texture.numSamples == 1) {
116 glRenderbufferStorage(GL_RENDERBUFFER, format, texture.width, texture.height);
118 glRenderbufferStorageMultisample(GL_RENDERBUFFER, texture.numSamples, format, texture.width, texture.height);
121 glBindRenderbuffer(GL_RENDERBUFFER, 0);
123 glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.frameBuffer);
124 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);
126 if (!checkFrameBuffer()){
130 glBindFramebuffer(GL_FRAMEBUFFER, 0);
134 return this->depthStencils.addResource(depthStencilTarget);
140 if(!HandleIsValid(renderTargetHandle)){
141 renderTargetHandle = createRenderTarget(
nullptr, 0);
144 TextureGL20 & texture = this->textures->textures[textureHandle];
145 GLenum target = texture.type;
147 GLuint frameBuffer = renderTarget.frameBuffer;
149 glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
150 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target, texture.textureId, 0);
152 if (!checkFrameBuffer()){
156 glBindFramebuffer(GL_FRAMEBUFFER, 0);
160 return this->depthStencils.addResource(depthTarget);
166 if(!HandleIsValid(renderTargetHandle)){
167 renderTargetHandle = createRenderTarget(
nullptr, 0);
171 GLenum target = texture.type;
172 GLuint frameBuffer = renderTarget.frameBuffer;
174 glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
176 if(target == GL_TEXTURE_CUBE_MAP){
180 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
181 GL_TEXTURE_CUBE_MAP_POSITIVE_X+face,
182 texture.textureId, depthStencilView.
levelIndex);
184 else if(target == GL_TEXTURE_CUBE_MAP_ARRAY || target == GL_TEXTURE_2D_ARRAY){
185 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texture.textureId,
189 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
190 target, texture.textureId, depthStencilView.
levelIndex);
193 if (!checkFrameBuffer()){
197 glBindFramebuffer(GL_FRAMEBUFFER, 0);
201 return this->depthStencils.addResource(depthTarget);
206 auto & depthStencil = this->depthStencils[depthStencilHandle];
208 if (depthStencil.renderBuffer) {
209 glDeleteRenderbuffers(1, &depthStencil.depthBuffer);
212 this->depthStencils.removeResource(depthStencilHandle);
217 return this->depthStencilStates.addResource(depthStencilState);
222 this->depthStencilStates.removeResource(handle);
227 return this->rasterizerStates.addResource(rasterizerState);
232 this->rasterizerStates.removeResource(handle);
237 return loadBlendState(blendState, blendState);
243 blendState.color = blendStateColor;
244 blendState.alpha = blendStateAlpha;
245 return this->blendStates.addResource(std::move(blendState));
251 this->blendStates.removeResource(handle);
256 std::vector<RenderTargetHandle> rtHandles;
257 for (
auto & rt : renderTargets) {
258 rtHandles.push_back(renderTargets.getHandle(rt));
261 for (
auto & handle : rtHandles) {
262 releaseRenderTarget(handle);
265 std::vector<DepthStencilHandle> dsHandles;
266 for (
auto & ds : depthStencils) {
267 dsHandles.push_back(depthStencils.getHandle(ds));
270 for (
auto & handle : dsHandles) {
271 releaseDepthStencilTarget(handle);
274 this->blendStates.clear();
275 this->rasterizerStates.clear();
276 this->depthStencilStates.clear();
281 if(name.
empty() || !HandleIsValid(handle))
return;
284 auto & renderTarget = this->renderTargets[handle];
285 glObjectLabel(GL_FRAMEBUFFER, renderTarget.frameBuffer,
static_cast<GLsizei
>(name.
size()), name.
data());
293 if(name.
empty() || !HandleIsValid(handle))
return;
295 auto & depthStencil = this->depthStencils[handle];
296 if(depthStencil.renderBuffer){
298 glObjectLabel(GL_RENDERBUFFER, depthStencil.depthBuffer,
static_cast<GLsizei
>(name.
size()), name.
data());
Log implementation class.
Provides a weakly referenced view over the contents of a string.
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
constexpr size_t size() const noexcept
Get the size of the string.
constexpr bool empty() const noexcept
Check if the string is empty.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Encapsulates blend state for the graphics pipeline in a state object.
Encapsulates state for depth buffer usage and stencil buffer usage in a state object.
Describes a single depth stencil view and which resources to use from the underlying texture.
TextureHandle texture
Texture handle.
uint8_t levelIndex
Index of the mipmap level to render to.
uint16_t layerIndex
Index of the first layer (if array) to write depth to.
static const Handle_t NoHandle
Represents a handle to nothing.
static const Handle_t InvalidHandle
Represents an invalid handle.
Encapsulates state for primitive rasterization in a state object.
Describes a single render target view and which resources to use from the underlying texture.
uint16_t layerIndex
Index of the first layer (if array) to render to.
TextureHandle texture
Texture handle.
uint8_t levelIndex
Index of the mipmap level to render to.
void releaseRasterizerState(RasterizerStateHandle handle) override
Release the rasterizer state with the given handle.
void releaseRenderTarget(RenderTargetHandle renderTargetHandle) override
Release the render target with the given renderTargetHandle.
void releaseResources() override
Release all allocated render target resources.
void releaseBlendState(BlendStateHandle handle) override
Release the blend state with the given handle.
void releaseDepthStencilTarget(DepthStencilHandle depthStencilHandle) override
Release the depth target with the given depthStencilHandle.
RenderTargetHandle createRenderTarget(const RenderTargetViewDescription *renderTargetViews, const size_t numViews) override
Create a render target using the given view descriptions.
void releaseDepthStencilState(DepthStencilStateHandle handle) override
Release the depth stencil state with the given handle.
BlendStateHandle loadBlendState(const BlendState &blendState) override
Load a blend state object.
DepthStencilHandle createDepthStencilTarget(const RenderTargetHandle handle) override
Creates a depth/stencil target to back the render target with the given handle.
void annotate(RenderTargetHandle handle, const StringView &name) override
Associate a name with an object for use in graphics debugging.
DepthStencilStateHandle loadDepthStencilState(const DepthStencilState &depthStencilState) override
Load a depth stencil state object.
RasterizerStateHandle loadRasterizerState(const RasterizerState &rasterizerState) override
Load a rasterizer state object.