Browse Source

Implemented ARB_compute_shader.

The test fails somehow, but too tired to fix anything now.
pull/132/head
Vladimír Vondruš 10 years ago
parent
commit
bcd8a81ba5
  1. 2
      doc/opengl-mapping.dox
  2. 2
      doc/opengl-support.dox
  3. 7
      src/Magnum/AbstractShaderProgram.cpp
  4. 22
      src/Magnum/AbstractShaderProgram.h
  5. 91
      src/Magnum/Test/AbstractShaderProgramGLTest.cpp
  6. 7
      src/Magnum/Test/AbstractShaderProgramGLTestFiles/ComputeShader.comp
  7. 3
      src/Magnum/Test/AbstractShaderProgramGLTestFiles/resources.conf

2
doc/opengl-mapping.dox

@ -121,7 +121,7 @@ OpenGL function | Matching API
@fn_gl{DepthRangeArray} | | @fn_gl{DepthRangeArray} | |
@fn_gl{DepthRangeIndexed} | | @fn_gl{DepthRangeIndexed} | |
@fn_gl{DetachShader} | | @fn_gl{DetachShader} | |
@fn_gl{DispatchCompute} | | @fn_gl{DispatchCompute} | @ref AbstractShaderProgram::DispatchCompute()
@fn_gl_extension{DispatchComputeGroupSize,ARB,compute_variable_group_size} | | @fn_gl_extension{DispatchComputeGroupSize,ARB,compute_variable_group_size} | |
@fn_gl{DispatchComputeIndirect} | | @fn_gl{DispatchComputeIndirect} | |
@fn_gl{DrawArrays}, \n @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | @ref Mesh::draw(), \n @ref MeshView::draw() @fn_gl{DrawArrays}, \n @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | @ref Mesh::draw(), \n @ref MeshView::draw()

2
doc/opengl-support.dox

@ -173,7 +173,7 @@ GLSL 4.30 | done
@extension{ARB,arrays_of_arrays} | done (shading language only) @extension{ARB,arrays_of_arrays} | done (shading language only)
@extension{ARB,ES3_compatibility} | only conservative sample query and compression formats @extension{ARB,ES3_compatibility} | only conservative sample query and compression formats
@extension{ARB,clear_buffer_object} | | @extension{ARB,clear_buffer_object} | |
@extension{ARB,compute_shader} | | @extension{ARB,compute_shader} | done except for indirect dispatch
@extension{ARB,copy_image} | | @extension{ARB,copy_image} | |
@extension{KHR,debug} | missing log retrieval, sync, pipeline and sampler label @extension{KHR,debug} | missing log retrieval, sync, pipeline and sampler label
@extension{ARB,explicit_uniform_location} | done @extension{ARB,explicit_uniform_location} | done

7
src/Magnum/AbstractShaderProgram.cpp

@ -332,6 +332,13 @@ std::pair<bool, std::string> AbstractShaderProgram::validate() {
return {success, std::move(message)}; return {success, std::move(message)};
} }
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractShaderProgram::dispatchCompute(const Vector3ui& workgroupCount) {
use();
glDispatchCompute(workgroupCount.x(), workgroupCount.y(), workgroupCount.z());
}
#endif
void AbstractShaderProgram::use() { void AbstractShaderProgram::use() {
/* Use only if the program isn't already in use */ /* Use only if the program isn't already in use */
GLuint& current = Context::current().state().shaderProgram->current; GLuint& current = Context::current().state().shaderProgram->current;

22
src/Magnum/AbstractShaderProgram.h

@ -413,6 +413,13 @@ shader.setTransformation(transformation)
mesh.draw(shader); mesh.draw(shader);
@endcode @endcode
@anchor AbstractShaderProgram-compute-workflow
## Compute workflow
Add just the @ref Shader::Type::Compute shader and implement uniform/texture
setting functions as needed. After setting up required parameters call
@ref dispatchCompute().
@anchor AbstractShaderProgram-types @anchor AbstractShaderProgram-types
## Mapping between GLSL and Magnum types ## Mapping between GLSL and Magnum types
@ -756,6 +763,21 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
*/ */
std::pair<bool, std::string> validate(); std::pair<bool, std::string> validate();
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/**
* @brief Dispatch compute
* @param workgroupCount Workgroup count in given dimension
*
* Valid only on programs with compute shader attached.
* @see @fn_gl{DispatchCompute}
* @requires_gl43 Extension @extension{ARB,compute_shader}
* @requires_gles31 Compute shaders are not available in OpenGL ES 3.0
* and older.
* @requires_gles Compute shaders are not available in WebGL.
*/
void dispatchCompute(const Vector3ui& workgroupCount);
#endif
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @brief Use shader for rendering * @brief Use shader for rendering

91
src/Magnum/Test/AbstractShaderProgramGLTest.cpp

@ -29,9 +29,16 @@
#include "Magnum/AbstractShaderProgram.h" #include "Magnum/AbstractShaderProgram.h"
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Extensions.h" #include "Magnum/Extensions.h"
#include "Magnum/Image.h"
#include "Magnum/ImageView.h"
#include "Magnum/ImageFormat.h"
#include "Magnum/PixelFormat.h"
#include "Magnum/Shader.h" #include "Magnum/Shader.h"
#include "Magnum/Texture.h"
#include "Magnum/TextureFormat.h"
#include "Magnum/Math/Matrix.h" #include "Magnum/Math/Matrix.h"
#include "Magnum/Math/Vector4.h" #include "Magnum/Math/Vector4.h"
#include "Magnum/Math/Color.h"
#include "Magnum/Test/AbstractOpenGLTester.h" #include "Magnum/Test/AbstractOpenGLTester.h"
namespace Magnum { namespace Test { namespace Magnum { namespace Test {
@ -62,6 +69,8 @@ struct AbstractShaderProgramGLTest: AbstractOpenGLTester {
void uniformBlockIndexNotFound(); void uniformBlockIndexNotFound();
void uniformBlock(); void uniformBlock();
#endif #endif
void compute();
}; };
AbstractShaderProgramGLTest::AbstractShaderProgramGLTest() { AbstractShaderProgramGLTest::AbstractShaderProgramGLTest() {
@ -86,7 +95,9 @@ AbstractShaderProgramGLTest::AbstractShaderProgramGLTest() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&AbstractShaderProgramGLTest::createUniformBlocks, &AbstractShaderProgramGLTest::createUniformBlocks,
&AbstractShaderProgramGLTest::uniformBlockIndexNotFound, &AbstractShaderProgramGLTest::uniformBlockIndexNotFound,
&AbstractShaderProgramGLTest::uniformBlock &AbstractShaderProgramGLTest::uniformBlock,
&AbstractShaderProgramGLTest::compute
#endif #endif
}); });
} }
@ -628,6 +639,84 @@ void AbstractShaderProgramGLTest::uniformBlock() {
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
} }
void AbstractShaderProgramGLTest::compute() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::compute_shader>())
CORRADE_SKIP(Extensions::GL::ARB::compute_shader::string() + std::string(" is not supported."));
#else
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP("OpenGL ES 3.1 is not supported.");
#endif
struct ComputeShader: AbstractShaderProgram {
explicit ComputeShader() {
Utility::Resource rs("AbstractShaderProgramGLTest");
Shader compute(
#ifndef MAGNUM_TARGET_GLES
Version::GL430,
#else
Version::GLES310,
#endif
Shader::Type::Compute);
compute.addSource(rs.get("ComputeShader.comp"));
CORRADE_INTERNAL_ASSERT(compute.compile());
attachShader(compute);
link();
}
ComputeShader& setImages(Texture2D& input, Texture2D& output) {
input.bindImage(0, 0, ImageAccess::ReadOnly, ImageFormat::RGBA8UI);
output.bindImage(1, 0, ImageAccess::WriteOnly, ImageFormat::RGBA8UI);
return *this;
}
} shader;
MAGNUM_VERIFY_NO_ERROR();
const Color4ub inData[] = {
{ 10, 20, 30, 40},
{ 50, 60, 70, 80},
{ 90, 100, 110, 120},
{130, 140, 150, 160}
};
#ifndef MAGNUM_TARGET_GLES
const Color4ub outData[] = {
{ 15, 30, 45, 60},
{ 75, 90, 105, 120},
{135, 150, 165, 180},
{195, 210, 225, 240}
};
#endif
Texture2D in;
in.setStorage(1, TextureFormat::RGBA8UI, {2, 2})
.setSubImage(0, {}, ImageView2D{PixelFormat::RGBAInteger, PixelType::UnsignedByte, {2, 2}, inData});
Texture2D out;
out.setStorage(1, TextureFormat::RGBA8UI, {2, 2});
MAGNUM_VERIFY_NO_ERROR();
shader.setImages(in, out)
.dispatchCompute({1, 1, 1});
MAGNUM_VERIFY_NO_ERROR();
/** @todo Test on ES */
#ifndef MAGNUM_TARGET_GLES
const auto data = out.image(0, {PixelFormat::RGBAInteger, PixelType::UnsignedByte}).data();
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(
(Corrade::Containers::ArrayView<const Color4ub>{reinterpret_cast<const Color4ub*>(data.data()), 4}),
(Corrade::Containers::ArrayView<const Color4ub>{outData}));
#endif
}
#endif #endif
}} }}

7
src/Magnum/Test/AbstractShaderProgramGLTestFiles/ComputeShader.comp

@ -0,0 +1,7 @@
layout(local_size_x = 2, local_size_y = 2) in;
layout(binding = 0, rgba8ui) uniform mediump uimage2D inData;
layout(binding = 1, rgba8ui) uniform mediump uimage2D outData;
void main() {
imageStore(outData, ivec2(gl_GlobalInvocationID.xy), imageLoad(inData, ivec2(gl_GlobalInvocationID.xy))*3u/2u);
}

3
src/Magnum/Test/AbstractShaderProgramGLTestFiles/resources.conf

@ -14,3 +14,6 @@ filename=UniformBlockShader.frag
[file] [file]
filename=UniformBlockShader.vert filename=UniformBlockShader.vert
[file]
filename=ComputeShader.comp

Loading…
Cancel
Save