diff --git a/OgreMain/include/OgreGpuProgram.h b/OgreMain/include/OgreGpuProgram.h index b9a4cb0e05b..51d2a6332c6 100644 --- a/OgreMain/include/OgreGpuProgram.h +++ b/OgreMain/include/OgreGpuProgram.h @@ -52,10 +52,12 @@ namespace Ogre { GPT_GEOMETRY_PROGRAM, GPT_DOMAIN_PROGRAM, GPT_HULL_PROGRAM, - GPT_COMPUTE_PROGRAM + GPT_MESH_PROGRAM, // aliases with vertex + GPT_COMPUTE_PROGRAM, // aliases with fragment + GPT_TASK_PROGRAM }; enum { - GPT_COUNT = GPT_COMPUTE_PROGRAM + 1, + GPT_COUNT = GPT_TASK_PROGRAM + 1, /// max programs that can be active in a pipeline (e.g compute is separate) GPT_PIPELINE_COUNT = GPT_HULL_PROGRAM + 1 }; diff --git a/OgreMain/include/OgreRenderSystemCapabilities.h b/OgreMain/include/OgreRenderSystemCapabilities.h index 06b84527d62..b73ad412b44 100644 --- a/OgreMain/include/OgreRenderSystemCapabilities.h +++ b/OgreMain/include/OgreRenderSystemCapabilities.h @@ -171,6 +171,8 @@ namespace Ogre RSC_RTT_DEPTHBUFFER_RESOLUTION_LESSEQUAL = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 15), /// Supports using vertex buffers for instance data RSC_VERTEX_BUFFER_INSTANCE_DATA = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 16), + /// Supports mesh and task programs + RSC_MESH_PROGRAM = OGRE_CAPS_VALUE(CAPS_CATEGORY_COMMON_2, 17), // ***** DirectX specific caps ***** /// Is DirectX feature "per stage constants" supported diff --git a/OgreMain/include/OgreScriptCompiler.h b/OgreMain/include/OgreScriptCompiler.h index 129d29097d2..3f0fa9683f9 100644 --- a/OgreMain/include/OgreScriptCompiler.h +++ b/OgreMain/include/OgreScriptCompiler.h @@ -833,7 +833,10 @@ namespace Ogre ID_CAMERA, ID_ALIGN_TO_FACE, ID_UNORDERED_ACCESS_MIP, - + ID_MESH_PROGRAM, + ID_MESH_PROGRAM_REF, + ID_TASK_PROGRAM, + ID_TASK_PROGRAM_REF, ID_END_BUILTIN_IDS }; /** @} */ diff --git a/OgreMain/src/OgreGpuProgram.cpp b/OgreMain/src/OgreGpuProgram.cpp index 7d495a3bba9..f9a5635ecb4 100644 --- a/OgreMain/src/OgreGpuProgram.cpp +++ b/OgreMain/src/OgreGpuProgram.cpp @@ -233,7 +233,8 @@ namespace Ogre if ((getType() == GPT_GEOMETRY_PROGRAM && !caps->hasCapability(RSC_GEOMETRY_PROGRAM)) || ((getType() == GPT_DOMAIN_PROGRAM || getType() == GPT_HULL_PROGRAM) && !caps->hasCapability(RSC_TESSELLATION_PROGRAM)) || - (getType() == GPT_COMPUTE_PROGRAM && !caps->hasCapability(RSC_COMPUTE_PROGRAM))) + (getType() == GPT_COMPUTE_PROGRAM && !caps->hasCapability(RSC_COMPUTE_PROGRAM)) || + ((getType() == GPT_MESH_PROGRAM || getType() == GPT_TASK_PROGRAM) && !caps->hasCapability(RSC_MESH_PROGRAM))) { return false; } @@ -376,6 +377,10 @@ namespace Ogre return "hull"; case GPT_COMPUTE_PROGRAM: return "compute"; + case GPT_MESH_PROGRAM: + return "mesh"; + case GPT_TASK_PROGRAM: + return "task"; default: OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Unexpected GPU program type", diff --git a/OgreMain/src/OgreRenderSystemCapabilities.cpp b/OgreMain/src/OgreRenderSystemCapabilities.cpp index 278b416c0f6..59b857c649b 100644 --- a/OgreMain/src/OgreRenderSystemCapabilities.cpp +++ b/OgreMain/src/OgreRenderSystemCapabilities.cpp @@ -134,6 +134,7 @@ namespace Ogre { pLog->logMessage(" - Domain program constant 4-vectors: " + StringConverter::toString(mConstantFloatCount[GPT_DOMAIN_PROGRAM])); } + pLog->logMessage(" * Mesh programs: " + StringConverter::toString(hasCapability(RSC_MESH_PROGRAM), true)); pLog->logMessage(" * Compute programs: " + StringConverter::toString(hasCapability(RSC_COMPUTE_PROGRAM), true)); if (hasCapability(RSC_COMPUTE_PROGRAM)) { diff --git a/OgreMain/src/OgreSceneManager.cpp b/OgreMain/src/OgreSceneManager.cpp index a2606b4df30..a20cff1e32f 100644 --- a/OgreMain/src/OgreSceneManager.cpp +++ b/OgreMain/src/OgreSceneManager.cpp @@ -25,6 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------------- */ +#include "OgreGpuProgram.h" #include "OgreStableHeaders.h" #include "OgreControllerManager.h" @@ -667,7 +668,8 @@ const Pass* SceneManager::_setPass(const Pass* pass, bool shadowDerivation) { bindGpuProgram(vprog->_getBindingDelegate()); } - else if (!mDestRenderSystem->getCapabilities()->hasCapability(RSC_FIXED_FUNCTION)) + else if (!mDestRenderSystem->getCapabilities()->hasCapability(RSC_FIXED_FUNCTION) && + !pass->hasGpuProgram(GPT_MESH_PROGRAM)) { OGRE_EXCEPT(Exception::ERR_INVALID_STATE, "RenderSystem does not support FixedFunction, " @@ -686,7 +688,7 @@ const Pass* SceneManager::_setPass(const Pass* pass, bool shadowDerivation) // Set fixed-function vertex parameters } - for(auto gptype : {GPT_DOMAIN_PROGRAM, GPT_HULL_PROGRAM, GPT_GEOMETRY_PROGRAM}) + for(auto gptype : {GPT_DOMAIN_PROGRAM, GPT_HULL_PROGRAM, GPT_GEOMETRY_PROGRAM, GPT_MESH_PROGRAM, GPT_TASK_PROGRAM}) { if (pass->hasGpuProgram(gptype)) { diff --git a/OgreMain/src/OgreScriptCompiler.cpp b/OgreMain/src/OgreScriptCompiler.cpp index 7e679d47dcf..9e937acff5e 100644 --- a/OgreMain/src/OgreScriptCompiler.cpp +++ b/OgreMain/src/OgreScriptCompiler.cpp @@ -914,6 +914,8 @@ namespace Ogre mIds["tessellation_hull_program"] = ID_TESSELLATION_HULL_PROGRAM; mIds["tessellation_domain_program"] = ID_TESSELLATION_DOMAIN_PROGRAM; mIds["compute_program"] = ID_COMPUTE_PROGRAM; + mIds["mesh_program"] = ID_MESH_PROGRAM; + mIds["task_program"] = ID_TASK_PROGRAM; mIds["technique"] = ID_TECHNIQUE; mIds["pass"] = ID_PASS; mIds["texture_unit"] = ID_TEXTURE_UNIT; @@ -923,6 +925,8 @@ namespace Ogre mIds["tessellation_hull_program_ref"] = ID_TESSELLATION_HULL_PROGRAM_REF; mIds["tessellation_domain_program_ref"] = ID_TESSELLATION_DOMAIN_PROGRAM_REF; mIds["compute_program_ref"] = ID_COMPUTE_PROGRAM_REF; + mIds["mesh_program_ref"] = ID_MESH_PROGRAM_REF; + mIds["task_program_ref"] = ID_TASK_PROGRAM_REF; mIds["shadow_caster_vertex_program_ref"] = ID_SHADOW_CASTER_VERTEX_PROGRAM_REF; mIds["shadow_caster_fragment_program_ref"] = ID_SHADOW_CASTER_FRAGMENT_PROGRAM_REF; mIds["shadow_receiver_vertex_program_ref"] = ID_SHADOW_RECEIVER_VERTEX_PROGRAM_REF; diff --git a/OgreMain/src/OgreScriptTranslator.cpp b/OgreMain/src/OgreScriptTranslator.cpp index 7d40852de9d..63263d6d854 100644 --- a/OgreMain/src/OgreScriptTranslator.cpp +++ b/OgreMain/src/OgreScriptTranslator.cpp @@ -26,6 +26,7 @@ THE SOFTWARE. ----------------------------------------------------------------------------- */ +#include "OgreScriptCompiler.h" #include "OgreStableHeaders.h" #include "OgreBuiltinScriptTranslators.h" #include "OgreGpuProgramManager.h" @@ -533,6 +534,12 @@ namespace Ogre{ case ID_COMPUTE_PROGRAM: case ID_COMPUTE_PROGRAM_REF: return GPT_COMPUTE_PROGRAM; + case ID_MESH_PROGRAM: + case ID_MESH_PROGRAM_REF: + return GPT_MESH_PROGRAM; + case ID_TASK_PROGRAM: + case ID_TASK_PROGRAM_REF: + return GPT_TASK_PROGRAM; } } @@ -2212,6 +2219,8 @@ namespace Ogre{ case ID_TESSELLATION_HULL_PROGRAM_REF: case ID_TESSELLATION_DOMAIN_PROGRAM_REF: case ID_COMPUTE_PROGRAM_REF: + case ID_MESH_PROGRAM_REF: + case ID_TASK_PROGRAM_REF: translateProgramRef(getProgramType(child->id), compiler, child); break; case ID_SHADOW_CASTER_VERTEX_PROGRAM_REF: @@ -2235,6 +2244,8 @@ namespace Ogre{ case ID_TESSELLATION_HULL_PROGRAM: case ID_TESSELLATION_DOMAIN_PROGRAM: case ID_COMPUTE_PROGRAM: + case ID_MESH_PROGRAM: + case ID_TASK_PROGRAM: { // auto assign inline defined programs processNode(compiler, i); @@ -5264,7 +5275,9 @@ namespace Ogre{ obj->id == ID_GEOMETRY_PROGRAM || obj->id == ID_TESSELLATION_HULL_PROGRAM || obj->id == ID_TESSELLATION_DOMAIN_PROGRAM || - obj->id == ID_COMPUTE_PROGRAM) + obj->id == ID_COMPUTE_PROGRAM || + obj->id == ID_MESH_PROGRAM || + obj->id == ID_TASK_PROGRAM) translator = &mGpuProgramTranslator; else if(obj->id == ID_SHARED_PARAMS) translator = &mSharedParamsTranslator; diff --git a/OgreMain/src/OgreTechnique.cpp b/OgreMain/src/OgreTechnique.cpp index 183f44cfb5d..7d8cb2bf16a 100644 --- a/OgreMain/src/OgreTechnique.cpp +++ b/OgreMain/src/OgreTechnique.cpp @@ -188,7 +188,7 @@ namespace Ogre { if (!caps->hasCapability(RSC_FIXED_FUNCTION) && currPass->isProgrammable() && !currPass->hasGpuProgram(GPT_COMPUTE_PROGRAM)) { - if (!currPass->hasVertexProgram() || + if ((!currPass->hasVertexProgram() && !currPass->hasGpuProgram(GPT_MESH_PROGRAM)) || (!currPass->hasFragmentProgram() && !currPass->hasGeometryProgram())) { compileErrors << "Pass " << passNum << ": RenderSystem requires both vertex and fragment programs"; diff --git a/PlugIns/CgProgramManager/src/OgreCgFxScriptLoader.cpp b/PlugIns/CgProgramManager/src/OgreCgFxScriptLoader.cpp index 8418eaa1533..46afd30635c 100644 --- a/PlugIns/CgProgramManager/src/OgreCgFxScriptLoader.cpp +++ b/PlugIns/CgProgramManager/src/OgreCgFxScriptLoader.cpp @@ -26,6 +26,7 @@ THE SOFTWARE. ----------------------------------------------------------------------------- */ #include "OgreCgFxScriptLoader.h" +#include "OgreGpuProgram.h" #include "OgreResourceGroupManager.h" #include "OgreMaterialManager.h" #include "OgreTechnique.h" @@ -2814,6 +2815,8 @@ namespace Ogre { case GPT_COMPUTE_PROGRAM: case GPT_DOMAIN_PROGRAM: case GPT_HULL_PROGRAM: + case GPT_MESH_PROGRAM: + case GPT_TASK_PROGRAM: break; } CGstateassignment cgStateAssignment = cgGetNamedStateAssignment(cgPass, stateName); @@ -2833,6 +2836,8 @@ namespace Ogre { case GPT_COMPUTE_PROGRAM: case GPT_DOMAIN_PROGRAM: case GPT_HULL_PROGRAM: + case GPT_MESH_PROGRAM: + case GPT_TASK_PROGRAM: break; } @@ -2906,6 +2911,8 @@ namespace Ogre { case GPT_DOMAIN_PROGRAM: case GPT_COMPUTE_PROGRAM: case GPT_HULL_PROGRAM: + case GPT_MESH_PROGRAM: + case GPT_TASK_PROGRAM: break; } diff --git a/PlugIns/GLSLang/src/OgreGLSLang.cpp b/PlugIns/GLSLang/src/OgreGLSLang.cpp index 2adcc64bba6..157f500963f 100644 --- a/PlugIns/GLSLang/src/OgreGLSLang.cpp +++ b/PlugIns/GLSLang/src/OgreGLSLang.cpp @@ -317,6 +317,8 @@ static EShLanguage getShLanguage(GpuProgramType type) case GPT_HULL_PROGRAM: return EShLangTessControl; case GPT_DOMAIN_PROGRAM: return EShLangTessEvaluation; case GPT_COMPUTE_PROGRAM: return EShLangCompute; + case GPT_MESH_PROGRAM: return EShLangMeshNV; + case GPT_TASK_PROGRAM: return EShLangTaskNV; // clang-format on } @@ -331,6 +333,13 @@ GLSLangProgram::GLSLangProgram(ResourceManager* creator, const String& name, Res { setupBaseParamDictionary(); memset(&DefaultTBuiltInResource.limits, 1, sizeof(TLimits)); + + if(sizeof(TBuiltInResource) == 420) // replace with build_info.h, when it is universally available + { + // copy VK_NV_mesh_shader limits to VK_EXT_mesh_shader + memcpy(&DefaultTBuiltInResource.maxMeshViewCountNV + 1, &DefaultTBuiltInResource.maxMeshOutputVerticesNV, + 9 * sizeof(int)); + } } } @@ -412,8 +421,16 @@ void GLSLangProgram::prepareImpl() if(mSyntaxCode == "gl_spirv") shader.setEnvClient(glslang::EShClientOpenGL, glslang::EShTargetOpenGL_450); else if(mSyntaxCode == "spirv") + { shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); + if(mType == GPT_MESH_PROGRAM || mType == GPT_TASK_PROGRAM) + { + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_2); + shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4); + } + } + // minimal version is 430 for explicit uniform location, but we use latest to get all features if (!shader.parse(&DefaultTBuiltInResource, 460, false, EShMsgSpvRules)) { diff --git a/RenderSystems/Direct3D11/src/OgreD3D11HLSLProgram.cpp b/RenderSystems/Direct3D11/src/OgreD3D11HLSLProgram.cpp index 7eddf5f8878..10a33b7d7c7 100644 --- a/RenderSystems/Direct3D11/src/OgreD3D11HLSLProgram.cpp +++ b/RenderSystems/Direct3D11/src/OgreD3D11HLSLProgram.cpp @@ -859,6 +859,10 @@ namespace Ogre { case GPT_COMPUTE_PROGRAM: CreateComputeShader(); break; + case GPT_MESH_PROGRAM: + case GPT_TASK_PROGRAM: + OgreAssertDbg(false, "should never get here"); + break; } } diff --git a/RenderSystems/Direct3D11/src/OgreD3D11RenderSystem.cpp b/RenderSystems/Direct3D11/src/OgreD3D11RenderSystem.cpp index 16178edda50..39b9fdd64b9 100644 --- a/RenderSystems/Direct3D11/src/OgreD3D11RenderSystem.cpp +++ b/RenderSystems/Direct3D11/src/OgreD3D11RenderSystem.cpp @@ -2250,6 +2250,10 @@ namespace Ogre mBoundComputeProgram = static_cast(prg); } break; + case GPT_MESH_PROGRAM: + case GPT_TASK_PROGRAM: + OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Mesh and task shaders are not supported in D3D11"); + break; }; RenderSystem::bindGpuProgram(prg); diff --git a/RenderSystems/GL/src/GLSL/src/OgreGLSLProgram.cpp b/RenderSystems/GL/src/GLSL/src/OgreGLSLProgram.cpp index 68dcf8f4a33..767d64fdae8 100644 --- a/RenderSystems/GL/src/GLSL/src/OgreGLSLProgram.cpp +++ b/RenderSystems/GL/src/GLSL/src/OgreGLSLProgram.cpp @@ -208,6 +208,8 @@ namespace Ogre { case GPT_COMPUTE_PROGRAM: case GPT_DOMAIN_PROGRAM: case GPT_HULL_PROGRAM: + case GPT_MESH_PROGRAM: + case GPT_TASK_PROGRAM: break; } mGLShaderHandle = (size_t)glCreateShaderObjectARB(shaderType); diff --git a/RenderSystems/GL/src/OgreGLRenderSystem.cpp b/RenderSystems/GL/src/OgreGLRenderSystem.cpp index 09a3b6c03ee..f8cd9b77899 100644 --- a/RenderSystems/GL/src/OgreGLRenderSystem.cpp +++ b/RenderSystems/GL/src/OgreGLRenderSystem.cpp @@ -2389,6 +2389,8 @@ namespace Ogre { case GPT_COMPUTE_PROGRAM: case GPT_DOMAIN_PROGRAM: case GPT_HULL_PROGRAM: + case GPT_MESH_PROGRAM: + case GPT_TASK_PROGRAM: break; } @@ -2444,6 +2446,8 @@ namespace Ogre { case GPT_COMPUTE_PROGRAM: case GPT_DOMAIN_PROGRAM: case GPT_HULL_PROGRAM: + case GPT_MESH_PROGRAM: + case GPT_TASK_PROGRAM: break; } } diff --git a/RenderSystems/GL3Plus/src/GLSL/src/OgreGLSLSeparableProgram.cpp b/RenderSystems/GL3Plus/src/GLSL/src/OgreGLSLSeparableProgram.cpp index f22f44f7a42..23783563a87 100644 --- a/RenderSystems/GL3Plus/src/GLSL/src/OgreGLSLSeparableProgram.cpp +++ b/RenderSystems/GL3Plus/src/GLSL/src/OgreGLSLSeparableProgram.cpp @@ -67,12 +67,14 @@ namespace Ogre } } + #define GL_MESH_SHADER_BIT_NV 0x00000040 GLenum ogre2gltype[GPT_COUNT] = { GL_VERTEX_SHADER_BIT, GL_FRAGMENT_SHADER_BIT, GL_GEOMETRY_SHADER_BIT, GL_TESS_EVALUATION_SHADER_BIT, GL_TESS_CONTROL_SHADER_BIT, + GL_MESH_SHADER_BIT_NV, GL_COMPUTE_SHADER_BIT }; diff --git a/RenderSystems/GL3Plus/src/GLSL/src/OgreGLSLShader.cpp b/RenderSystems/GL3Plus/src/GLSL/src/OgreGLSLShader.cpp index 45c1b285d70..88ea9e2a2c5 100644 --- a/RenderSystems/GL3Plus/src/GLSL/src/OgreGLSLShader.cpp +++ b/RenderSystems/GL3Plus/src/GLSL/src/OgreGLSLShader.cpp @@ -235,6 +235,8 @@ namespace Ogre { /// Get OpenGL GLSL shader type from OGRE GPU program type. static GLenum getGLShaderType(GpuProgramType programType) { + #define GL_MESH_SHADER_NV 0x9559 + #define GL_TASK_SHADER_NV 0x955A switch (programType) { case GPT_VERTEX_PROGRAM: @@ -249,6 +251,10 @@ namespace Ogre { return GL_FRAGMENT_SHADER; case GPT_COMPUTE_PROGRAM: return GL_COMPUTE_SHADER; + case GPT_MESH_PROGRAM: + return GL_MESH_SHADER_NV; + case GPT_TASK_PROGRAM: + return GL_TASK_SHADER_NV; } return 0; @@ -352,6 +358,8 @@ namespace Ogre { break; case GPT_FRAGMENT_PROGRAM: case GPT_COMPUTE_PROGRAM: + case GPT_MESH_PROGRAM: + case GPT_TASK_PROGRAM: // Fragment and compute shaders do // not have standard blocks. break; diff --git a/RenderSystems/GL3Plus/src/OgreGL3PlusRenderSystem.cpp b/RenderSystems/GL3Plus/src/OgreGL3PlusRenderSystem.cpp index fe153c592dc..6069cd97600 100644 --- a/RenderSystems/GL3Plus/src/OgreGL3PlusRenderSystem.cpp +++ b/RenderSystems/GL3Plus/src/OgreGL3PlusRenderSystem.cpp @@ -418,6 +418,11 @@ namespace Ogre { // OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &workgroupInvocations)); } + if (checkExtension("GL_NV_mesh_shader")) + { + rsc->setCapability(RSC_MESH_PROGRAM); + } + if (hasMinGLVersion(4, 1) || checkExtension("GL_ARB_get_program_binary")) { GLint formats = 0; @@ -1102,6 +1107,14 @@ namespace Ogre { // OGRE_CHECK_GL_ERROR(glDrawArraysInstanced(GL_PATCHES, 0, primCount, 1)); } } + else if (mCurrentShader[GPT_MESH_PROGRAM]) + { + OgreAssert(op.indexData, "indexData required for mesh shader"); + + typedef void (APIENTRYP PFNGLDRAWMESHTASKSNVPROC) (GLuint first, GLuint count); + auto glDrawMeshTasksNV = (PFNGLDRAWMESHTASKSNVPROC)mGLSupport->getProcAddress("glDrawMeshTasksNV"); + OGRE_CHECK_GL_ERROR(glDrawMeshTasksNV(0, op.indexData->indexCount)); + } else if (op.useIndexes) { void *pBufferData = VBO_BUFFER_OFFSET(op.indexData->indexStart * diff --git a/RenderSystems/Vulkan/src/OgreVulkanDevice.cpp b/RenderSystems/Vulkan/src/OgreVulkanDevice.cpp index 303a30f52d6..cc9aac46a50 100644 --- a/RenderSystems/Vulkan/src/OgreVulkanDevice.cpp +++ b/RenderSystems/Vulkan/src/OgreVulkanDevice.cpp @@ -87,7 +87,7 @@ namespace Ogre appInfo.pEngineName = "Ogre3D Vulkan Engine"; appInfo.engineVersion = OGRE_VERSION; - appInfo.apiVersion = VK_API_VERSION_1_0; + appInfo.apiVersion = VK_API_VERSION_1_2; createInfo.pApplicationInfo = &appInfo; createInfo.enabledLayerCount = layers.size(); @@ -249,7 +249,20 @@ namespace Ogre extensions.push_back( VK_KHR_SWAPCHAIN_EXTENSION_NAME ); + VkPhysicalDeviceFeatures2 features2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}; + +#ifdef VK_EXT_mesh_shader + VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT}; + if(mRenderSystem->getCapabilities()->hasCapability(RSC_MESH_PROGRAM)) + { + meshShaderFeatures.taskShader = VK_TRUE; + meshShaderFeatures.meshShader = VK_TRUE; + features2.pNext = &meshShaderFeatures; + } +#endif + VkDeviceCreateInfo createInfo = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO}; + createInfo.pNext = &features2; createInfo.enabledExtensionCount = static_cast( extensions.size() ); createInfo.ppEnabledExtensionNames = extensions.data(); @@ -257,7 +270,7 @@ namespace Ogre createInfo.queueCreateInfoCount = static_cast( queueCreateInfo.size() ); createInfo.pQueueCreateInfos = &queueCreateInfo[0]; - createInfo.pEnabledFeatures = &mDeviceFeatures; + //features2.features = mDeviceFeatures; OGRE_VK_CHECK(vkCreateDevice(mPhysicalDevice, &createInfo, NULL, &mDevice)); diff --git a/RenderSystems/Vulkan/src/OgreVulkanProgram.cpp b/RenderSystems/Vulkan/src/OgreVulkanProgram.cpp index f67db90d7fd..80b79a1ac52 100644 --- a/RenderSystems/Vulkan/src/OgreVulkanProgram.cpp +++ b/RenderSystems/Vulkan/src/OgreVulkanProgram.cpp @@ -95,6 +95,8 @@ namespace Ogre case GPT_HULL_PROGRAM: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; case GPT_DOMAIN_PROGRAM: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; case GPT_COMPUTE_PROGRAM: return VK_SHADER_STAGE_COMPUTE_BIT; + case GPT_MESH_PROGRAM: return VK_SHADER_STAGE_MESH_BIT_NV; + case GPT_TASK_PROGRAM: return VK_SHADER_STAGE_TASK_BIT_NV; // clang-format on } return VK_SHADER_STAGE_FRAGMENT_BIT; diff --git a/RenderSystems/Vulkan/src/OgreVulkanRenderSystem.cpp b/RenderSystems/Vulkan/src/OgreVulkanRenderSystem.cpp index ff74eabdd0b..94d913ffd80 100644 --- a/RenderSystems/Vulkan/src/OgreVulkanRenderSystem.cpp +++ b/RenderSystems/Vulkan/src/OgreVulkanRenderSystem.cpp @@ -762,6 +762,14 @@ namespace Ogre } else if( extensionName == VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME ) deviceExtensions.push_back( VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME ); +#ifdef VK_EXT_mesh_shader + else if( extensionName == VK_EXT_MESH_SHADER_EXTENSION_NAME) + { + deviceExtensions.push_back( VK_EXT_MESH_SHADER_EXTENSION_NAME ); + deviceExtensions.push_back( VK_KHR_SPIRV_1_4_EXTENSION_NAME ); + mRealCapabilities->setCapability(RSC_MESH_PROGRAM); + } +#endif } } @@ -1034,7 +1042,14 @@ namespace Ogre vkCmdBindPipeline( cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); // Render to screen! - if( op.useIndexes ) + if(mProgramBound[GPT_MESH_PROGRAM]) + { +#ifdef VK_EXT_mesh_shader + OgreAssert(op.indexData, "indexData required for mesh shader"); + vkCmdDrawMeshTasksEXT(cmdBuffer, op.indexData->indexCount, 1, 1); +#endif + } + else if( op.useIndexes ) { do { @@ -1076,8 +1091,10 @@ namespace Ogre void VulkanRenderSystem::bindGpuProgram(GpuProgram* prg) { auto shader = static_cast(prg); - shaderStages[prg->getType()] = shader->getPipelineShaderStageCi(); + shaderStages[prg->getType() % GPT_PIPELINE_COUNT] = shader->getPipelineShaderStageCi(); mBoundGpuPrograms[prg->getType()] = prg->_getHash(); + + RenderSystem::bindGpuProgram(prg); } void VulkanRenderSystem::bindGpuProgramParameters( GpuProgramType gptype, const GpuProgramParametersPtr& params, diff --git a/Samples/Media/materials/programs/GLSL400/MeshProgram.glsl b/Samples/Media/materials/programs/GLSL400/MeshProgram.glsl new file mode 100644 index 00000000000..ab08b2d8fb7 --- /dev/null +++ b/Samples/Media/materials/programs/GLSL400/MeshProgram.glsl @@ -0,0 +1,51 @@ +#version 450 + +#ifndef VULKAN +#extension GL_NV_mesh_shader : require +#define gl_MeshVerticesEXT gl_MeshVerticesNV +#define SetMeshOutputsEXT(verts, prims) gl_PrimitiveCountNV = (prims) +#else +#extension GL_EXT_mesh_shader : require +#endif + +layout(local_size_x=1) in; +layout(max_vertices=4, max_primitives=2, triangles) out; + + +layout(location=0) out PerVertexData +{ + vec3 color; +} v_out[]; + + +void main() +{ + SetMeshOutputsEXT(4, 2); + + float frac = gl_WorkGroupID.x / 6.0; + + float xmin = -1.0 + frac * 2.0; + float xmax = xmin + 2.0 / (7.0); + + gl_MeshVerticesEXT[0].gl_Position = vec4(xmin, -0.5, 0.0, 1.0); // Upper Left + gl_MeshVerticesEXT[1].gl_Position = vec4(xmax, -0.5, 0.0, 1.0); // Upper Right + gl_MeshVerticesEXT[2].gl_Position = vec4(xmin, 0.5, 0.0, 1.0); // Bottom Left + gl_MeshVerticesEXT[3].gl_Position = vec4(xmax, 0.5, 0.0, 1.0); // Bottom Right + + v_out[0].color = vec3(1.0, 0.0, 0.0); + v_out[1].color = vec3(0.0, 1.0, 0.0); + v_out[2].color = vec3(0.0, 0.0, 1.0); + v_out[3].color = vec3(1.0, 1.0, 0.0); + +#ifdef VULKAN + gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2); + gl_PrimitiveTriangleIndicesEXT[1] = uvec3(2, 1, 3); +#else + gl_PrimitiveIndicesNV[0] = 0; + gl_PrimitiveIndicesNV[1] = 1; + gl_PrimitiveIndicesNV[2] = 2; + gl_PrimitiveIndicesNV[3] = 2; + gl_PrimitiveIndicesNV[4] = 1; + gl_PrimitiveIndicesNV[5] = 3; +#endif +} \ No newline at end of file diff --git a/Samples/Media/materials/programs/GLSL400/MeshShaderFp.frag b/Samples/Media/materials/programs/GLSL400/MeshShaderFp.frag new file mode 100644 index 00000000000..e2e8f06a38c --- /dev/null +++ b/Samples/Media/materials/programs/GLSL400/MeshShaderFp.frag @@ -0,0 +1,9 @@ +#version 450 +layout(location=0) out vec4 fragColour; + +layout(location=0) in vec3 colour; + +void main(void) +{ + fragColour = vec4(colour, 1); +} diff --git a/Samples/Media/materials/scripts/RasterizationOrder.material b/Samples/Media/materials/scripts/AdvancedGLSL.material similarity index 55% rename from Samples/Media/materials/scripts/RasterizationOrder.material rename to Samples/Media/materials/scripts/AdvancedGLSL.material index 09804bf183e..d55bb44d672 100644 --- a/Samples/Media/materials/scripts/RasterizationOrder.material +++ b/Samples/Media/materials/scripts/AdvancedGLSL.material @@ -1,3 +1,4 @@ +// Atomic counters shared_params CounterBuffer { shared_param_named ac uint 0 @@ -26,3 +27,27 @@ material Example/RasterizationOrder } } +// Mesh shader +fragment_program Ogre/MeshShaderFp glslang +{ + source MeshShaderFp.frag +} + +mesh_program Ogre/MeshShader glslang +{ + source MeshProgram.glsl +} + +material Example/MeshShader +{ + technique + { + pass + { + mesh_program_ref Ogre/MeshShader {} + fragment_program_ref Ogre/MeshShaderFp {} + cull_hardware none + } + } +} +