First draft at batch generateTextureMipsWithPipeline

This commit is contained in:
Olivier Prat 2018-04-12 17:58:05 +02:00
parent 5978158358
commit 644ef33730
12 changed files with 124 additions and 44 deletions

View file

@ -62,7 +62,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::gl::GLBackend::do_setFramebufferSwapChain),
(&::gpu::gl::GLBackend::do_clearFramebuffer),
(&::gpu::gl::GLBackend::do_blit),
(&::gpu::gl::GLBackend::do_generateTextureMips),
(&::gpu::gl::GLBackend::do_generateTextureMips),
(&::gpu::gl::GLBackend::do_generateTextureMipsWithPipeline),
(&::gpu::gl::GLBackend::do_advance),
@ -133,10 +134,23 @@ GLBackend::GLBackend() {
GLBackend::~GLBackend() {
if (_mipGenerationFramebufferId) {
glDeleteFramebuffers(1, &_mipGenerationFramebufferId);
_mipGenerationFramebufferId = 0;
}
killInput();
killTransform();
}
void GLBackend::do_draw(const Batch& batch, size_t paramOffset) {
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
uint32 numVertices = batch._params[paramOffset + 1]._uint;
uint32 startVertex = batch._params[paramOffset + 0]._uint;
draw(mode, numVertices, startVertex);
}
void GLBackend::renderPassTransfer(const Batch& batch) {
const size_t numCommands = batch.getCommands().size();
const Batch::Commands::value_type* command = batch.getCommands().data();

View file

@ -108,7 +108,7 @@ public:
// Draw Stage
virtual void do_draw(const Batch& batch, size_t paramOffset) = 0;
virtual void do_draw(const Batch& batch, size_t paramOffset);
virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) = 0;
virtual void do_drawInstanced(const Batch& batch, size_t paramOffset) = 0;
virtual void do_drawIndexedInstanced(const Batch& batch, size_t paramOffset) = 0;
@ -120,7 +120,8 @@ public:
virtual void do_setInputBuffer(const Batch& batch, size_t paramOffset) final;
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_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;
@ -234,6 +235,8 @@ public:
protected:
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
@ -492,6 +495,8 @@ protected:
} _textureManagement;
virtual void initTextureManagementStage() {}
GLuint _mipGenerationFramebufferId{ 0 };
typedef void (GLBackend::*CommandCall)(const Batch&, size_t);
static CommandCall _commandCalls[Batch::NUM_COMMANDS];
friend class GLState;

View file

@ -66,16 +66,58 @@ GLTexture* GLBackend::syncGPUObject(const TexturePointer& texturePointer) {
}
void GLBackend::do_generateTextureMips(const Batch& batch, size_t paramOffset) {
TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint);
if (!resourceTexture) {
return;
}
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;
}
// DO not transfer the texture, this call is expected for rendering texture
GLTexture* object = syncGPUObject(resourceTexture);
if (!object) {
return;
}
object->generateMips();
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_EXT, 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);
resetOutputStage();
}

View file

@ -20,12 +20,7 @@ using namespace gpu::gl41;
const std::string GL41Backend::GL41_VERSION { "GL41" };
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];
uint32 numVertices = batch._params[paramOffset + 1]._uint;
uint32 startVertex = batch._params[paramOffset + 0]._uint;
void GL41Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) {
if (isStereo()) {
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
glDrawArraysInstanced(mode, startVertex, numVertices, 2);

View file

@ -133,6 +133,9 @@ public:
};
protected:
void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override;
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
@ -146,7 +149,6 @@ protected:
GLQuery* syncGPUObject(const Query& query) override;
// Draw Stage
void do_draw(const Batch& batch, size_t paramOffset) override;
void do_drawIndexed(const Batch& batch, size_t paramOffset) override;
void do_drawInstanced(const Batch& batch, size_t paramOffset) override;
void do_drawIndexedInstanced(const Batch& batch, size_t paramOffset) override;

View file

@ -24,33 +24,28 @@ void GL45Backend::recycle() const {
Parent::recycle();
}
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];
uint32 numVertices = batch._params[paramOffset + 1]._uint;
uint32 startVertex = batch._params[paramOffset + 0]._uint;
if (isStereo()) {
void GL45Backend::draw(GLenum mode, uint32 numVertices, uint32 startVertex) {
if (isStereo()) {
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
glDrawArraysInstanced(mode, startVertex, numVertices, 2);
#else
setupStereoSide(0);
glDrawArrays(mode, startVertex, numVertices);
setupStereoSide(1);
glDrawArrays(mode, startVertex, numVertices);
setupStereoSide(0);
glDrawArrays(mode, startVertex, numVertices);
setupStereoSide(1);
glDrawArrays(mode, startVertex, numVertices);
#endif
_stats._DSNumTriangles += 2 * numVertices / 3;
_stats._DSNumDrawcalls += 2;
_stats._DSNumTriangles += 2 * numVertices / 3;
_stats._DSNumDrawcalls += 2;
} else {
glDrawArrays(mode, startVertex, numVertices);
_stats._DSNumTriangles += numVertices / 3;
_stats._DSNumDrawcalls++;
}
_stats._DSNumAPIDrawcalls++;
} else {
glDrawArrays(mode, startVertex, numVertices);
_stats._DSNumTriangles += numVertices / 3;
_stats._DSNumDrawcalls++;
}
_stats._DSNumAPIDrawcalls++;
(void) CHECK_GL_ERROR();
(void)CHECK_GL_ERROR();
}
void GL45Backend::do_drawIndexed(const Batch& batch, size_t paramOffset) {

View file

@ -231,6 +231,7 @@ public:
protected:
void draw(GLenum mode, uint32 numVertices, uint32 startVertex) override;
void recycle() const override;
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
@ -246,7 +247,6 @@ protected:
// Draw Stage
void do_draw(const Batch& batch, size_t paramOffset) override;
void do_drawIndexed(const Batch& batch, size_t paramOffset) override;
void do_drawInstanced(const Batch& batch, size_t paramOffset) override;
void do_drawIndexedInstanced(const Batch& batch, size_t paramOffset) override;

View file

@ -425,6 +425,15 @@ void Batch::generateTextureMips(const TexturePointer& texture) {
_params.emplace_back(_textures.cache(texture));
}
void Batch::generateTextureMipsWithPipeline(const TexturePointer& texture, int numMips) {
setResourceTexture(0, 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

@ -211,7 +211,9 @@ public:
void blit(const FramebufferPointer& src, const Vec4i& srcRect, const FramebufferPointer& dst, const Vec4i& dstRect);
// Generate the mips for a texture
void generateTextureMips(const TexturePointer& texture);
void generateTextureMips(const TexturePointer& texture);
// Generate the mips for a texture using the current pipeline
void generateTextureMipsWithPipeline(const TexturePointer& texture, int numMips = -1);
// Query Section
void beginQuery(const QueryPointer& query);
@ -310,7 +312,8 @@ public:
COMMAND_setFramebufferSwapChain,
COMMAND_clearFramebuffer,
COMMAND_blit,
COMMAND_generateTextureMips,
COMMAND_generateTextureMips,
COMMAND_generateTextureMipsWithPipeline,
COMMAND_advance,

View file

@ -14,6 +14,7 @@
#include "Frame.h"
#include "GPULogging.h"
#include "StandardShaderLib.h"
using namespace gpu;
@ -317,3 +318,14 @@ Size Context::getTexturePendingGPUTransferMemSize() {
Size Context::getTextureResourcePopulatedGPUMemSize() {
return Backend::textureResourcePopulatedGPUMemSize.getValue();
}
PipelinePointer Context::createMipGenerationPipeline(const ShaderPointer& ps, const gpu::Shader::BindingSet& slotBindings) {
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
static gpu::StatePointer state(new gpu::State());
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::makeProgram(*program, slotBindings);
// Good to go add the brand new pipeline
return gpu::Pipeline::create(program, state);
}

View file

@ -220,6 +220,8 @@ public:
// Same as above but grabbed at every end of a frame
void getFrameStats(ContextStats& stats) const;
static PipelinePointer createMipGenerationPipeline(const ShaderPointer& pixelShader, const gpu::Shader::BindingSet& slotBindings = gpu::Shader::BindingSet());
double getFrameTimerGPUAverage() const;
double getFrameTimerBatchAverage() const;

View file

@ -313,6 +313,7 @@ float evalAO(in vec3 C, in vec3 n_C, in vec3 Q) {
// the source occlusion texture
uniform sampler2D occlusionMap;
vec2 fetchOcclusionDepthRaw(ivec2 coords, out vec3 raw) {
raw = texelFetch(occlusionMap, coords, 0).xyz;
return unpackOcclusionDepth(raw);