1#include "RenderTargetsGL20.h"
2#include "TexturesGL20.h"
3#include "GraphicsDeviceGL20.h"
5#include "Foundation/Logging/Logger.h"
11 bool checkFrameBuffer()
13 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
15 if (status == GL_FRAMEBUFFER_UNDEFINED) {
return false; }
16 else if (status == GL_FRAMEBUFFER_UNSUPPORTED) {
17 LOG_ERROR(logger,
"FBO contains unsupported image formats.");
19 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) {
20 LOG_ERROR(logger,
"FBO incomplete, missing any image attachments.");
22 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) {
23 LOG_ERROR(logger,
"FBO incomplete, missing complete attachments.");
25 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER) {
26 LOG_ERROR(logger,
"FBO incomplete, draw buffer.");
28 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER) {
29 LOG_ERROR(logger,
"FBO incomplete, read buffer.");
31 }
else if (status == GL_FRAMEBUFFER_UNSUPPORTED) {
32 LOG_ERROR(logger,
"FBO incomplete, unsupported combination of internal formats.");
34 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) {
35 LOG_ERROR(logger,
"FBO incomplete, multisample.");
37 }
else if (status == GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS) {
38 LOG_ERROR(logger,
"FBO incomplete, layers.");
41 assert(status == GL_FRAMEBUFFER_COMPLETE);
47Cogs::RenderTargetsGL20::~RenderTargetsGL20()
49 if (this->renderTargets.size()) {
50 LOG_WARNING(logger,
"Render targets resources not empty. %zu resources left.", this->renderTargets.size());
52 if (this->depthStencils.size()) {
53 LOG_WARNING(logger,
"Depth stencil target resources not empty. %zu resources left.", this->depthStencils.size());
61 glGenFramebuffers(1, &renderTarget.frameBuffer);
62 glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.frameBuffer);
64 renderTarget.numTextures = numViews;
66 for (
size_t i = 0; i < numViews; ++i) {
68 GLenum target = texture.type;
69 renderTarget.textures[i] = renderTargetViews[i].
texture;
71 if(target == GL_TEXTURE_CUBE_MAP){
72 GLint face = renderTargetViews[i].
layerIndex%6;
73 GLint layer = renderTargetViews[i].
layerIndex/6;
75 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 +
static_cast<GLint
>(i),
76 GL_TEXTURE_CUBE_MAP_POSITIVE_X+face,
77 texture.textureId, renderTargetViews[i].
layerIndex);
78 }
else if(target == GL_TEXTURE_CUBE_MAP_ARRAY || target == GL_TEXTURE_2D_ARRAY) {
79 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 +
static_cast<GLint
>(i),
83 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 +
static_cast<GLint
>(i),
84 target, texture.textureId, renderTargetViews[i].
levelIndex);
88 if (numViews && !checkFrameBuffer()) {
92 glBindFramebuffer(GL_FRAMEBUFFER, 0);
94 return this->renderTargets.addResource(renderTarget);
99 auto & renderTarget = this->renderTargets[renderTargetHandle];
101 glDeleteFramebuffers(1, &renderTarget.frameBuffer);
103 this->renderTargets.removeResource(renderTargetHandle);
109 TextureGL20 & texture = this->textures->textures[renderTarget.textures[0]];
111 GLuint depthRenderBuffer;
112 glGenRenderbuffers(1, &depthRenderBuffer);
113 glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
115 GLenum format = GL_DEPTH_COMPONENT32F;
116 if (texture.numSamples == 1) {
117 glRenderbufferStorage(GL_RENDERBUFFER, format, texture.width, texture.height);
119 glRenderbufferStorageMultisample(GL_RENDERBUFFER, texture.numSamples, format, texture.width, texture.height);
122 glBindRenderbuffer(GL_RENDERBUFFER, 0);
124 glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.frameBuffer);
125 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);
127 if (!checkFrameBuffer()){
131 glBindFramebuffer(GL_FRAMEBUFFER, 0);
135 return this->depthStencils.addResource(depthStencilTarget);
141 if(!HandleIsValid(renderTargetHandle)){
142 renderTargetHandle = createRenderTarget(
nullptr, 0);
145 TextureGL20 & texture = this->textures->textures[textureHandle];
146 GLenum target = texture.type;
148 GLuint frameBuffer = renderTarget.frameBuffer;
150 glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
151 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target, texture.textureId, 0);
153 if (!checkFrameBuffer()){
157 glBindFramebuffer(GL_FRAMEBUFFER, 0);
161 return this->depthStencils.addResource(depthTarget);
167 if(!HandleIsValid(renderTargetHandle)){
168 renderTargetHandle = createRenderTarget(
nullptr, 0);
172 GLenum target = texture.type;
173 GLuint frameBuffer = renderTarget.frameBuffer;
175 glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
177 if(target == GL_TEXTURE_CUBE_MAP){
181 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
182 GL_TEXTURE_CUBE_MAP_POSITIVE_X+face,
183 texture.textureId, depthStencilView.
levelIndex);
185 else if(target == GL_TEXTURE_CUBE_MAP_ARRAY || target == GL_TEXTURE_2D_ARRAY){
186 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texture.textureId,
190 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
191 target, texture.textureId, depthStencilView.
levelIndex);
194 if (!checkFrameBuffer()){
198 glBindFramebuffer(GL_FRAMEBUFFER, 0);
202 return this->depthStencils.addResource(depthTarget);
207 auto & depthStencil = this->depthStencils[depthStencilHandle];
209 if (depthStencil.renderBuffer) {
210 glDeleteRenderbuffers(1, &depthStencil.depthBuffer);
213 this->depthStencils.removeResource(depthStencilHandle);
220 if (HandleIsValid(renderTargetHandle)) {
221 const RenderTargetGL20 & renderTarget = this->renderTargets[renderTargetHandle];
222 layout.
numColorTargets =
static_cast<uint8_t
>(renderTarget.numTextures);
224 for (
size_t i = 0; i < renderTarget.numTextures; ++i) {
225 const TextureGL20 & texture = this->textures->textures[renderTarget.textures[i]];
227 layout.
samples =
static_cast<uint8_t
>(texture.numSamples);
236 if (HandleIsValid(depthStencilHandle)) {
239 ? this->textures->textures[depthStencil.texture].format
240 : TextureFormat::D32_FLOAT;
241 }
else if (!HandleIsValid(renderTargetHandle)) {
250 return this->depthStencilStates.addResource(depthStencilState);
255 this->depthStencilStates.removeResource(handle);
260 return this->rasterizerStates.addResource(rasterizerState);
265 this->rasterizerStates.removeResource(handle);
270 return loadBlendState(blendState, blendState);
276 blendState.color = blendStateColor;
277 blendState.alpha = blendStateAlpha;
278 return this->blendStates.addResource(std::move(blendState));
284 this->blendStates.removeResource(handle);
289 std::vector<RenderTargetHandle> rtHandles;
290 for (
auto & rt : renderTargets) {
291 rtHandles.push_back(renderTargets.getHandle(rt));
294 for (
auto & handle : rtHandles) {
295 releaseRenderTarget(handle);
298 std::vector<DepthStencilHandle> dsHandles;
299 for (
auto & ds : depthStencils) {
300 dsHandles.push_back(depthStencils.getHandle(ds));
303 for (
auto & handle : dsHandles) {
304 releaseDepthStencilTarget(handle);
307 this->blendStates.clear();
308 this->rasterizerStates.clear();
309 this->depthStencilStates.clear();
314 if(name.
empty() || !HandleIsValid(handle))
return;
317 auto & renderTarget = this->renderTargets[handle];
318 glObjectLabel(GL_FRAMEBUFFER, renderTarget.frameBuffer,
static_cast<GLsizei
>(name.
size()), name.
data());
326 if(name.
empty() || !HandleIsValid(handle))
return;
328 auto & depthStencil = this->depthStencils[handle];
329 if(depthStencil.renderBuffer){
331 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.
Settings for graphics device initialization.
int numSamples
Number of samples to use for back buffer MSAA.
TextureFormat colorFormat
Back buffer format.
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 the formats and sample count of a render target's attachments.
TextureFormat colorFormats[8]
Formats of the color targets, only the first numColorTargets entries are valid.
TextureFormat depthStencilFormat
Format of the depth stencil target, TextureFormat::Unknown if there is none.
uint8_t samples
Number of samples, 1 implies no multisampling.
uint8_t numColorTargets
Number of valid entries in colorFormats.
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.
RenderTargetLayout getLayout(const RenderTargetHandle renderTargetHandle, const DepthStencilHandle depthStencilHandle) override
Get the view layout for the given render target / depth stencil target pair.
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.