Added generateTextureMipsWithPipeline function in batch

This commit is contained in:
Olivier Prat 2018-09-27 10:26:51 +02:00
parent 7701cfd9c8
commit 9cd963af95
10 changed files with 125 additions and 1 deletions

View file

@ -64,6 +64,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::gl::GLBackend::do_clearFramebuffer),
(&::gpu::gl::GLBackend::do_blit),
(&::gpu::gl::GLBackend::do_generateTextureMips),
(&::gpu::gl::GLBackend::do_generateTextureMipsWithPipeline),
(&::gpu::gl::GLBackend::do_advance),
@ -163,6 +164,10 @@ GLBackend::GLBackend() {
GLBackend::~GLBackend() {}
void GLBackend::shutdown() {
if (_mipGenerationFramebufferId) {
glDeleteFramebuffers(1, &_mipGenerationFramebufferId);
_mipGenerationFramebufferId = 0;
}
killInput();
killTransform();
killTextureManagementStage();

View file

@ -288,6 +288,7 @@ public:
virtual void do_setIndexBuffer(const Batch& batch, size_t paramOffset) final;
virtual void do_setIndirectBuffer(const Batch& batch, size_t paramOffset) final;
virtual void do_generateTextureMips(const Batch& batch, size_t paramOffset) final;
virtual void do_generateTextureMipsWithPipeline(const Batch& batch, size_t paramOffset) final;
// Transform Stage
virtual void do_setModelTransform(const Batch& batch, size_t paramOffset) final;
@ -407,6 +408,8 @@ public:
protected:
virtual GLint getRealUniformLocation(GLint location) const;
virtual void draw(GLenum mode, uint32 numVertices, uint32 startVertex) = 0;
void recycle() const override;
// FIXME instead of a single flag, create a features struct similar to
@ -696,6 +699,8 @@ protected:
virtual void initTextureManagementStage();
virtual void killTextureManagementStage();
GLuint _mipGenerationFramebufferId{ 0 };
typedef void (GLBackend::*CommandCall)(const Batch&, size_t);
static CommandCall _commandCalls[Batch::NUM_COMMANDS];
friend class GLState;

View file

@ -79,3 +79,50 @@ void GLBackend::do_generateTextureMips(const Batch& batch, size_t paramOffset) {
object->generateMips();
}
void GLBackend::do_generateTextureMipsWithPipeline(const Batch& batch, size_t paramOffset) {
TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint);
if (!resourceTexture) {
return;
}
// Do not transfer the texture, this call is expected for rendering texture
GLTexture* object = syncGPUObject(resourceTexture);
if (!object) {
return;
}
auto numMips = batch._params[paramOffset + 1]._int;
if (numMips < 0) {
numMips = resourceTexture->getNumMips();
} else {
numMips = std::min(numMips, (int)resourceTexture->getNumMips());
}
if (_mipGenerationFramebufferId == 0) {
glGenFramebuffers(1, &_mipGenerationFramebufferId);
Q_ASSERT(_mipGenerationFramebufferId > 0);
}
glBindFramebuffer(GL_FRAMEBUFFER, _mipGenerationFramebufferId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
for (int level = 1; level < numMips; level++) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, object->_id, level);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level - 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level - 1);
const auto mipDimensions = resourceTexture->evalMipDimensions(level);
glViewport(0, 0, mipDimensions.x, mipDimensions.y);
draw(GL_TRIANGLE_STRIP, 4, 0);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, numMips - 1);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
resetOutputStage();
// Restore viewport
ivec4& vp = _transform._viewport;
glViewport(vp.x, vp.y, vp.z, vp.w);
}

View file

@ -20,6 +20,29 @@ using namespace gpu::gl41;
const std::string GL41Backend::GL41_VERSION { "GL41" };
void GL41Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) {
if (isStereo()) {
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
#else
setupStereoSide(0);
glDrawArrays(mode, startVertex, numVertices);
setupStereoSide(1);
glDrawArrays(mode, startVertex, numVertices);
#endif
_stats._DSNumTriangles += 2 * numVertices / 3;
_stats._DSNumDrawcalls += 2;
} else {
glDrawArrays(mode, startVertex, numVertices);
_stats._DSNumTriangles += numVertices / 3;
_stats._DSNumDrawcalls++;
}
_stats._DSNumAPIDrawcalls++;
(void)CHECK_GL_ERROR();
}
void GL41Backend::do_draw(const Batch& batch, size_t paramOffset) {
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];

View file

@ -130,6 +130,9 @@ public:
};
protected:
void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override;
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;

View file

@ -42,6 +42,30 @@ void GL45Backend::recycle() const {
Parent::recycle();
}
void GL45Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) {
if (isStereo()) {
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
#else
setupStereoSide(0);
glDrawArrays(mode, startVertex, numVertices);
setupStereoSide(1);
glDrawArrays(mode, startVertex, numVertices);
#endif
_stats._DSNumTriangles += 2 * numVertices / 3;
_stats._DSNumDrawcalls += 2;
} else {
glDrawArrays(mode, startVertex, numVertices);
_stats._DSNumTriangles += numVertices / 3;
_stats._DSNumDrawcalls++;
}
_stats._DSNumAPIDrawcalls++;
(void)CHECK_GL_ERROR();
}
void GL45Backend::do_draw(const Batch& batch, size_t paramOffset) {
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];

View file

@ -229,6 +229,7 @@ public:
protected:
void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override;
void recycle() const override;
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;

View file

@ -417,6 +417,15 @@ void Batch::generateTextureMips(const TexturePointer& texture) {
_params.emplace_back(_textures.cache(texture));
}
void Batch::generateTextureMipsWithPipeline(const TexturePointer& texture, int numMips) {
setResourceTexture(gpu::slot::texture::MipCreationInput, texture);
ADD_COMMAND(generateTextureMipsWithPipeline);
_params.emplace_back(_textures.cache(texture));
_params.emplace_back(numMips);
}
void Batch::beginQuery(const QueryPointer& query) {
ADD_COMMAND(beginQuery);

View file

@ -216,6 +216,8 @@ public:
// Generate the mips for a texture
void generateTextureMips(const TexturePointer& texture);
// Generate the mips for a texture using the current pipeline
void generateTextureMipsWithPipeline(const TexturePointer& destTexture, int numMips = -1);
// Query Section
void beginQuery(const QueryPointer& query);
@ -316,6 +318,7 @@ public:
COMMAND_clearFramebuffer,
COMMAND_blit,
COMMAND_generateTextureMips,
COMMAND_generateTextureMipsWithPipeline,
COMMAND_advance,

View file

@ -21,6 +21,9 @@
#define GPU_TEXTURE_TRANSFORM_OBJECT 31
// Mip creation
#define GPU_TEXTURE_MIP_CREATION_INPUT 0
#define GPU_STORAGE_TRANSFORM_OBJECT 7
#define GPU_ATTR_POSITION 0
@ -67,7 +70,8 @@ enum Buffer {
namespace texture {
enum Texture {
ObjectTransforms = GPU_TEXTURE_TRANSFORM_OBJECT,
};
MipCreationInput = GPU_TEXTURE_MIP_CREATION_INPUT,
};
} // namespace texture
namespace storage {