TESTGLSLGEOM: added geometry shader test application

also only regenerate the shader headers if something really changed for the c++ interface
added ScopedVertexBuffer
moved general imgui controls into TestApp
changed default gl versions
improved geometry shader support
master
Martin Gerhardy 2018-04-13 21:11:43 +02:00
parent 85d0a3b582
commit 4c0e4d1ce5
43 changed files with 523 additions and 306 deletions

2
.gitignore vendored
View File

@ -8,3 +8,5 @@
gmon.out gmon.out
/*.sync /*.sync
/perf.data* /perf.data*
luac.out
*.patch

View File

@ -167,7 +167,7 @@ doc: cmake
$(call COMPILE, codegen) $(call COMPILE, codegen)
$(call COMPILE, $@) $(call COMPILE, $@)
server client voxedit shapetool mapedit shadertool noisetool databasetool uitool tests tests-math tests-core tests-persistence tests-voxel benchmarks-voxel tests-noise tests-computeshadertool testmesh testcamera testdepthbuffer testnuklear testtexture testvoxelfont testplane testimgui testoctree testglslcomp testluaui testoctreevisit testshapebuilder tests-shadertool flatc computeshadertool: cmake server client voxedit shapetool mapedit shadertool noisetool databasetool uitool tests tests-math tests-core tests-persistence tests-voxel benchmarks-voxel tests-noise tests-computeshadertool testmesh testcamera testdepthbuffer testnuklear testtexture testvoxelfont testplane testimgui testoctree testglslgeom testglslcomp testluaui testoctreevisit testshapebuilder tests-shadertool flatc computeshadertool: cmake
$(call COMPILE, $@) $(call COMPILE, $@)
$(call COMPILE, copy-data-shared) $(call COMPILE, copy-data-shared)
$(call COMPILE, copy-data-$@) $(call COMPILE, copy-data-$@)

View File

@ -14,10 +14,6 @@ INFO: (0) Validation output: shaders/world
active samplers with a different type refer to the same texture image unit active samplers with a different type refer to the same texture image unit
``` ```
## Code generation
Only replace the files if something has really changed. (`configure_file`?)
# Data handling # Data handling
The current approach with data dir must be extended/redone someone. There are way too many files installed per artifact atm. Also there should be CPack support to generate debian packages. The current approach with data dir must be extended/redone someone. There are way too many files installed per artifact atm. Also there should be CPack support to generate debian packages.

View File

@ -48,115 +48,122 @@ endmacro()
macro(generate_shaders TARGET) macro(generate_shaders TARGET)
set(files ${ARGV}) set(files ${ARGV})
list(REMOVE_AT files 0) list(REMOVE_AT files 0)
set(_headers)
set(GEN_DIR ${GENERATE_DIR}/shaders/${TARGET}/) set(GEN_DIR ${GENERATE_DIR}/shaders/${TARGET}/)
set(_template ${ROOT_DIR}/src/tools/shadertool/ShaderTemplate.h.in) set(_template ${ROOT_DIR}/src/tools/shadertool/ShaderTemplate.h.in)
set(_template_ub ${ROOT_DIR}/src/tools/shadertool/UniformBufferTemplate.h.in) set(_template_ub ${ROOT_DIR}/src/tools/shadertool/UniformBufferTemplate.h.in)
file(MAKE_DIRECTORY ${GEN_DIR}) file(MAKE_DIRECTORY ${GEN_DIR})
target_include_directories(${TARGET} PUBLIC ${GEN_DIR}) target_include_directories(${TARGET} PUBLIC ${GEN_DIR})
foreach (shader_dir "${TARGET}" shared) set(_headers)
set(_dir ${ROOT_DIR}/${GAME_BASE_DIR}/${shader_dir}/shaders) add_custom_target(UpdateShaders${TARGET})
if (IS_DIRECTORY ${_dir}) file(WRITE ${CMAKE_BINARY_DIR}/GenerateShaderHeader${TARGET}.cmake "configure_file(\${SRC} \${DST} @ONLY)")
foreach (_file ${files}) foreach (_file ${files})
convert_to_camel_case(${_file} _f) set(_shaders)
set(_shaderfile "${_f}Shader.h") set(_lastdir)
set(_shader "${GEN_DIR}${_shaderfile}") foreach (shader_dir "${TARGET}" shared)
if (EXISTS ${_dir}/${_file}.frag AND EXISTS ${_dir}/${_file}.vert) set(_dir ${ROOT_DIR}/${GAME_BASE_DIR}/${shader_dir}/shaders)
add_custom_command( if (EXISTS ${_dir}/${_file}.frag AND EXISTS ${_dir}/${_file}.vert)
OUTPUT ${_shader} list(APPEND _shaders ${_dir}/${_file}.frag ${_dir}/${_file}.vert)
IMPLICIT_DEPENDS C ${_dir}/${_file}.frag C ${_dir}/${_file}.vert set(_lastdir ${_dir})
COMMENT "Validate ${_file} and generate ${_shaderfile}" endif()
COMMAND ${CMAKE_BINARY_DIR}/shadertool --glslang ${CMAKE_BINARY_DIR}/glslangValidator --shader ${_dir}/${_file} --shadertemplate ${_template} --buffertemplate ${_template_ub} --sourcedir ${GEN_DIR} if (EXISTS ${_dir}/${_file}.geom)
DEPENDS shadertool ${_dir}/${_file}.frag ${_dir}/${_file}.vert ${_template} ${_template_ub} list(APPEND _shaders ${_dir}/${_file}.geom)
) set(_lastdir ${_dir})
list(APPEND _headers ${_shader}) endif()
elseif (EXISTS ${_dir}/${_file}.comp) if (EXISTS ${_dir}/${_file}.comp)
add_custom_command( list(APPEND _shaders ${_dir}/${_file}.comp)
OUTPUT ${_shader} set(_lastdir ${_dir})
IMPLICIT_DEPENDS C ${_dir}/${_file}.comp endif()
COMMENT "Validate ${_file} and generate ${_shaderfile}" endforeach()
COMMAND ${CMAKE_BINARY_DIR}/shadertool --glslang ${CMAKE_BINARY_DIR}/glslangValidator --shader ${_dir}/${_file} --shadertemplate ${_template} --buffertemplate ${_template_ub} --sourcedir ${GEN_DIR} if (_shaders)
DEPENDS shadertool ${_dir}/${_file}.comp ${_template} ${_template_ub} convert_to_camel_case(${_file} _f)
) set(_shaderfile "${_f}Shader.h")
list(APPEND _headers ${_shader}) set(_shader "${GEN_DIR}${_shaderfile}")
endif() add_custom_command(
endforeach() OUTPUT ${_shader}.in
IMPLICIT_DEPENDS C ${_shaders}
COMMENT "Validate ${_file} and generate ${_shaderfile}"
COMMAND ${CMAKE_BINARY_DIR}/shadertool --glslang ${CMAKE_BINARY_DIR}/glslangValidator --postfix .in --shader ${_lastdir}/${_file} --shadertemplate ${_template} --buffertemplate ${_template_ub} --sourcedir ${GEN_DIR}
DEPENDS shadertool ${_shaders} ${_template} ${_template_ub}
)
list(APPEND _headers ${_shader})
add_custom_command(OUTPUT ${_shader} COMMAND ${CMAKE_COMMAND} -D SRC=${_shader}.in -D DST=${_shader} -P ${CMAKE_BINARY_DIR}/GenerateShaderHeader${TARGET}.cmake DEPENDS ${_shader}.in)
else()
message(FATAL_ERROR "Could not find any shader files for ${_file} and target '${TARGET}'")
endif() endif()
endforeach() endforeach()
convert_to_camel_case(${TARGET} _filetarget) convert_to_camel_case(${TARGET} _filetarget)
# TODO: not regenerated if files were added, renamed or removed
set(_h ${GEN_DIR}/${_filetarget}Shaders.h) set(_h ${GEN_DIR}/${_filetarget}Shaders.h)
file(WRITE ${_h}.in "#pragma once\n") file(WRITE ${_h}.in "#pragma once\n")
foreach(header_path ${_headers}) foreach (header_path ${_headers})
string(REPLACE "${GEN_DIR}" "" header "${header_path}") string(REPLACE "${GEN_DIR}" "" header "${header_path}")
file(APPEND ${_h}.in "#include \"${header}\"\n") file(APPEND ${_h}.in "#include \"${header}\"\n")
endforeach() endforeach()
add_custom_command(
OUTPUT ${_h}
COMMAND ${CMAKE_COMMAND}
ARGS -E copy_if_different ${_h}.in ${_h}
COMMENT "Generate ${_h}"
)
add_custom_target(GenerateShaderBindings${TARGET} add_custom_target(GenerateShaderBindings${TARGET}
DEPENDS ${_headers} ${_h} DEPENDS ${_headers}
COMMENT "Generate shader bindings for ${TARGET} in ${GEN_DIR}" COMMENT "Generate shader bindings for ${TARGET} in ${GEN_DIR}"
) )
#target_sources(${TARGET} PUBLIC ${_headers} ${_h}) set_source_files_properties(${_headers} ${_h} PROPERTIES GENERATED TRUE)
set_source_files_properties(${_headers} ${_h} ${_h}.in PROPERTIES GENERATED TRUE) add_custom_target(GenerateShaderHeader${TARGET} ${CMAKE_COMMAND} -D SRC=${_h}.in -D DST=${_h} -P ${CMAKE_BINARY_DIR}/GenerateShaderHeader${TARGET}.cmake)
add_dependencies(${TARGET} GenerateShaderBindings${TARGET}) add_dependencies(${TARGET} GenerateShaderHeader${TARGET} UpdateShaders${TARGET})
add_dependencies(codegen GenerateShaderBindings${TARGET}) add_dependencies(GenerateShaderHeader${TARGET} GenerateShaderBindings${TARGET})
add_dependencies(codegen GenerateShaderHeader${TARGET} UpdateShaders${TARGET})
endmacro() endmacro()
macro(generate_compute_shaders TARGET) macro(generate_compute_shaders TARGET)
set(files ${ARGV}) set(files ${ARGV})
list(REMOVE_AT files 0) list(REMOVE_AT files 0)
set(_headers)
set(GEN_DIR ${GENERATE_DIR}/compute-shaders/${TARGET}/) set(GEN_DIR ${GENERATE_DIR}/compute-shaders/${TARGET}/)
set(_template ${ROOT_DIR}/src/tools/computeshadertool/ComputeShaderTemplate.h.in) set(_template ${ROOT_DIR}/src/tools/computeshadertool/ComputeShaderTemplate.h.in)
file(MAKE_DIRECTORY ${GEN_DIR}) file(MAKE_DIRECTORY ${GEN_DIR})
target_include_directories(${TARGET} PUBLIC ${GEN_DIR}) target_include_directories(${TARGET} PUBLIC ${GEN_DIR})
foreach (shader_dir "${TARGET}" shared) set(_headers)
set(_dir ${ROOT_DIR}/${GAME_BASE_DIR}/${shader_dir}/shaders) add_custom_target(UpdateComputeShaders${TARGET})
if (IS_DIRECTORY ${_dir}) file(WRITE ${CMAKE_BINARY_DIR}/GenerateComputeShaderHeader${TARGET}.cmake "configure_file(\${SRC} \${DST} @ONLY)")
foreach (_file ${files}) foreach (_file ${files})
if (EXISTS ${_dir}/${_file}.cl) set(_shaders)
convert_to_camel_case(${_file} _f) set(_lastdir)
set(_shaderfile "${_f}Shader.h") foreach (shader_dir "${TARGET}" shared)
set(_shader "${GEN_DIR}${_shaderfile}") set(_dir ${ROOT_DIR}/${GAME_BASE_DIR}/${shader_dir}/shaders)
add_custom_command( if (EXISTS ${_dir}/${_file}.cl)
OUTPUT ${_shader} list(APPEND _shaders ${_dir}/${_file}.cl)
IMPLICIT_DEPENDS C ${_dir}/${_file}.cl set(_lastdir ${_dir})
COMMENT "Generate ${_shaderfile}" endif()
COMMAND ${CMAKE_BINARY_DIR}/computeshadertool --shader ${_dir}/${_file} --shadertemplate ${_template} --sourcedir ${GEN_DIR} endforeach()
DEPENDS computeshadertool ${_dir}/${_file}.cl ${_template} if (_shaders)
) convert_to_camel_case(${_file} _f)
list(APPEND _headers ${_shader}) set(_shaderfile "${_f}Shader.h")
endif() set(_shader "${GEN_DIR}${_shaderfile}")
endforeach() add_custom_command(
OUTPUT ${_shader}.in
IMPLICIT_DEPENDS C ${_shaders}
COMMENT "Validate ${_file} and generate ${_shaderfile}"
COMMAND ${CMAKE_BINARY_DIR}/computeshadertool --shader ${_dir}/${_file} --postfix .in --shadertemplate ${_template} --sourcedir ${GEN_DIR}
DEPENDS computeshadertool ${_shaders} ${_template}
)
list(APPEND _headers ${_shader})
add_custom_command(OUTPUT ${_shader} COMMAND ${CMAKE_COMMAND} -D SRC=${_shader}.in -D DST=${_shader} -P ${CMAKE_BINARY_DIR}/GenerateComputeShaderHeader${TARGET}.cmake DEPENDS ${_shader}.in)
else()
message(FATAL_ERROR "Could not find any shader files for ${_file} and target '${TARGET}'")
endif() endif()
endforeach() endforeach()
convert_to_camel_case(${TARGET} _filetarget) convert_to_camel_case(${TARGET} _filetarget)
# TODO: not regenerated if files were added, renamed or removed
set(_h ${GEN_DIR}/${_filetarget}Shaders.h) set(_h ${GEN_DIR}/${_filetarget}Shaders.h)
file(WRITE ${_h}.in "#pragma once\n") file(WRITE ${_h}.in "#pragma once\n")
foreach(header_path ${_headers}) foreach (header_path ${_headers})
string(REPLACE "${GEN_DIR}" "" header "${header_path}") string(REPLACE "${GEN_DIR}" "" header "${header_path}")
file(APPEND ${_h}.in "#include \"${header}\"\n") file(APPEND ${_h}.in "#include \"${header}\"\n")
endforeach() endforeach()
add_custom_command(
OUTPUT ${_h}
COMMAND ${CMAKE_COMMAND}
ARGS -E copy_if_different ${_h}.in ${_h}
COMMENT "Generate ${_h}"
)
add_custom_target(GenerateComputeShaderBindings${TARGET} add_custom_target(GenerateComputeShaderBindings${TARGET}
DEPENDS ${_headers} ${_h} DEPENDS ${_headers}
COMMENT "Generate compute shader bindings for ${TARGET} in ${GEN_DIR}" COMMENT "Generate shader bindings for ${TARGET} in ${GEN_DIR}"
) )
#target_sources(${TARGET} PUBLIC ${_headers} ${_h}) set_source_files_properties(${_headers} ${_h} PROPERTIES GENERATED TRUE)
set_source_files_properties(${_headers} ${_h} ${_h}.in PROPERTIES GENERATED TRUE) add_custom_target(GenerateComputeShaderHeader${TARGET} ${CMAKE_COMMAND} -D SRC=${_h}.in -D DST=${_h} -P ${CMAKE_BINARY_DIR}/GenerateComputeShaderHeader${TARGET}.cmake)
add_dependencies(${TARGET} GenerateComputeShaderBindings${TARGET}) add_dependencies(${TARGET} GenerateComputeShaderHeader${TARGET} UpdateComputeShaders${TARGET})
add_dependencies(codegen GenerateComputeShaderBindings${TARGET}) add_dependencies(GenerateComputeShaderHeader${TARGET} GenerateComputeShaderBindings${TARGET})
add_dependencies(codegen GenerateComputeShaderHeader${TARGET} UpdateComputeShaders${TARGET})
endmacro() endmacro()
macro(generate_db_models TARGET INPUT OUTPUT) macro(generate_db_models TARGET INPUT OUTPUT)

View File

@ -0,0 +1,6 @@
$in vec3 v_color;
$out vec4 o_color;
void main() {
o_color = vec4(v_color, 1.0);
}

View File

@ -0,0 +1,26 @@
layout(points) in;
layout(line_strip, max_vertices = 64) out;
$in vec3 g_color[];
$out vec3 v_color;
uniform int u_sides;
uniform float u_radius;
uniform mat4 u_projection;
const float PI = 3.1415926;
void main() {
v_color = g_color[0];
float delta = PI * 2.0 / float(u_sides);
float ang = 0.0f;
for (int i = 0; i <= u_sides; i++) {
vec4 offset = vec4(cos(ang) * u_radius, -sin(ang) * u_radius, 0.0, 0.0);
gl_Position = u_projection * (gl_in[0].gl_Position + offset);
ang += delta;
EmitVertex();
}
EndPrimitive();
}

View File

@ -0,0 +1,9 @@
$in vec4 a_pos;
$in vec3 a_color;
uniform mat4 u_view;
$out vec3 g_color;
void main() {
gl_Position = u_view * a_pos;
g_color = a_color;
}

View File

@ -0,0 +1,5 @@
w +move_forward
a +move_left
s +move_backward
d +move_right
ctrl+q quit

View File

@ -38,10 +38,9 @@ void TextureRenderer::render(const glm::mat4& projection) {
video::ScopedShader scoped(_textureShader); video::ScopedShader scoped(_textureShader);
_textureShader.setProjection(projection); _textureShader.setProjection(projection);
_textureShader.setTexture(video::TextureUnit::Zero); _textureShader.setTexture(video::TextureUnit::Zero);
_texturedFullscreenQuad.bind(); video::ScopedVertexBuffer scopedBuf(_texturedFullscreenQuad);
const int elements = _texturedFullscreenQuad.elements(0, _textureShader.getComponentsPos()); const int elements = _texturedFullscreenQuad.elements(0, _textureShader.getComponentsPos());
video::drawArrays(video::Primitive::Triangles, elements); video::drawArrays(video::Primitive::Triangles, elements);
_texturedFullscreenQuad.unbind();
} }
void TextureRenderer::shutdown() { void TextureRenderer::shutdown() {

View File

@ -115,6 +115,19 @@ void TestApp::onRenderUI() {
if (ImGui::Checkbox("Toggle profiler", &temp)) { if (ImGui::Checkbox("Toggle profiler", &temp)) {
_renderTracing = toggleTrace(); _renderTracing = toggleTrace();
} }
if (ImGui::Checkbox("Render axis", &_renderAxis)) {
setRenderAxis(_renderAxis);
}
if (ImGui::Checkbox("Render plane", &_renderPlane)) {
setRenderPlane(_renderPlane);
}
if (ImGui::Checkbox("Camera motion", &_cameraMotion)) {
setCameraMotion(_cameraMotion);
}
if (ImGui::InputFloat("Camera speed", &_cameraSpeed, 0.02f, 0.1f)) {
setCameraSpeed(_cameraSpeed);
}
ImGui::InputVarFloat("Rotation speed", _rotationSpeed, 0.01f, 0.1f);
ImGui::Separator(); ImGui::Separator();
if (ImGui::Button("Quit")) { if (ImGui::Button("Quit")) {
requestQuit(); requestQuit();

View File

@ -145,9 +145,6 @@ void TestMeshApp::onRenderUI() {
ImGui::CheckboxVar("Show shadow cascades", _debugShadowCascade); ImGui::CheckboxVar("Show shadow cascades", _debugShadowCascade);
static const char* items[] = { "Disable", "First", "Second", "Third", "Fourth" }; static const char* items[] = { "Disable", "First", "Second", "Third", "Fourth" };
ImGui::Combo("Bone weight", &_boneInfluence, items, IM_ARRAYSIZE(items)); ImGui::Combo("Bone weight", &_boneInfluence, items, IM_ARRAYSIZE(items));
if (ImGui::Checkbox("Render axis", &_renderAxis)) {
setRenderAxis(_renderAxis);
}
ImGui::Checkbox("Render mesh", &_renderMesh); ImGui::Checkbox("Render mesh", &_renderMesh);
ImGui::Checkbox("Render normals", &_renderNormals); ImGui::Checkbox("Render normals", &_renderNormals);
ImGui::Checkbox("Render bones", &_renderBones); ImGui::Checkbox("Render bones", &_renderBones);
@ -158,15 +155,6 @@ void TestMeshApp::onRenderUI() {
ImGui::PopTextWrapPos(); ImGui::PopTextWrapPos();
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
if (ImGui::Checkbox("Render plane", &_renderPlane)) {
setRenderPlane(_renderPlane);
}
if (ImGui::Checkbox("Camera motion", &_cameraMotion)) {
setCameraMotion(_cameraMotion);
}
if (ImGui::InputFloat("Camera speed", &_cameraSpeed, 0.02f, 0.1f)) {
setCameraSpeed(_cameraSpeed);
}
if (ImGui::InputFloat3("Camera omega", glm::value_ptr(_omega))) { if (ImGui::InputFloat3("Camera omega", glm::value_ptr(_omega))) {
_camera.setOmega(_omega); _camera.setOmega(_omega);
} }
@ -174,7 +162,6 @@ void TestMeshApp::onRenderUI() {
ImGui::InputFloat("Shadow bias slope", &_shadowBiasSlope, 0.01f, 0.1f); ImGui::InputFloat("Shadow bias slope", &_shadowBiasSlope, 0.01f, 0.1f);
ImGui::InputFloat("Shadow range", &_shadowRangeZ, 0.01f, 0.1f); ImGui::InputFloat("Shadow range", &_shadowRangeZ, 0.01f, 0.1f);
ImGui::InputFloat("Fog range", &_fogRange, 0.01f, 0.1f); ImGui::InputFloat("Fog range", &_fogRange, 0.01f, 0.1f);
ImGui::InputVarFloat("Rotation speed", _rotationSpeed, 0.01f, 0.1f);
if (_mesh->animations() > 1 && ImGui::InputVarInt("Animation index", _animationIndex, 1, 1)) { if (_mesh->animations() > 1 && ImGui::InputVarInt("Animation index", _animationIndex, 1, 1)) {
_animationIndex->setVal(_mesh->currentAnimation()); _animationIndex->setVal(_mesh->currentAnimation());
} }
@ -320,7 +307,7 @@ void TestMeshApp::doRender() {
_shadowMapRenderShader.setNear(_camera.nearPlane()); _shadowMapRenderShader.setNear(_camera.nearPlane());
// bind buffers // bind buffers
core_assert_always(_shadowMapDebugBuffer.bind()); video::ScopedVertexBuffer scopedBuf(_shadowMapDebugBuffer);
// configure shadow map texture // configure shadow map texture
video::bindTexture(video::TextureUnit::Zero, _depthBuffer); video::bindTexture(video::TextureUnit::Zero, _depthBuffer);
@ -341,9 +328,6 @@ void TestMeshApp::doRender() {
if (_depthBuffer.depthCompare()) { if (_depthBuffer.depthCompare()) {
video::setupDepthCompareTexture(video::TextureUnit::Zero, _depthBuffer.textureType(), _depthBuffer.texture()); video::setupDepthCompareTexture(video::TextureUnit::Zero, _depthBuffer.textureType(), _depthBuffer.texture());
} }
// unbind buffer
_shadowMapDebugBuffer.unbind();
} }
if (!oldDepth) { if (!oldDepth) {

View File

@ -342,7 +342,7 @@ core::AppState IMGUIApp::onRunning() {
core_assert_always(_vbo.update(_bufferIndex, cmdList->VtxBuffer.Data, cmdList->VtxBuffer.Size * sizeof(ImDrawVert))); core_assert_always(_vbo.update(_bufferIndex, cmdList->VtxBuffer.Data, cmdList->VtxBuffer.Size * sizeof(ImDrawVert)));
core_assert_always(_vbo.update(_indexBufferIndex, cmdList->IdxBuffer.Data, cmdList->IdxBuffer.Size * sizeof(ImDrawIdx))); core_assert_always(_vbo.update(_indexBufferIndex, cmdList->IdxBuffer.Data, cmdList->IdxBuffer.Size * sizeof(ImDrawIdx)));
core_assert_always(_vbo.bind()); video::ScopedVertexBuffer scopedBuf(_vbo);
for (int i = 0; i < cmdList->CmdBuffer.Size; ++i) { for (int i = 0; i < cmdList->CmdBuffer.Size; ++i) {
const ImDrawCmd* cmd = &cmdList->CmdBuffer[i]; const ImDrawCmd* cmd = &cmdList->CmdBuffer[i];
@ -356,7 +356,6 @@ core::AppState IMGUIApp::onRunning() {
} }
idxBufferOffset += cmd->ElemCount; idxBufferOffset += cmd->ElemCount;
} }
_vbo.unbind();
} }
video::scissor(0, 0, renderTargetW, renderTargetH); video::scissor(0, 0, renderTargetW, renderTargetH);

View File

@ -592,7 +592,7 @@ int Mesh::render() {
if (_state != io::IOSTATE_LOADED) { if (_state != io::IOSTATE_LOADED) {
return 0; return 0;
} }
_vertexBuffer.bind(); video::ScopedVertexBuffer scopedBuf(_vertexBuffer);
int drawCalls = 0; int drawCalls = 0;
for (const RenderMeshData& mesh : _meshData) { for (const RenderMeshData& mesh : _meshData) {
const uint32_t matIdx = mesh.materialIndex; const uint32_t matIdx = mesh.materialIndex;
@ -602,8 +602,6 @@ int Mesh::render() {
video::drawElementsBaseVertex<Indices::value_type>(video::Primitive::Triangles, mesh.noOfIndices, mesh.baseIndex, mesh.baseVertex); video::drawElementsBaseVertex<Indices::value_type>(video::Primitive::Triangles, mesh.noOfIndices, mesh.baseIndex, mesh.baseVertex);
++drawCalls; ++drawCalls;
} }
_vertexBuffer.unbind();
return drawCalls; return drawCalls;
} }
@ -638,11 +636,10 @@ int Mesh::renderBones(video::Shader& shader) {
boneData.reserve(_boneMapping.size() * 2); boneData.reserve(_boneMapping.size() * 2);
traverseBones(boneData, _scene->mRootNode, glm::mat4(1.0f), glm::vec3(0), false); traverseBones(boneData, _scene->mRootNode, glm::mat4(1.0f), glm::vec3(0), false);
_vertexBufferLines.update(_vertexBufferLinesIndex, boneData.data); _vertexBufferLines.update(_vertexBufferLinesIndex, boneData.data);
_vertexBufferLines.bind(); video::ScopedVertexBuffer scopedBuf(_vertexBufferLines);
ScopedLineWidth lineWidth(2.0f); ScopedLineWidth lineWidth(2.0f);
const int elements = _vertexBufferLines.elements(_vertexBufferLinesIndex, 2); const int elements = _vertexBufferLines.elements(_vertexBufferLinesIndex, 2);
video::drawArrays(video::Primitive::Lines, elements); video::drawArrays(video::Primitive::Lines, elements);
_vertexBufferLines.unbind();
return 1; return 1;
} }
@ -681,11 +678,10 @@ int Mesh::renderNormals(video::Shader& shader) {
} }
_vertexBufferLines.update(_vertexBufferLinesIndex, normalData.data); _vertexBufferLines.update(_vertexBufferLinesIndex, normalData.data);
_vertexBufferLines.bind(); video::ScopedVertexBuffer scopedBuf(_vertexBufferLines);
ScopedLineWidth lineWidth(2.0f); ScopedLineWidth lineWidth(2.0f);
const int elements = _vertexBufferLines.elements(_vertexBufferLinesIndex, 2); const int elements = _vertexBufferLines.elements(_vertexBufferLinesIndex, 2);
video::drawArrays(video::Primitive::Lines, elements); video::drawArrays(video::Primitive::Lines, elements);
_vertexBufferLines.unbind();
return 1; return 1;
} }

View File

@ -17,12 +17,12 @@
namespace video { namespace video {
#ifdef GL_ES_VERSION_2_0 #ifdef GL_ES_VERSION_3_1
// default to opengles3 // default to opengles3
int Shader::glslVersion = GLSLVersion::V300; int Shader::glslVersion = GLSLVersion::V310;
#else #else
// default to opengl3 // default to opengl4
int Shader::glslVersion = GLSLVersion::V330; int Shader::glslVersion = GLSLVersion::V430;
#endif #endif
Shader::Shader() { Shader::Shader() {
@ -327,14 +327,12 @@ std::string Shader::getSource(ShaderType shaderType, const std::string& buffer,
} }
std::string src; std::string src;
src.append("#version "); src.append("#version ");
if (shaderType == ShaderType::Compute) { src.append(std::to_string(glslVersion));
src.append("430");
} else {
src.append(std::to_string(glslVersion));
}
src.append("\n"); src.append("\n");
if (glslVersion < GLSLVersion::V140) { if (shaderType == ShaderType::Compute) {
//src.append("#extension GL_EXT_draw_instanced : enable\n"); src.append("#extension GL_ARB_compute_shader : enable\n");
src.append("#extension GL_ARB_shader_storage_buffer_object : enable\n");
src.append("#extension GL_ARB_compute_variable_group_size : enable\n");
} }
core::Var::visitSorted([&] (const core::VarPtr& var) { core::Var::visitSorted([&] (const core::VarPtr& var) {

View File

@ -1,3 +1,7 @@
/**
* @file
*/
#include "ShaderManager.h" #include "ShaderManager.h"
#include "core/Var.h" #include "core/Var.h"
#include "core/Log.h" #include "core/Log.h"

View File

@ -9,6 +9,9 @@
namespace video { namespace video {
/** /**
* Register @c Shader instances here to let them automatically recompile
* on @c core::CV_SHADER @c core::CVar change.
*
* @ingroup Video * @ingroup Video
*/ */
class ShaderManager { class ShaderManager {

View File

@ -144,7 +144,11 @@ enum class VertexBufferMode {
enum class Primitive { enum class Primitive {
Points, Points,
Lines, Lines,
LinesAdjacency,
Triangles, Triangles,
TrianglesAdjacency,
LineStrip,
TriangleStrip,
Max Max
}; };

View File

@ -170,4 +170,18 @@ inline void VertexBuffer::setMode(int32_t idx, VertexBufferMode mode) {
_modes[idx] = mode; _modes[idx] = mode;
} }
class ScopedVertexBuffer {
private:
const VertexBuffer& _buf;
public:
ScopedVertexBuffer(const VertexBuffer& buf) :
_buf(buf) {
buf.bind();
}
~ScopedVertexBuffer() {
_buf.unbind();
}
};
} }

View File

@ -157,7 +157,11 @@ static_assert(std::enum_value(Face::Max) == lengthof(Faces), "Array sizes don't
static GLenum Primitives[] { static GLenum Primitives[] {
GL_POINTS, GL_POINTS,
GL_LINES, GL_LINES,
GL_TRIANGLES GL_LINES_ADJACENCY,
GL_TRIANGLES,
GL_TRIANGLES_ADJACENCY,
GL_LINE_STRIP,
GL_TRIANGLE_STRIP,
}; };
static_assert(std::enum_value(Primitive::Max) == lengthof(Primitives), "Array sizes don't match Max"); static_assert(std::enum_value(Primitive::Max) == lengthof(Primitives), "Array sizes don't match Max");

View File

@ -75,8 +75,6 @@ else()
target_compile_options(${LIB} PRIVATE -O3) target_compile_options(${LIB} PRIVATE -O3)
endif() endif()
generate_compute_shaders(voxel meshextractor)
set(TEST_SRCS set(TEST_SRCS
tests/AbstractVoxelTest.h tests/AbstractVoxelTest.h
tests/AbstractVoxFormatTest.h tests/AbstractVoxFormatTest.cpp tests/AbstractVoxFormatTest.h tests/AbstractVoxFormatTest.cpp

View File

@ -115,9 +115,8 @@ void OctreeRenderer::renderOctreeNode(const video::Camera& camera, RenderOctreeN
const int numIndices = renderNode->_vb.elements(renderNode->_indexBuffer, 1, sizeof(voxel::IndexType)); const int numIndices = renderNode->_vb.elements(renderNode->_indexBuffer, 1, sizeof(voxel::IndexType));
if (numIndices > 0 && renderNode->_renderThisNode) { if (numIndices > 0 && renderNode->_renderThisNode) {
if (camera.isVisible(renderNode->_aabb)) { if (camera.isVisible(renderNode->_aabb)) {
renderNode->_vb.bind(); video::ScopedVertexBuffer scopedBuf(renderNode->_vb);
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices); video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices);
renderNode->_vb.unbind();
} }
} }

View File

@ -220,7 +220,7 @@ void RawVolumeRenderer::render(const video::Camera& camera) {
if (nIndices == 0) { if (nIndices == 0) {
continue; continue;
} }
core_assert_always(_vertexBuffer[idx].bind()); video::ScopedVertexBuffer scopedBuf(_vertexBuffer[idx]);
_shadowMapShader.setModel(glm::translate(_offsets[idx])); _shadowMapShader.setModel(glm::translate(_offsets[idx]));
for (int i = 0; i < maxDepthBuffers; ++i) { for (int i = 0; i < maxDepthBuffers; ++i) {
_depthBuffer.bindTexture(i); _depthBuffer.bindTexture(i);
@ -228,7 +228,6 @@ void RawVolumeRenderer::render(const video::Camera& camera) {
static_assert(sizeof(voxel::IndexType) == sizeof(uint32_t), "Index type doesn't match"); static_assert(sizeof(voxel::IndexType) == sizeof(uint32_t), "Index type doesn't match");
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, nIndices); video::drawElements<voxel::IndexType>(video::Primitive::Triangles, nIndices);
} }
_vertexBuffer[idx].unbind();
} }
video::cullFace(video::Face::Back); video::cullFace(video::Face::Back);
if (oldBlend) { if (oldBlend) {
@ -255,11 +254,10 @@ void RawVolumeRenderer::render(const video::Camera& camera) {
if (nIndices == 0) { if (nIndices == 0) {
continue; continue;
} }
core_assert_always(_vertexBuffer[idx].bind()); video::ScopedVertexBuffer scopedBuf(_vertexBuffer[idx]);
_worldShader.setModel(glm::translate(_offsets[idx])); _worldShader.setModel(glm::translate(_offsets[idx]));
static_assert(sizeof(voxel::IndexType) == sizeof(uint32_t), "Index type doesn't match"); static_assert(sizeof(voxel::IndexType) == sizeof(uint32_t), "Index type doesn't match");
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, nIndices); video::drawElements<voxel::IndexType>(video::Primitive::Triangles, nIndices);
_vertexBuffer[idx].unbind();
} }
} }
_whiteTexture->unbind(); _whiteTexture->unbind();

View File

@ -339,9 +339,8 @@ bool WorldRenderer::renderOpaqueBuffers() {
if (numIndices == 0u) { if (numIndices == 0u) {
return false; return false;
} }
_opaqueBuffer.bind(); video::ScopedVertexBuffer scopedBuf(_opaqueBuffer);
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices); video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices);
_opaqueBuffer.unbind();
return true; return true;
} }
@ -350,9 +349,8 @@ bool WorldRenderer::renderWaterBuffers() {
if (numIndices == 0u) { if (numIndices == 0u) {
return false; return false;
} }
_waterBuffer.bind(); video::ScopedVertexBuffer scopedBuf(_waterBuffer);
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices); video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices);
_waterBuffer.unbind();
return true; return true;
} }
@ -364,7 +362,7 @@ int WorldRenderer::renderPlants(const std::list<PlantBuffer*>& vbos, int* vertic
continue; continue;
} }
vbo->vb.bind(); video::ScopedVertexBuffer scopedBuf(vbo->vb);
if (vbo->amount == 1) { if (vbo->amount == 1) {
video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices); video::drawElements<voxel::IndexType>(video::Primitive::Triangles, numIndices);
} else { } else {
@ -557,7 +555,7 @@ int WorldRenderer::renderWorld(const video::Camera& camera, int* vertices) {
_shadowMapRenderShader.setNear(camera.nearPlane()); _shadowMapRenderShader.setNear(camera.nearPlane());
// bind buffers // bind buffers
core_assert_always(_shadowMapDebugBuffer.bind()); video::ScopedVertexBuffer scopedBuf(_shadowMapDebugBuffer);
// configure shadow map texture // configure shadow map texture
video::bindTexture(video::TextureUnit::Zero, _depthBuffer); video::bindTexture(video::TextureUnit::Zero, _depthBuffer);
@ -578,9 +576,6 @@ int WorldRenderer::renderWorld(const video::Camera& camera, int* vertices) {
if (_depthBuffer.depthCompare()) { if (_depthBuffer.depthCompare()) {
video::setupDepthCompareTexture(video::TextureUnit::Zero, _depthBuffer.textureType(), _depthBuffer.texture()); video::setupDepthCompareTexture(video::TextureUnit::Zero, _depthBuffer.textureType(), _depthBuffer.texture());
} }
// unbind buffer
_shadowMapDebugBuffer.unbind();
} }
if (_renderAABBs->boolVal()) { if (_renderAABBs->boolVal()) {

View File

@ -3,6 +3,7 @@ add_subdirectory(testmesh)
add_subdirectory(testtexture) add_subdirectory(testtexture)
add_subdirectory(testplane) add_subdirectory(testplane)
add_subdirectory(testglslcomp) add_subdirectory(testglslcomp)
add_subdirectory(testglslgeom)
add_subdirectory(testimgui) add_subdirectory(testimgui)
add_subdirectory(testnuklear) add_subdirectory(testnuklear)
add_subdirectory(testluaui) add_subdirectory(testluaui)

View File

@ -15,11 +15,10 @@ void TestDepthBuffer::doRender() {
const int quadHeight = (int) (height / 3.0f); const int quadHeight = (int) (height / 3.0f);
video::ScopedShader scopedShader(_shadowMapRenderShader); video::ScopedShader scopedShader(_shadowMapRenderShader);
video::ScopedViewPort scopedViewport(width - quadWidth, 0, quadWidth, quadHeight); video::ScopedViewPort scopedViewport(width - quadWidth, 0, quadWidth, quadHeight);
core_assert_always(_texturedFullscreenQuad.bind()); video::ScopedVertexBuffer scopedBuf(_texturedFullscreenQuad);
video::bindTexture(video::TextureUnit::Zero, _depthBuffer); video::bindTexture(video::TextureUnit::Zero, _depthBuffer);
_shadowMapRenderShader.setShadowmap(video::TextureUnit::Zero); _shadowMapRenderShader.setShadowmap(video::TextureUnit::Zero);
video::drawArrays(video::Primitive::Triangles, _texturedFullscreenQuad.elements(0)); video::drawArrays(video::Primitive::Triangles, _texturedFullscreenQuad.elements(0));
_texturedFullscreenQuad.unbind();
} }
core::AppState TestDepthBuffer::onInit() { core::AppState TestDepthBuffer::onInit() {

View File

@ -0,0 +1,7 @@
project(testglslgeom)
set(SRCS
TestGLSLGeom.h TestGLSLGeom.cpp
)
engine_add_executable(TARGET ${PROJECT_NAME} SRCS ${SRCS} WINDOWED NOINSTALL)
engine_target_link_libraries(TARGET ${PROJECT_NAME} DEPENDENCIES testcore imgui)
generate_shaders(${PROJECT_NAME} test)

View File

@ -0,0 +1,80 @@
/**
* @file
*/
#include "TestGLSLGeom.h"
#include "io/Filesystem.h"
#include "core/Color.h"
#include "video/Camera.h"
#include "video/ScopedViewPort.h"
TestGLSLGeom::TestGLSLGeom(const metric::MetricPtr& metric, const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, const core::TimeProviderPtr& timeProvider) :
Super(metric, filesystem, eventBus, timeProvider) {
init(ORGANISATION, "testglslgeom");
}
core::AppState TestGLSLGeom::onInit() {
core::AppState state = Super::onInit();
if (state != core::AppState::Running) {
return state;
}
if (!_testShader.setup()) {
Log::error("Failed to init the compute shader");
return core::AppState::InitFailure;
}
_testShader.recordUsedUniforms(true);
struct Buf {
glm::vec4 pos{0, 0, 0, 1};
glm::vec3 color{1, 1, 1};
};
Buf buf;
int32_t bufIndex = _buffer.create(&buf, sizeof(buf));
_buffer.setMode(bufIndex, video::VertexBufferMode::Static);
video::Attribute attributePos;
attributePos.bufferIndex = bufIndex;
attributePos.index = _testShader.getLocationPos();
attributePos.size = _testShader.getComponentsPos();
attributePos.offset = offsetof(Buf, pos);
attributePos.stride = sizeof(Buf);
_buffer.addAttribute(attributePos);
video::Attribute attributeColor;
attributeColor.bufferIndex = bufIndex;
attributeColor.index = _testShader.getLocationColor();
attributeColor.size = _testShader.getComponentsColor();
attributeColor.offset = offsetof(Buf, color);
attributeColor.stride = sizeof(Buf);
_buffer.addAttribute(attributeColor);
video::clearColor(::core::Color::Black);
return state;
}
core::AppState TestGLSLGeom::onCleanup() {
core::AppState state = Super::onCleanup();
_testShader.shutdown();
_buffer.shutdown();
return state;
}
void TestGLSLGeom::onRenderUI() {
ImGui::SliderFloat("radius", &_radius, 1.0f, 20.0f);
ImGui::SliderInt("sides", &_sides, 2, _testShader.getMaxGeometryVertices());
Super::onRenderUI();
}
void TestGLSLGeom::doRender() {
video::ScopedShader scopedShd(_testShader);
_testShader.setSides(_sides);
_testShader.setRadius(_radius);
_testShader.setView(_camera.viewMatrix());
_testShader.setProjection(_camera.projectionMatrix());
video::ScopedVertexBuffer scopedBuf(_buffer);
const int elements = _buffer.elements(0, _testShader.getComponentsPos());
video::drawArrays(_testShader.getPrimitiveTypeIn(), elements);
}
TEST_APP(TestGLSLGeom)

View File

@ -0,0 +1,31 @@
/**
* @file
*/
#pragma once
#include "testcore/TestApp.h"
#include "video/VertexBuffer.h"
#include "TestglslgeomShaders.h"
/**
* @brief Visual test for GLSL geometry shaders
*
* This test application is using a geometry shader to build a sphere from a single point.
*/
class TestGLSLGeom: public TestApp {
private:
using Super = TestApp;
shader::TestShader _testShader;
video::VertexBuffer _buffer;
int _sides = 16;
float _radius = 10.0f;
void doRender() override;
public:
TestGLSLGeom(const metric::MetricPtr& metric, const io::FilesystemPtr& filesystem, const core::EventBusPtr& eventBus, const core::TimeProviderPtr& timeProvider);
virtual void onRenderUI() override;
virtual core::AppState onInit() override;
virtual core::AppState onCleanup() override;
};

View File

@ -171,9 +171,6 @@ void TestShapeBuilder::onRenderUI() {
ImGui::Separator(); ImGui::Separator();
ImGui::Checkbox("Render Axis", &_renderAxis);
ImGui::Checkbox("Render Plane", &_renderPlane);
if (ImGui::Button("Clear")) { if (ImGui::Button("Clear")) {
for (int i = 0; i < _meshCount; ++i) { for (int i = 0; i < _meshCount; ++i) {
_shapeRenderer.deleteMesh(_meshes[i]); _shapeRenderer.deleteMesh(_meshes[i]);

View File

@ -41,6 +41,7 @@ core::AppState ComputeShaderTool::onRunning() {
_shaderDirectory = getArgVal("--shaderdir"); _shaderDirectory = getArgVal("--shaderdir");
_sourceDirectory = getArgVal("--sourcedir", _sourceDirectory = getArgVal("--sourcedir",
_filesystem->basePath() + "src/modules/" + _namespaceSrc + "/"); _filesystem->basePath() + "src/modules/" + _namespaceSrc + "/");
_postfix = getArgVal("--postfix", "");
if (!core::string::endsWith(_shaderDirectory, "/")) { if (!core::string::endsWith(_shaderDirectory, "/")) {
_shaderDirectory = _shaderDirectory + "/"; _shaderDirectory = _shaderDirectory + "/";
@ -68,7 +69,7 @@ core::AppState ComputeShaderTool::onRunning() {
return core::AppState::Cleanup; return core::AppState::Cleanup;
} }
const std::string& templateShader = filesystem()->load(_shaderTemplateFile); const std::string& templateShader = filesystem()->load(_shaderTemplateFile);
if (!computeshadertool::generateSrc(filesystem(), templateShader, _name, _namespaceSrc, _shaderDirectory, _sourceDirectory, _kernels, _structs)) { if (!computeshadertool::generateSrc(filesystem(), templateShader, _name, _namespaceSrc, _shaderDirectory, _sourceDirectory, _kernels, _structs, _postfix)) {
_exitCode = 100; _exitCode = 100;
return core::AppState::Cleanup; return core::AppState::Cleanup;
} }

View File

@ -31,6 +31,7 @@ private:
protected: protected:
std::string _namespaceSrc; std::string _namespaceSrc;
std::string _sourceDirectory; std::string _sourceDirectory;
std::string _postfix;
std::string _shaderDirectory; std::string _shaderDirectory;
std::string _computeFilename; std::string _computeFilename;
std::string _shaderTemplateFile; std::string _shaderTemplateFile;

View File

@ -214,7 +214,8 @@ bool generateSrc(const io::FilesystemPtr& filesystem,
const std::string& shaderDirectory, const std::string& shaderDirectory,
const std::string& sourceDirectory, const std::string& sourceDirectory,
const std::vector<Kernel>& _kernels, const std::vector<Kernel>& _kernels,
const std::vector<Struct>& _structs) { const std::vector<Struct>& _structs,
const std::string& postfix) {
const std::string name = _name + "Shader"; const std::string name = _name + "Shader";
std::vector<std::string> shaderNameParts; std::vector<std::string> shaderNameParts;
@ -267,7 +268,7 @@ bool generateSrc(const io::FilesystemPtr& filesystem,
src = core::string::replaceAll(src, "$shutdown$", shutdown.str()); src = core::string::replaceAll(src, "$shutdown$", shutdown.str());
src = core::string::replaceAll(src, "$structs$", structs.str()); src = core::string::replaceAll(src, "$structs$", structs.str());
src = core::string::replaceAll(src, "$createkernels$", createKernels.str()); src = core::string::replaceAll(src, "$createkernels$", createKernels.str());
const std::string targetFile = sourceDirectory + filename + ".h"; const std::string targetFile = sourceDirectory + filename + ".h" + postfix;
Log::info("Generate shader bindings for %s at %s", _name.c_str(), targetFile.c_str()); Log::info("Generate shader bindings for %s at %s", _name.c_str(), targetFile.c_str());
if (!filesystem->syswrite(targetFile, src)) { if (!filesystem->syswrite(targetFile, src)) {
Log::error("Failed to write %s", targetFile.c_str()); Log::error("Failed to write %s", targetFile.c_str());

View File

@ -18,6 +18,7 @@ extern bool generateSrc(const io::FilesystemPtr& filesystem,
const std::string& sourceDirectory, const std::string& sourceDirectory,
const std::string& templateShader, const std::string& templateShader,
const std::vector<Kernel>& kernels, const std::vector<Kernel>& kernels,
const std::vector<Struct>& structs); const std::vector<Struct>& structs,
const std::string& postfix);
} }

View File

@ -32,7 +32,7 @@ static const char *convertToTexUnit(int unit) {
} }
bool generateSrc(const std::string& templateShader, const std::string& templateUniformBuffer, const ShaderStruct& shaderStruct, bool generateSrc(const std::string& templateShader, const std::string& templateUniformBuffer, const ShaderStruct& shaderStruct,
const io::FilesystemPtr& filesystem, const std::string& namespaceSrc, const std::string& sourceDirectory, const std::string& shaderDirectory) { const io::FilesystemPtr& filesystem, const std::string& namespaceSrc, const std::string& sourceDirectory, const std::string& shaderDirectory, const std::string& postfix) {
std::string src(templateShader); std::string src(templateShader);
const std::string& name = shaderStruct.name + "Shader"; const std::string& name = shaderStruct.name + "Shader";
@ -93,15 +93,30 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
attributes << "// no attributes"; attributes << "// no attributes";
} }
std::stringstream setters; std::stringstream methods;
if (uniformSize > 0 || attributeSize > 0) { if (uniformSize > 0 || attributeSize > 0) {
setters << "\n"; methods << "\n";
}
if (shaderStruct.out.layout.maxGeometryVertices > 0) {
methods << "\tint getMaxGeometryVertices() const {\n";
methods << "\t\treturn " << shaderStruct.out.layout.maxGeometryVertices << ";\n";
methods << "\t}\n\n;";
}
if (shaderStruct.out.layout.primitiveType != video::Primitive::Max) {
methods << "\tvideo::Primitive getPrimitiveTypeOut() const {\n";
methods << "\t\treturn video::Primitive::" << util::getPrimitiveTypeString(shaderStruct.out.layout.primitiveType) << ";\n";
methods << "\t}\n\n;";
}
if (shaderStruct.in.layout.primitiveType != video::Primitive::Max) {
methods << "\tvideo::Primitive getPrimitiveTypeIn() const {\n";
methods << "\t\treturn video::Primitive::" << util::getPrimitiveTypeString(shaderStruct.in.layout.primitiveType) << ";\n";
methods << "\t}\n\n;";
} }
for (int i = 0; i < uniformSize; ++i) { for (int i = 0; i < uniformSize; ++i) {
const Variable& v = shaderStruct.uniforms[i]; const Variable& v = shaderStruct.uniforms[i];
const bool isInteger = v.isSingleInteger(); const bool isInteger = v.isSingleInteger();
const std::string& uniformName = util::convertName(v.name, true); const std::string& uniformName = util::convertName(v.name, true);
setters << "\tinline bool set" << uniformName << "("; methods << "\tinline bool set" << uniformName << "(";
const Types& cType = util::resolveTypes(v.type); const Types& cType = util::resolveTypes(v.type);
auto layoutIter = shaderStruct.layouts.find(v.name); auto layoutIter = shaderStruct.layouts.find(v.name);
Layout layout; Layout layout;
@ -110,126 +125,119 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
} }
if (v.arraySize > 0 && isInteger) { if (v.arraySize > 0 && isInteger) {
setters << "const "; methods << "const ";
} else if (cType.passBy == PassBy::Reference) { } else if (cType.passBy == PassBy::Reference) {
setters << "const "; methods << "const ";
} }
setters << cType.ctype; methods << cType.ctype;
if (v.arraySize == -1 || cType.passBy == PassBy::Pointer) { if (v.arraySize == -1 || cType.passBy == PassBy::Pointer) {
setters << "*"; methods << "*";
} else if (cType.passBy == PassBy::Reference) { } else if (cType.passBy == PassBy::Reference) {
if (v.arraySize <= 0) { if (v.arraySize <= 0) {
setters << "&"; methods << "&";
} }
} else if (cType.passBy == PassBy::Value) { } else if (cType.passBy == PassBy::Value) {
} }
if (v.arraySize > 0) { if (v.arraySize > 0) {
setters << " (&" << v.name << ")[" << v.arraySize << "]"; methods << " (&" << v.name << ")[" << v.arraySize << "]";
} else { } else {
setters << " " << v.name; methods << " " << v.name;
} }
if (v.isSampler() && layout.binding != -1) { if (v.isSampler() && layout.binding != -1) {
setters << " = video::TextureUnit::" << convertToTexUnit(layout.binding); methods << " = video::TextureUnit::" << convertToTexUnit(layout.binding);
} }
if (v.arraySize == -1) { if (v.arraySize == -1) {
setters << ", int amount"; methods << ", int amount";
} }
setters << ") const {\n"; methods << ") const {\n";
setters << "\t\tconst int location = "; methods << "\t\tconst int location = ";
if (layout.location != -1) { if (layout.location != -1) {
setters << layout.location << ";\n"; methods << layout.location << ";\n";
} else { } else {
setters << "getUniformLocation(\"" << v.name << "\");\n"; methods << "getUniformLocation(\"" << v.name << "\");\n";
setters << "\t\tif (location == -1) {\n"; methods << "\t\tif (location == -1) {\n";
setters << "\t\t\treturn false;\n"; methods << "\t\t\treturn false;\n";
setters << "\t\t}\n"; methods << "\t\t}\n";
} }
setters << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize == -1 ? 2 : v.arraySize); methods << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize == -1 ? 2 : v.arraySize);
setters << "(location, " << v.name; methods << "(location, " << v.name;
if (v.arraySize > 0) { if (v.arraySize > 0) {
setters << ", " << v.arraySize; methods << ", " << v.arraySize;
} else if (v.arraySize == -1) { } else if (v.arraySize == -1) {
setters << ", amount"; methods << ", amount";
} }
setters << ");\n"; methods << ");\n";
setters << "\t\treturn true;\n"; methods << "\t\treturn true;\n";
setters << "\t}\n"; methods << "\t}\n";
if (v.isSampler()) { if (v.isSampler()) {
if (layout.binding != -1) { if (layout.binding != -1) {
setters << "\n\tinline video::TextureUnit getBound" << uniformName << "TexUnit() const {\n"; methods << "\n\tinline video::TextureUnit getBound" << uniformName << "TexUnit() const {\n";
setters << "\t\treturn video::TextureUnit::" << convertToTexUnit(layout.binding) << ";\n\t}\n"; methods << "\t\treturn video::TextureUnit::" << convertToTexUnit(layout.binding) << ";\n\t}\n";
} }
} }
if (v.isSampler() || v.isImage()) { if (v.isSampler() || v.isImage()) {
if (layout.imageFormat != video::ImageFormat::Max) { if (layout.imageFormat != video::ImageFormat::Max) {
setters << "\n\tinline video::ImageFormat getImageFormat" << uniformName << "() const {\n"; methods << "\n\tinline video::ImageFormat getImageFormat" << uniformName << "() const {\n";
setters << "\t\treturn video::ImageFormat::" << util::getImageFormatTypeString(layout.imageFormat) << ";\n\t}\n"; methods << "\t\treturn video::ImageFormat::" << util::getImageFormatTypeString(layout.imageFormat) << ";\n\t}\n";
} }
// TODO: generate texture with correct format and constraints.
}
if (layout.primitiveType != PrimitiveType::None) {
// TODO:
}
if (layout.blockLayout != BlockLayout::unknown) {
// TODO:
} }
if (layout.localSize.x != -1) { if (layout.localSize.x != -1) {
setters << "\n\tinline int getLocalSizeX() const {\n"; methods << "\n\tinline int getLocalSizeX() const {\n";
setters << "\t\treturn " << layout.localSize.x << ";\n\t}\n"; methods << "\t\treturn " << layout.localSize.x << ";\n\t}\n";
} }
if (layout.localSize.y != -1) { if (layout.localSize.y != -1) {
setters << "\n\tinline int getLocalSizeY() const {\n"; methods << "\n\tinline int getLocalSizeY() const {\n";
setters << "\t\treturn " << layout.localSize.y << ";\n\t}\n"; methods << "\t\treturn " << layout.localSize.y << ";\n\t}\n";
} }
if (layout.localSize.z != -1) { if (layout.localSize.z != -1) {
setters << "\n\tinline int getLocalSizeZ() const {\n"; methods << "\n\tinline int getLocalSizeZ() const {\n";
setters << "\t\treturn " << layout.localSize.z << ";\n\t}\n"; methods << "\t\treturn " << layout.localSize.z << ";\n\t}\n";
} }
if (v.arraySize > 0) { if (v.arraySize > 0) {
setters << "\n\tinline bool set" << uniformName << "(" << "const std::vector<" << cType.ctype << ">& var) const {\n"; methods << "\n\tinline bool set" << uniformName << "(" << "const std::vector<" << cType.ctype << ">& var) const {\n";
setters << "\t\tconst int location = getUniformLocation(\"" << v.name; methods << "\t\tconst int location = getUniformLocation(\"" << v.name;
setters << "\");\n\t\tif (location == -1) {\n"; methods << "\");\n\t\tif (location == -1) {\n";
setters << "\t\t\treturn false;\n"; methods << "\t\t\treturn false;\n";
setters << "\t\t}\n"; methods << "\t\t}\n";
setters << "\t\tcore_assert((int)var.size() == " << v.arraySize << ");\n"; methods << "\t\tcore_assert((int)var.size() == " << v.arraySize << ");\n";
setters << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize) << "(location, &var.front(), var.size());\n"; methods << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize) << "(location, &var.front(), var.size());\n";
setters << "\t\treturn true;\n"; methods << "\t\treturn true;\n";
setters << "\t}\n"; methods << "\t}\n";
} else if (cType.type == Variable::Type::VEC2 || cType.type == Variable::Type::VEC3 || cType.type == Variable::Type::VEC4) { } else if (cType.type == Variable::Type::VEC2 || cType.type == Variable::Type::VEC3 || cType.type == Variable::Type::VEC4) {
setters << "\n\tinline bool set" << uniformName << "(" << "const std::vector<float>& var) const {\n"; methods << "\n\tinline bool set" << uniformName << "(" << "const std::vector<float>& var) const {\n";
setters << "\t\tconst int location = getUniformLocation(\"" << v.name; methods << "\t\tconst int location = getUniformLocation(\"" << v.name;
setters << "\");\n\t\tif (location == -1) {\n"; methods << "\");\n\t\tif (location == -1) {\n";
setters << "\t\t\treturn false;\n"; methods << "\t\t\treturn false;\n";
setters << "\t\t}\n"; methods << "\t\t}\n";
setters << "\t\tcore_assert(int(var.size()) % " << cType.components << " == 0);\n"; methods << "\t\tcore_assert(int(var.size()) % " << cType.components << " == 0);\n";
setters << "\t\tsetUniformfv(location, &var.front(), " << cType.components << ", " << cType.components << ");\n"; methods << "\t\tsetUniformfv(location, &var.front(), " << cType.components << ", " << cType.components << ");\n";
setters << "\t\treturn true;\n"; methods << "\t\treturn true;\n";
setters << "\t}\n"; methods << "\t}\n";
} }
if (i < uniformSize- - 2) { if (i < uniformSize- - 2) {
setters << "\n"; methods << "\n";
} }
#if 0 #if 0
if (v.arraySize == -1 || v.arraySize > 1) { if (v.arraySize == -1 || v.arraySize > 1) {
setters << "\tinline bool set" << uniformName << "("; methods << "\tinline bool set" << uniformName << "(";
const Types& cType = util::getTypes(v.type); const Types& cType = util::getTypes(v.type);
setters << "const std::vector<" << cType.ctype << ">& " << v.name << ") const {\n"; methods << "const std::vector<" << cType.ctype << ">& " << v.name << ") const {\n";
setters << "\t\tif (!hasUniform(\"" << v.name << "[0]\")) {\n"; methods << "\t\tif (!hasUniform(\"" << v.name << "[0]\")) {\n";
setters << "\t\t\treturn false;\n"; methods << "\t\t\treturn false;\n";
setters << "\t\t}\n"; methods << "\t\t}\n";
setters << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize == -1 ? 2 : v.arraySize); methods << "\t\tsetUniform" << util::uniformSetterPostfix(v.type, v.arraySize == -1 ? 2 : v.arraySize);
setters << "(\"" << v.name << "[0]\", &" << v.name << "[0], " << v.name << ".size());\n"; methods << "(\"" << v.name << "[0]\", &" << v.name << "[0], " << v.name << ".size());\n";
setters << "\t\treturn true;\n"; methods << "\t\treturn true;\n";
setters << "\t}\n"; methods << "\t}\n";
if (i < uniformSize- - 2) { if (i < uniformSize- - 2) {
setters << "\n"; methods << "\n";
} }
} }
#endif #endif
@ -238,70 +246,70 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
const Variable& v = shaderStruct.attributes[i]; const Variable& v = shaderStruct.attributes[i];
const std::string& attributeName = util::convertName(v.name, true); const std::string& attributeName = util::convertName(v.name, true);
const bool isInt = v.isInteger(); const bool isInt = v.isInteger();
setters << "\tinline bool init" << attributeName << "Custom(size_t stride = "; methods << "\tinline bool init" << attributeName << "Custom(size_t stride = ";
setters << "sizeof(" << util::resolveTypes(v.type).ctype << ")"; methods << "sizeof(" << util::resolveTypes(v.type).ctype << ")";
setters << ", const void* pointer = nullptr, video::DataType type = "; methods << ", const void* pointer = nullptr, video::DataType type = ";
if (isInt) { if (isInt) {
setters << "video::DataType::Int"; methods << "video::DataType::Int";
} else { } else {
setters << "video::DataType::Float"; methods << "video::DataType::Float";
} }
setters << ", int size = "; methods << ", int size = ";
setters << util::resolveTypes(v.type).components << ", "; methods << util::resolveTypes(v.type).components << ", ";
setters << "bool isInt = "; methods << "bool isInt = ";
setters << (isInt ? "true" : "false"); methods << (isInt ? "true" : "false");
setters << ", bool normalize = false) const {\n"; methods << ", bool normalize = false) const {\n";
setters << "\t\tconst int loc = enableVertexAttributeArray(\"" << v.name << "\");\n"; methods << "\t\tconst int loc = enableVertexAttributeArray(\"" << v.name << "\");\n";
setters << "\t\tif (loc == -1) {\n"; methods << "\t\tif (loc == -1) {\n";
setters << "\t\t\treturn false;\n"; methods << "\t\t\treturn false;\n";
setters << "\t\t}\n"; methods << "\t\t}\n";
setters << "\t\tif (isInt) {\n"; methods << "\t\tif (isInt) {\n";
setters << "\t\t\tsetVertexAttributeInt(loc, size, type, stride, pointer);\n"; methods << "\t\t\tsetVertexAttributeInt(loc, size, type, stride, pointer);\n";
setters << "\t\t} else {\n"; methods << "\t\t} else {\n";
setters << "\t\t\tsetVertexAttribute(loc, size, type, normalize, stride, pointer);\n"; methods << "\t\t\tsetVertexAttribute(loc, size, type, normalize, stride, pointer);\n";
setters << "\t\t}\n"; methods << "\t\t}\n";
setters << "\t\treturn true;\n"; methods << "\t\treturn true;\n";
setters << "\t}\n\n"; methods << "\t}\n\n";
setters << "\tinline int getLocation" << attributeName << "() const {\n"; methods << "\tinline int getLocation" << attributeName << "() const {\n";
setters << "\t\treturn getAttributeLocation(\"" << v.name << "\");\n"; methods << "\t\treturn getAttributeLocation(\"" << v.name << "\");\n";
setters << "\t}\n\n"; methods << "\t}\n\n";
setters << "\tinline int getComponents" << attributeName << "() const {\n"; methods << "\tinline int getComponents" << attributeName << "() const {\n";
setters << "\t\treturn getAttributeComponents(\"" << v.name << "\");\n"; methods << "\t\treturn getAttributeComponents(\"" << v.name << "\");\n";
setters << "\t}\n\n"; methods << "\t}\n\n";
setters << "\tinline bool init" << attributeName << "() const {\n"; methods << "\tinline bool init" << attributeName << "() const {\n";
setters << "\t\tconst int loc = enableVertexAttributeArray(\"" << v.name << "\");\n"; methods << "\t\tconst int loc = enableVertexAttributeArray(\"" << v.name << "\");\n";
setters << "\t\tif (loc == -1) {\n"; methods << "\t\tif (loc == -1) {\n";
setters << "\t\t\treturn false;\n"; methods << "\t\t\treturn false;\n";
setters << "\t\t}\n"; methods << "\t\t}\n";
setters << "\t\tconst size_t stride = sizeof(" << util::resolveTypes(v.type).ctype << ");\n"; methods << "\t\tconst size_t stride = sizeof(" << util::resolveTypes(v.type).ctype << ");\n";
setters << "\t\tconst void* pointer = nullptr;\n"; methods << "\t\tconst void* pointer = nullptr;\n";
setters << "\t\tconst video::DataType type = "; methods << "\t\tconst video::DataType type = ";
if (isInt) { if (isInt) {
setters << "video::DataType::Int"; methods << "video::DataType::Int";
} else { } else {
setters << "video::DataType::Float"; methods << "video::DataType::Float";
} }
setters << ";\n"; methods << ";\n";
setters << "\t\tconst int size = getAttributeComponents(loc);\n"; methods << "\t\tconst int size = getAttributeComponents(loc);\n";
if (isInt) { if (isInt) {
setters << "\t\tsetVertexAttributeInt(loc, size, type, stride, pointer);\n"; methods << "\t\tsetVertexAttributeInt(loc, size, type, stride, pointer);\n";
} else { } else {
setters << "\t\tsetVertexAttribute(loc, size, type, false, stride, pointer);\n"; methods << "\t\tsetVertexAttribute(loc, size, type, false, stride, pointer);\n";
} }
setters << "\t\treturn true;\n"; methods << "\t\treturn true;\n";
setters << "\t}\n\n"; methods << "\t}\n\n";
setters << "\tinline bool set" << attributeName << "Divisor(uint32_t divisor) const {\n"; methods << "\tinline bool set" << attributeName << "Divisor(uint32_t divisor) const {\n";
setters << "\t\tconst int location = getAttributeLocation(\"" << v.name << "\");\n"; methods << "\t\tconst int location = getAttributeLocation(\"" << v.name << "\");\n";
setters << "\t\treturn setDivisor(location, divisor);\n"; methods << "\t\treturn setDivisor(location, divisor);\n";
setters << "\t}\n"; methods << "\t}\n";
if (i < attributeSize - 1) { if (i < attributeSize - 1) {
setters << "\n"; methods << "\n";
} }
} }
if (!shaderStruct.uniformBlocks.empty()) { if (!shaderStruct.uniformBlocks.empty()) {
setters << "\n"; methods << "\n";
} }
std::stringstream ub; std::stringstream ub;
std::stringstream shutdown; std::stringstream shutdown;
@ -354,17 +362,17 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
ub << "\n\tinline operator const video::UniformBuffer&() const {\n"; ub << "\n\tinline operator const video::UniformBuffer&() const {\n";
ub << "\t\treturn _" << uniformBufferName << ";\n"; ub << "\t\treturn _" << uniformBufferName << ";\n";
ub << "\t}\n"; ub << "\t}\n";
setters << "\t/**\n"; methods << "\t/**\n";
setters << "\t * @brief The the uniform buffer for the uniform block " << ubuf.name << "\n"; methods << "\t * @brief The the uniform buffer for the uniform block " << ubuf.name << "\n";
setters << "\t */\n"; methods << "\t */\n";
setters << "\tinline bool set" << uniformBufferStructName << "(const video::UniformBuffer& buf) {\n"; methods << "\tinline bool set" << uniformBufferStructName << "(const video::UniformBuffer& buf) {\n";
setters << "\t\treturn setUniformBuffer(\"" << ubuf.name << "\", buf);\n"; methods << "\t\treturn setUniformBuffer(\"" << ubuf.name << "\", buf);\n";
setters << "\t}\n"; methods << "\t}\n";
std::string generatedUb = core::string::replaceAll(templateUniformBuffer, "$name$", uniformBufferStructName); std::string generatedUb = core::string::replaceAll(templateUniformBuffer, "$name$", uniformBufferStructName);
generatedUb = core::string::replaceAll(generatedUb, "$namespace$", namespaceSrc); generatedUb = core::string::replaceAll(generatedUb, "$namespace$", namespaceSrc);
generatedUb = core::string::replaceAll(generatedUb, "$uniformbuffers$", ub.str()); generatedUb = core::string::replaceAll(generatedUb, "$uniformbuffers$", ub.str());
generatedUb = core::string::replaceAll(generatedUb, "$setters$", ""); generatedUb = core::string::replaceAll(generatedUb, "$methods$", "");
generatedUb = core::string::replaceAll(generatedUb, "$shutdown$", shutdown.str()); generatedUb = core::string::replaceAll(generatedUb, "$shutdown$", shutdown.str());
const std::string targetFileUb = sourceDirectory + uniformBufferStructName + ".h"; const std::string targetFileUb = sourceDirectory + uniformBufferStructName + ".h";
@ -379,10 +387,10 @@ bool generateSrc(const std::string& templateShader, const std::string& templateU
} }
src = core::string::replaceAll(src, "$attributes$", attributes.str()); src = core::string::replaceAll(src, "$attributes$", attributes.str());
src = core::string::replaceAll(src, "$setters$", setters.str()); src = core::string::replaceAll(src, "$methods$", methods.str());
src = core::string::replaceAll(src, "$includes$", includes.str()); src = core::string::replaceAll(src, "$includes$", includes.str());
const std::string targetFile = sourceDirectory + filename + ".h"; const std::string targetFile = sourceDirectory + filename + ".h" + postfix;
Log::debug("Generate shader bindings for %s at %s", shaderStruct.name.c_str(), targetFile.c_str()); Log::debug("Generate shader bindings for %s at %s", shaderStruct.name.c_str(), targetFile.c_str());
if (!filesystem->syswrite(targetFile, src)) { if (!filesystem->syswrite(targetFile, src)) {
Log::error("Failed to write %s", targetFile.c_str()); Log::error("Failed to write %s", targetFile.c_str());

View File

@ -11,6 +11,6 @@
namespace shadertool { namespace shadertool {
extern bool generateSrc(const std::string& templateShader, const std::string& templateUniformBuffer, const ShaderStruct& shaderStruct, extern bool generateSrc(const std::string& templateShader, const std::string& templateUniformBuffer, const ShaderStruct& shaderStruct,
const io::FilesystemPtr& filesystem, const std::string& namespaceSrc, const std::string& sourceDirectory, const std::string& shaderDirectory); const io::FilesystemPtr& filesystem, const std::string& namespaceSrc, const std::string& sourceDirectory, const std::string& shaderDirectory, const std::string& postfix);
} }

View File

@ -17,8 +17,7 @@
namespace shadertool { namespace shadertool {
static const char* PrimitiveTypeStr[] { static const char* PrimitiveStr[] {
nullptr,
"points", "points",
"lines", "lines",
"lines_adjacency", "lines_adjacency",
@ -27,18 +26,15 @@ static const char* PrimitiveTypeStr[] {
"line_strip", "line_strip",
"triangle_strip" "triangle_strip"
}; };
static_assert(lengthof(PrimitiveTypeStr) == std::enum_value(PrimitiveType::Max), "PrimitiveTypeStr doesn't match enum"); static_assert(lengthof(PrimitiveStr) == std::enum_value(video::Primitive::Max), "PrimitiveStr doesn't match enum");
static PrimitiveType layoutPrimitiveType(const std::string& token) { static video::Primitive layoutPrimitiveType(const std::string& token) {
for (int i = 0; i < lengthof(PrimitiveTypeStr); ++i) { for (int i = 0; i < lengthof(PrimitiveStr); ++i) {
if (PrimitiveTypeStr[i] == nullptr) { if (token == PrimitiveStr[i]) {
continue; return (video::Primitive)i;
}
if (token == PrimitiveTypeStr[i]) {
return (PrimitiveType)i;
} }
} }
return PrimitiveType::None; return video::Primitive::Max;
} }
bool parseLayout(TokenIterator& tok, Layout& layout) { bool parseLayout(TokenIterator& tok, Layout& layout) {
@ -156,7 +152,12 @@ bool parseLayout(TokenIterator& tok, Layout& layout) {
if (format != video::ImageFormat::Max) { if (format != video::ImageFormat::Max) {
layout.imageFormat = format; layout.imageFormat = format;
} else { } else {
Log::warn("Unknown token given for layout: %s (line %i)", token.c_str(), tok.line()); video::Primitive primitiveType = layoutPrimitiveType(token);
if (primitiveType != video::Primitive::Max) {
layout.primitiveType = primitiveType;
} else {
Log::warn("Unknown token given for layout: %s (line %i)", token.c_str(), tok.line());
}
} }
} }
} while (token != ")"); } while (token != ")");
@ -216,6 +217,10 @@ bool parse(ShaderStruct& shaderStruct, const std::string& shaderFile, const std:
Log::warn("SSBO not supported"); Log::warn("SSBO not supported");
} else if (token == "uniform") { } else if (token == "uniform") {
v = &shaderStruct.uniforms; v = &shaderStruct.uniforms;
} else if (hasLayout && token == "in") {
shaderStruct.in.layout = layout;
} else if (hasLayout && token == "out") {
shaderStruct.out.layout = layout;
} else if (uniformBlock) { } else if (uniformBlock) {
if (token == "}") { if (token == "}") {
uniformBlock = false; uniformBlock = false;

View File

@ -62,7 +62,7 @@ $uniformarrayinfo$
} }
} }
$setters$ $methods$
}; };
typedef std::shared_ptr<$name$> $name$Ptr; typedef std::shared_ptr<$name$> $name$Ptr;

View File

@ -95,6 +95,7 @@ core::AppState ShaderTool::onRunning() {
_shaderDirectory = getArgVal("--shaderdir"); _shaderDirectory = getArgVal("--shaderdir");
_sourceDirectory = getArgVal("--sourcedir", _sourceDirectory = getArgVal("--sourcedir",
_filesystem->basePath() + "src/modules/" + _namespaceSrc + "/"); _filesystem->basePath() + "src/modules/" + _namespaceSrc + "/");
_postfix = getArgVal("--postfix", "");
if (!core::string::endsWith(_shaderDirectory, "/")) { if (!core::string::endsWith(_shaderDirectory, "/")) {
_shaderDirectory = _shaderDirectory + "/"; _shaderDirectory = _shaderDirectory + "/";
@ -138,7 +139,7 @@ core::AppState ShaderTool::onRunning() {
} }
if (!shadertool::generateSrc(templateShader, templateUniformBuffer, _shaderStruct, if (!shadertool::generateSrc(templateShader, templateUniformBuffer, _shaderStruct,
filesystem(), _namespaceSrc, _sourceDirectory, _shaderDirectory)) { filesystem(), _namespaceSrc, _sourceDirectory, _shaderDirectory, _postfix)) {
Log::error("Failed to generate shader source for %s", _shaderfile.c_str()); Log::error("Failed to generate shader source for %s", _shaderfile.c_str());
_exitCode = 1; _exitCode = 1;
return core::AppState::Cleanup; return core::AppState::Cleanup;
@ -199,7 +200,7 @@ core::AppState ShaderTool::onRunning() {
} }
if (!shadertool::generateSrc(templateShader, templateUniformBuffer, _shaderStruct, if (!shadertool::generateSrc(templateShader, templateUniformBuffer, _shaderStruct,
filesystem(), _namespaceSrc, _sourceDirectory, _shaderDirectory)) { filesystem(), _namespaceSrc, _sourceDirectory, _shaderDirectory, _postfix)) {
Log::error("Failed to generate shader source for %s", _shaderfile.c_str()); Log::error("Failed to generate shader source for %s", _shaderfile.c_str());
_exitCode = 1; _exitCode = 1;
return core::AppState::Cleanup; return core::AppState::Cleanup;

View File

@ -19,6 +19,7 @@ protected:
ShaderStruct _shaderStruct; ShaderStruct _shaderStruct;
std::string _namespaceSrc; std::string _namespaceSrc;
std::string _sourceDirectory; std::string _sourceDirectory;
std::string _postfix;
std::string _shaderDirectory; std::string _shaderDirectory;
std::string _shaderTemplateFile; std::string _shaderTemplateFile;
std::string _glslangValidatorBin; std::string _glslangValidatorBin;

View File

@ -23,18 +23,6 @@ enum class BlockLayout {
std430 std430
}; };
enum class PrimitiveType {
None,
Points,
Lines,
LinesAdjacency,
Triangles,
TrianglesAdjacency,
LineStrip,
TriangleStrip,
Max
};
struct Variable { struct Variable {
enum Type { enum Type {
DOUBLE = 0, FLOAT, UNSIGNED_INT, INT, BOOL, DOUBLE = 0, FLOAT, UNSIGNED_INT, INT, BOOL,
@ -93,7 +81,7 @@ struct Layout {
bool pixelCenterInteger = false; // 4.0 bool pixelCenterInteger = false; // 4.0
bool earlyFragmentTests = false; // 4.2 bool earlyFragmentTests = false; // 4.2
glm::ivec3 localSize { -1 }; glm::ivec3 localSize { -1 };
PrimitiveType primitiveType = PrimitiveType::None; video::Primitive primitiveType = video::Primitive::Max;
BlockLayout blockLayout = BlockLayout::unknown; BlockLayout blockLayout = BlockLayout::unknown;
video::ImageFormat imageFormat = video::ImageFormat::Max; video::ImageFormat imageFormat = video::ImageFormat::Max;
@ -110,12 +98,21 @@ struct ImageFormatType {
const char* ctype; const char* ctype;
}; };
struct PrimitiveType {
video::Primitive type;
const char* str;
};
struct UniformBlock { struct UniformBlock {
std::string name; std::string name;
std::vector<Variable> members; std::vector<Variable> members;
Layout layout; Layout layout;
}; };
struct InOut {
Layout layout;
};
struct ShaderStruct { struct ShaderStruct {
std::string name; std::string name;
std::string filename; std::string filename;
@ -129,4 +126,6 @@ struct ShaderStruct {
std::vector<Variable> varyings; std::vector<Variable> varyings;
// fragment only // fragment only
std::vector<Variable> outs; std::vector<Variable> outs;
InOut in;
InOut out;
}; };

View File

@ -21,7 +21,7 @@ $uniformbuffers$
void shutdown() { void shutdown() {
$shutdown$ $shutdown$
} }
$setters$ $methods$
}; };
}; };

View File

@ -143,6 +143,29 @@ const char* getImageFormatTypeString(video::ImageFormat format) {
return nullptr; return nullptr;
} }
#define PRIMITVEENTRY(x) {video::Primitive::x, #x}
static const PrimitiveType cPrimitiveType[] = {
PRIMITVEENTRY(Points),
PRIMITVEENTRY(Lines),
PRIMITVEENTRY(LinesAdjacency),
PRIMITVEENTRY(Triangles),
PRIMITVEENTRY(TrianglesAdjacency),
PRIMITVEENTRY(LineStrip),
PRIMITVEENTRY(TriangleStrip)
};
#undef PRIMITVEENTRY
static_assert((size_t)video::Primitive::Max == lengthof(cPrimitiveType), "mismatch in primitive types");
const char* getPrimitiveTypeString(video::Primitive primitive) {
const int max = std::enum_value(video::Primitive::Max);
for (int i = 0; i < max; ++i) {
if (primitive == cPrimitiveType[i].type) {
return cPrimitiveType[i].str;
}
}
return nullptr;
}
std::string uniformSetterPostfix(const Variable::Type type, int amount) { std::string uniformSetterPostfix(const Variable::Type type, int amount) {
switch (type) { switch (type) {
case Variable::MAX: case Variable::MAX:

View File

@ -30,6 +30,8 @@ extern video::ImageFormat getImageFormat(const std::string& type, int line);
extern const char* getImageFormatGLType(video::ImageFormat format); extern const char* getImageFormatGLType(video::ImageFormat format);
extern const char* getImageFormatTypeString(video::ImageFormat format); extern const char* getImageFormatTypeString(video::ImageFormat format);
extern const char* getPrimitiveTypeString(video::Primitive primitive);
extern int getComponents(const Variable::Type type); extern int getComponents(const Variable::Type type);
extern Variable::Type getType(const std::string& type, int line); extern Variable::Type getType(const std::string& type, int line);