void makeSTBRun() { //start STB activateSTB(); BOOL ommitIRCommands = FALSE; if (stbActive) { if (waitForSTBToStart(2)) { //will get here if the STB was activated via PIR //mean while the user clicked OFF btn //if the STB is started we do not emit printf("Will not send IR start as device is started\r\n"); ommitIRCommands = TRUE; } } if (!ommitIRCommands) { fillCommandBuffer(IR_CMD_OFF); do { sendIRCommandBlocking(); //wait for the device to start again } while (!waitForSTBToStart(2)); } stbTVRunning = 1; }
void pumpDownCommand() { delayMs(200); fillCommandBuffer(IR_CMD_PRG_DOWN); sendIRCommandBlocking(); setupAutoIRAlarm(); }
void pumpLEDOffCommand() { delayMs(200); fillHeaderBuffer(IR_HDR_LED); fillCommandBuffer(IR_CMD_LED_OFF); sendIRCommandBlocking(); fillHeaderBuffer(IR_HDR_HANSUN); }
PRAGMA_WARNING_POP //[-------------------------------------------------------] //[ Public virtual IApplication methods ] //[-------------------------------------------------------] void VertexBuffer::onInitialization() { // Get and check the renderer instance Renderer::IRendererPtr renderer(getRenderer()); if (nullptr != renderer) { // Create the buffer manager mBufferManager = renderer->createBufferManager(); { // Create the root signature // Setup Renderer::RootSignatureBuilder rootSignature; rootSignature.initialize(0, nullptr, 0, nullptr, Renderer::RootSignatureFlags::ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); // Create the instance mRootSignature = renderer->createRootSignature(rootSignature); } // Vertex input layout static constexpr Renderer::VertexAttribute vertexAttributesLayoutVBO[] = { { // Attribute 0 // Data destination Renderer::VertexAttributeFormat::FLOAT_2, // vertexAttributeFormat (Renderer::VertexAttributeFormat) "Position", // name[32] (char) "POSITION", // semanticName[32] (char) 0, // semanticIndex (uint32_t) // Data source 0, // inputSlot (uint32_t) 0, // alignedByteOffset (uint32_t) sizeof(float) * 5, // strideInBytes (uint32_t) 0 // instancesPerElement (uint32_t) }, { // Attribute 1 // Data destination Renderer::VertexAttributeFormat::FLOAT_3, // vertexAttributeFormat (Renderer::VertexAttributeFormat) "Color", // name[32] (char) "COLOR", // semanticName[32] (char) 0, // semanticIndex (uint32_t) // Data source 0, // inputSlot (uint32_t) sizeof(float) * 2, // alignedByteOffset (uint32_t) sizeof(float) * 5, // strideInBytes (uint32_t) 0 // instancesPerElement (uint32_t) } }; const Renderer::VertexAttributes vertexAttributesVBO(static_cast<uint32_t>(GLM_COUNTOF(vertexAttributesLayoutVBO)), vertexAttributesLayoutVBO); static constexpr Renderer::VertexAttribute vertexAttributesLayoutVBOs[] = { { // Attribute 0 // Data destination Renderer::VertexAttributeFormat::FLOAT_2, // vertexAttributeFormat (Renderer::VertexAttributeFormat) "Position", // name[32] (char) "POSITION", // semanticName[32] (char) 0, // semanticIndex (uint32_t) // Data source 0, // inputSlot (uint32_t) 0, // alignedByteOffset (uint32_t) sizeof(float) * 2, // strideInBytes (uint32_t) 0 // instancesPerElement (uint32_t) }, { // Attribute 1 // Data destination Renderer::VertexAttributeFormat::FLOAT_3, // vertexAttributeFormat (Renderer::VertexAttributeFormat) "Color", // name[32] (char) "COLOR", // semanticName[32] (char) 0, // semanticIndex (uint32_t) // Data source 1, // inputSlot (uint32_t) 0, // alignedByteOffset (uint32_t) sizeof(float) * 3, // strideInBytes (uint32_t) 0 // instancesPerElement (uint32_t) } }; const Renderer::VertexAttributes vertexAttributesVBOs(static_cast<uint32_t>(GLM_COUNTOF(vertexAttributesLayoutVBOs)), vertexAttributesLayoutVBOs); // Vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. { // Create vertex array object (VAO) // Create the vertex buffer object (VBO) holding position and color data // -> Clip space vertex positions, left/bottom is (-1,-1) and right/top is (1,1) // -> Traditional normalized RGB vertex colors static constexpr float VERTEX_POSITION_COLOR[] = { // Position Color // Vertex ID Triangle on screen 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, // 0 0 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // 1 . . -0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 2 2.......1 }; Renderer::IVertexBufferPtr vertexBufferPositionColor(mBufferManager->createVertexBuffer(sizeof(VERTEX_POSITION_COLOR), VERTEX_POSITION_COLOR)); // Create vertex array object (VAO) const Renderer::VertexArrayVertexBuffer vertexArrayVertexBuffers[] = { vertexBufferPositionColor }; mVertexArrayVBO = mBufferManager->createVertexArray(vertexAttributesVBO, static_cast<uint32_t>(GLM_COUNTOF(vertexArrayVertexBuffers)), vertexArrayVertexBuffers); } { // Create vertex array object (VAO) using multiple vertex buffer object (VBO) // Create the vertex buffer object (VBO) holding color data // -> Traditional normalized RGB vertex colors static constexpr float VERTEX_COLOR[] = { // Vertex ID Triangle on screen 1.0f, 0.0f, 0.0f, // 0 0.......1 0.0f, 1.0f, 0.0f, // 1 . . 0.0f, 0.0f, 1.0f // 2 2 }; Renderer::IVertexBufferPtr vertexBufferColor(mBufferManager->createVertexBuffer(sizeof(VERTEX_COLOR), VERTEX_COLOR)); // Create the vertex buffer object (VBO) holding position data // -> Clip space vertex positions, left/bottom is (-1,-1) and right/top is (1,1) static constexpr float VERTEX_POSITION[] = { // Vertex ID Triangle on screen -0.5f, 0.0f, // 0 0.......1 1.0f, 0.0f, // 1 . . 0.0f, -1.0f // 2 2 }; Renderer::IVertexBufferPtr vertexBufferPosition(mBufferManager->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION)); // Create vertex array object (VAO) const Renderer::VertexArrayVertexBuffer vertexArrayVertexBuffers[] = { vertexBufferPosition, vertexBufferColor }; mVertexArrayVBOs = mBufferManager->createVertexArray(vertexAttributesVBOs, static_cast<uint32_t>(GLM_COUNTOF(vertexArrayVertexBuffers)), vertexArrayVertexBuffers); } { // Get the shader source code (outsourced to keep an overview) const char* vertexShaderSourceCode = nullptr; const char* fragmentShaderSourceCode = nullptr; #include "VertexBuffer_GLSL_450.h" // For Vulkan #include "VertexBuffer_GLSL_410.h" // macOS 10.11 only supports OpenGL 4.1 hence it's our OpenGL minimum #include "VertexBuffer_GLSL_ES3.h" #include "VertexBuffer_HLSL_D3D9_D3D10_D3D11_D3D12.h" #include "VertexBuffer_Null.h" Renderer::IShaderLanguage& shaderLanguage = renderer->getDefaultShaderLanguage(); { // Create pipeline state objects (PSO) using one vertex buffer object (VBO) // Create the graphics program Renderer::IGraphicsProgramPtr graphicsProgram; graphicsProgram = shaderLanguage.createGraphicsProgram( *mRootSignature, vertexAttributesVBO, shaderLanguage.createVertexShaderFromSourceCode(vertexAttributesVBO, vertexShaderSourceCode), shaderLanguage.createFragmentShaderFromSourceCode(fragmentShaderSourceCode)); // Create the graphics pipeline state objects (PSO) if (nullptr != graphicsProgram) { mGraphicsPipelineStateVBO = renderer->createGraphicsPipelineState(Renderer::GraphicsPipelineStateBuilder(mRootSignature, graphicsProgram, vertexAttributesVBO, getMainRenderTarget()->getRenderPass())); } } { // Create graphics pipeline state objects (PSO) using multiple vertex buffer object (VBO) // Create the graphics program Renderer::IGraphicsProgramPtr graphicsProgram; graphicsProgram = shaderLanguage.createGraphicsProgram( *mRootSignature, vertexAttributesVBOs, shaderLanguage.createVertexShaderFromSourceCode(vertexAttributesVBOs, vertexShaderSourceCode), shaderLanguage.createFragmentShaderFromSourceCode(fragmentShaderSourceCode)); // Create the graphics pipeline state objects (PSO) if (nullptr != graphicsProgram) { mGraphicsPipelineStateVBOs = renderer->createGraphicsPipelineState(Renderer::GraphicsPipelineStateBuilder(mRootSignature, graphicsProgram, vertexAttributesVBOs, getMainRenderTarget()->getRenderPass())); } } } // Since we're always submitting the same commands to the renderer, we can fill the command buffer once during initialization and then reuse it multiple times during runtime fillCommandBuffer(); } }
//[-------------------------------------------------------] //[ Public virtual IApplication methods ] //[-------------------------------------------------------] void FirstGeometryShader::onInitialization() { // Call the base implementation IApplicationRenderer::onInitialization(); // Get and check the renderer instance // -> Geometry shaders supported? Renderer::IRendererPtr renderer(getRenderer()); if (nullptr != renderer && renderer->getCapabilities().maximumNumberOfGsOutputVertices) { // Create the buffer manager mBufferManager = renderer->createBufferManager(); { // Create the root signature // Setup Renderer::RootSignatureBuilder rootSignature; rootSignature.initialize(0, nullptr, 0, nullptr, Renderer::RootSignatureFlags::ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); // Create the instance mRootSignature = renderer->createRootSignature(rootSignature); } // Vertex input layout const Renderer::VertexAttribute vertexAttributesLayout[] = { { // Attribute 0 // Data destination Renderer::VertexAttributeFormat::FLOAT_1, // vertexAttributeFormat (Renderer::VertexAttributeFormat) "Position", // name[32] (char) "POSITION", // semanticName[32] (char) 0, // semanticIndex (uint32_t) // Data source 0, // inputSlot (uint32_t) 0, // alignedByteOffset (uint32_t) // Data source, instancing part 0 // instancesPerElement (uint32_t) } }; const Renderer::VertexAttributes vertexAttributes(glm::countof(vertexAttributesLayout), vertexAttributesLayout); { // Create vertex array object (VAO) // Create the vertex buffer object (VBO) static const float VERTEX_POSITION[] = { // Vertex ID 42.0f // 0 }; Renderer::IVertexBufferPtr vertexBuffer(mBufferManager->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION, Renderer::BufferUsage::STATIC_DRAW)); // Create vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. const Renderer::VertexArrayVertexBuffer vertexArrayVertexBuffers[] = { { // Vertex buffer 0 vertexBuffer, // vertexBuffer (Renderer::IVertexBuffer *) sizeof(float) // strideInBytes (uint32_t) } }; mVertexArray = mBufferManager->createVertexArray(vertexAttributes, glm::countof(vertexArrayVertexBuffers), vertexArrayVertexBuffers); } // Create the program: Decide which shader language should be used (for example "GLSL" or "HLSL") Renderer::IShaderLanguagePtr shaderLanguage(renderer->getShaderLanguage()); if (nullptr != shaderLanguage) { // Create the program Renderer::IProgramPtr program; { // Get the shader source code (outsourced to keep an overview) const char *vertexShaderSourceCode = nullptr; const char *geometryShaderSourceCode = nullptr; const char *fragmentShaderSourceCode = nullptr; #include "FirstGeometryShader_GLSL_410.h" #include "FirstGeometryShader_HLSL_D3D10_D3D11_D3D12.h" #include "FirstGeometryShader_Null.h" // Create the program program = shaderLanguage->createProgram( *mRootSignature, vertexAttributes, shaderLanguage->createVertexShaderFromSourceCode(vertexAttributes, vertexShaderSourceCode), shaderLanguage->createGeometryShaderFromSourceCode(geometryShaderSourceCode, Renderer::GsInputPrimitiveTopology::POINTS, Renderer::GsOutputPrimitiveTopology::TRIANGLE_STRIP, 3), shaderLanguage->createFragmentShaderFromSourceCode(fragmentShaderSourceCode)); } // Create the pipeline state object (PSO) if (nullptr != program) { Renderer::PipelineState pipelineState = Renderer::PipelineStateBuilder(mRootSignature, program, vertexAttributes); pipelineState.primitiveTopologyType = Renderer::PrimitiveTopologyType::POINT; mPipelineState = renderer->createPipelineState(pipelineState); } } // Since we're always submitting the same commands to the renderer, we can fill the command buffer once during initialization and then reuse it multiple times during runtime fillCommandBuffer(); } }
PRAGMA_WARNING_POP //[-------------------------------------------------------] //[ Public virtual IApplication methods ] //[-------------------------------------------------------] void FirstComputeShader::onInitialization() { // Get and check the renderer instance Renderer::IRendererPtr renderer(getRenderer()); if (nullptr != renderer) { // Create the buffer and texture manager mBufferManager = renderer->createBufferManager(); mTextureManager = renderer->createTextureManager(); { // Create the graphics root signature // TODO(co) Compute shader: Get rid of the OpenGL/Direct3D 11 variation here const uint32_t offset = (renderer->getNameId() == Renderer::NameId::VULKAN || renderer->getNameId() == Renderer::NameId::OPENGL) ? 1u : 0u; Renderer::DescriptorRangeBuilder ranges[5]; ranges[0].initialize(Renderer::ResourceType::UNIFORM_BUFFER, 0, "UniformBuffer", Renderer::ShaderVisibility::FRAGMENT); ranges[1].initialize(Renderer::ResourceType::TEXTURE_BUFFER, 0, "InputTextureBuffer", Renderer::ShaderVisibility::VERTEX); ranges[2].initialize(Renderer::ResourceType::STRUCTURED_BUFFER, 1u + offset, "InputStructuredBuffer", Renderer::ShaderVisibility::VERTEX); ranges[3].initialize(Renderer::ResourceType::TEXTURE_2D, 1, "AlbedoMap", Renderer::ShaderVisibility::FRAGMENT); ranges[4].initializeSampler(0, Renderer::ShaderVisibility::FRAGMENT); Renderer::RootParameterBuilder rootParameters[2]; rootParameters[0].initializeAsDescriptorTable(4, &ranges[0]); rootParameters[1].initializeAsDescriptorTable(1, &ranges[4]); // Setup Renderer::RootSignatureBuilder rootSignature; rootSignature.initialize(static_cast<uint32_t>(GLM_COUNTOF(rootParameters)), rootParameters, 0, nullptr, Renderer::RootSignatureFlags::ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); // Create the instance mGraphicsRootSignature = renderer->createRootSignature(rootSignature); } { // Create the first compute root signature Renderer::DescriptorRangeBuilder ranges[7]; // Input ranges[0].initialize(Renderer::ResourceType::TEXTURE_2D, 0, "InputTexture2D", Renderer::ShaderVisibility::COMPUTE); ranges[1].initialize(Renderer::ResourceType::INDEX_BUFFER, 1, "InputIndexBuffer", Renderer::ShaderVisibility::COMPUTE); ranges[2].initialize(Renderer::ResourceType::VERTEX_BUFFER, 2, "InputVertexBuffer", Renderer::ShaderVisibility::COMPUTE); ranges[3].initialize(Renderer::ResourceType::UNIFORM_BUFFER, 0, "InputUniformBuffer", Renderer::ShaderVisibility::COMPUTE); // Output // TODO(co) Compute shader: Get rid of the OpenGL/Direct3D 11 variation here const uint32_t offset = (renderer->getNameId() == Renderer::NameId::VULKAN || renderer->getNameId() == Renderer::NameId::OPENGL) ? 4u : 0u; ranges[4].initialize(Renderer::ResourceType::TEXTURE_2D, 0u + offset, "OutputTexture2D", Renderer::ShaderVisibility::COMPUTE, Renderer::DescriptorRangeType::UAV); ranges[5].initialize(Renderer::ResourceType::INDEX_BUFFER, 1u + offset, "OutputIndexBuffer", Renderer::ShaderVisibility::COMPUTE, Renderer::DescriptorRangeType::UAV); ranges[6].initialize(Renderer::ResourceType::VERTEX_BUFFER, 2u + offset, "OutputVertexBuffer", Renderer::ShaderVisibility::COMPUTE, Renderer::DescriptorRangeType::UAV); Renderer::RootParameterBuilder rootParameters[1]; rootParameters[0].initializeAsDescriptorTable(7, &ranges[0]); // Setup Renderer::RootSignatureBuilder rootSignature; rootSignature.initialize(static_cast<uint32_t>(GLM_COUNTOF(rootParameters)), rootParameters, 0, nullptr, Renderer::RootSignatureFlags::NONE); // Create the instance mComputeRootSignature1 = renderer->createRootSignature(rootSignature); } { // Create the second compute root signature Renderer::DescriptorRangeBuilder ranges[6]; // Input ranges[0].initialize(Renderer::ResourceType::TEXTURE_BUFFER, 0, "InputTextureBuffer", Renderer::ShaderVisibility::COMPUTE); ranges[1].initialize(Renderer::ResourceType::STRUCTURED_BUFFER, 1, "InputStructuredBuffer", Renderer::ShaderVisibility::COMPUTE); ranges[2].initialize(Renderer::ResourceType::INDIRECT_BUFFER, 2, "InputIndirectBuffer", Renderer::ShaderVisibility::COMPUTE); // Output // TODO(co) Compute shader: Get rid of the OpenGL/Direct3D 11 variation here const uint32_t offset = (renderer->getNameId() == Renderer::NameId::VULKAN || renderer->getNameId() == Renderer::NameId::OPENGL) ? 3u : 0u; ranges[3].initialize(Renderer::ResourceType::TEXTURE_BUFFER, 0u + offset, "OutputTextureBuffer", Renderer::ShaderVisibility::COMPUTE, Renderer::DescriptorRangeType::UAV); ranges[4].initialize(Renderer::ResourceType::STRUCTURED_BUFFER, 1u + offset, "OutputStructuredBuffer", Renderer::ShaderVisibility::COMPUTE, Renderer::DescriptorRangeType::UAV); ranges[5].initialize(Renderer::ResourceType::INDIRECT_BUFFER, 2u + offset, "OutputIndirectBuffer", Renderer::ShaderVisibility::COMPUTE, Renderer::DescriptorRangeType::UAV); Renderer::RootParameterBuilder rootParameters[1]; rootParameters[0].initializeAsDescriptorTable(6, &ranges[0]); // Setup Renderer::RootSignatureBuilder rootSignature; rootSignature.initialize(static_cast<uint32_t>(GLM_COUNTOF(rootParameters)), rootParameters, 0, nullptr, Renderer::RootSignatureFlags::NONE); // Create the instance mComputeRootSignature2 = renderer->createRootSignature(rootSignature); } // Create sampler state and wrap it into a resource group instance Renderer::IResource* samplerStateResource = nullptr; { Renderer::SamplerState samplerState = Renderer::ISamplerState::getDefaultSamplerState(); samplerState.maxLOD = 0.0f; samplerStateResource = renderer->createSamplerState(samplerState); mGraphicsSamplerStateGroup = mGraphicsRootSignature->createResourceGroup(1, 1, &samplerStateResource); } { // Texture buffer static constexpr float VERTEX_POSITION_OFFSET[] = { // Vertex ID Triangle on screen 0.5f, -0.5f, 0.0f, 0.0f, // 0 0 0.5f, -0.5f, 0.0f, 0.0f, // 1 . . 0.5f, -0.5f, 0.0f, 0.0f, // 2 2.......1 }; // Create the texture buffer which will be read by a compute shader mComputeInputTextureBuffer = mBufferManager->createTextureBuffer(sizeof(VERTEX_POSITION_OFFSET), VERTEX_POSITION_OFFSET); // Create the texture buffer which will be filled by a compute shader mComputeOutputTextureBuffer = mBufferManager->createTextureBuffer(sizeof(VERTEX_POSITION_OFFSET), nullptr, Renderer::BufferFlag::UNORDERED_ACCESS | Renderer::BufferFlag::SHADER_RESOURCE); } { // Structured buffer struct Vertex { float position[2]; float padding[2]; }; static constexpr Vertex VERTICES[] = { // Vertex ID Triangle on screen { -0.5f, 0.5f, 0.0f, 0.0f }, // 0 0 { -0.5f, 0.5f, 0.0f, 0.0f }, // 1 . . { -0.5f, 0.5f, 0.0f, 0.0f }, // 2 2.......1 }; // Create the structured buffer which will be read by a compute shader mComputeInputStructuredBuffer = mBufferManager->createStructuredBuffer(sizeof(VERTICES), VERTICES, Renderer::BufferFlag::SHADER_RESOURCE, Renderer::BufferUsage::STATIC_DRAW, sizeof(Vertex)); // Create the structured buffer which will be filled by a compute shader mComputeOutputStructuredBuffer = mBufferManager->createStructuredBuffer(sizeof(VERTICES), nullptr, Renderer::BufferFlag::UNORDERED_ACCESS | Renderer::BufferFlag::SHADER_RESOURCE, Renderer::BufferUsage::STATIC_DRAW, sizeof(Vertex)); } { // Indirect buffer { // Create the indirect buffer which will be read by a compute shader const Renderer::DrawIndexedArguments drawIndexedArguments = { 0, // indexCountPerInstance (uint32_t) - Filled by compute shader via atomics counting 1, // instanceCount (uint32_t) 0, // startIndexLocation (uint32_t) 0, // baseVertexLocation (int32_t) 0 // startInstanceLocation (uint32_t) }; mComputeInputIndirectBuffer = mBufferManager->createIndirectBuffer(sizeof(Renderer::DrawIndexedArguments), &drawIndexedArguments, Renderer::IndirectBufferFlag::SHADER_RESOURCE | Renderer::IndirectBufferFlag::DRAW_INDEXED_ARGUMENTS); } // Create the indirect buffer which will be filled by a compute shader mComputeOutputIndirectBuffer = mBufferManager->createIndirectBuffer(sizeof(Renderer::DrawIndexedArguments), nullptr, Renderer::IndirectBufferFlag::UNORDERED_ACCESS | Renderer::IndirectBufferFlag::DRAW_INDEXED_ARGUMENTS); } // Vertex input layout static constexpr Renderer::VertexAttribute vertexAttributesLayout[] = { { // Attribute 0 // Data destination Renderer::VertexAttributeFormat::FLOAT_2, // vertexAttributeFormat (Renderer::VertexAttributeFormat) "Position", // name[32] (char) "POSITION", // semanticName[32] (char) 0, // semanticIndex (uint32_t) // Data source 0, // inputSlot (uint32_t) 0, // alignedByteOffset (uint32_t) sizeof(float) * 2, // strideInBytes (uint32_t) 0 // instancesPerElement (uint32_t) } }; const Renderer::VertexAttributes vertexAttributes(static_cast<uint32_t>(GLM_COUNTOF(vertexAttributesLayout)), vertexAttributesLayout); { // Create the index buffer object (IBO) static constexpr uint16_t INDICES[] = { 0, 1, 2 }; mComputeInputIndexBuffer = mBufferManager->createIndexBuffer(sizeof(INDICES), INDICES, Renderer::BufferFlag::SHADER_RESOURCE); mComputeOutputIndexBuffer = mBufferManager->createIndexBuffer(sizeof(INDICES), nullptr, Renderer::BufferFlag::UNORDERED_ACCESS); } { // Create vertex array object (VAO) // Create the vertex buffer object (VBO) // -> Clip space vertex positions, left/bottom is (-1,-1) and right/top is (1,1) static constexpr float VERTEX_POSITION[] = { // Vertex ID Triangle on screen 0.0f, 1.0f, // 0 0 1.0f, 0.0f, // 1 . . -0.5f, 0.0f // 2 2.......1 }; mComputeInputVertexBuffer = mBufferManager->createVertexBuffer(sizeof(VERTEX_POSITION), VERTEX_POSITION, Renderer::BufferFlag::SHADER_RESOURCE); mComputeOutputVertexBuffer = mBufferManager->createVertexBuffer(sizeof(VERTEX_POSITION), nullptr, Renderer::BufferFlag::UNORDERED_ACCESS); } { // Create vertex array object (VAO) // -> The vertex array object (VAO) keeps a reference to the used vertex buffer object (VBO) // -> This means that there's no need to keep an own vertex buffer object (VBO) reference // -> When the vertex array object (VAO) is destroyed, it automatically decreases the // reference of the used vertex buffer objects (VBO). If the reference counter of a // vertex buffer object (VBO) reaches zero, it's automatically destroyed. const Renderer::VertexArrayVertexBuffer vertexArrayVertexBuffers[] = { mComputeOutputVertexBuffer }; mVertexArray = mBufferManager->createVertexArray(vertexAttributes, static_cast<uint32_t>(GLM_COUNTOF(vertexArrayVertexBuffers)), vertexArrayVertexBuffers, mComputeOutputIndexBuffer); } { // Create the uniform buffer which will be read by a compute shader static constexpr float RGBA_COLOR[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; mComputeInputUniformBuffer = mBufferManager->createUniformBuffer(sizeof(RGBA_COLOR), RGBA_COLOR); } { // Resource group related // Create the texture instance, but without providing texture data (we use the texture as render target) // -> Use the "Renderer::TextureFlag::RENDER_TARGET"-flag to mark this texture as a render target // -> Required for Vulkan, Direct3D 9, Direct3D 10, Direct3D 11 and Direct3D 12 // -> Not required for OpenGL and OpenGL ES 3 // -> The optimized texture clear value is a Direct3D 12 related option const Renderer::TextureFormat::Enum textureFormat = Renderer::TextureFormat::Enum::R8G8B8A8; Renderer::ITexture* computeInputTexture2D = mTextureManager->createTexture2D(16, 16, textureFormat, nullptr, Renderer::TextureFlag::SHADER_RESOURCE | Renderer::TextureFlag::RENDER_TARGET, Renderer::TextureUsage::DEFAULT, 1, reinterpret_cast<const Renderer::OptimizedTextureClearValue*>(&Color4::GREEN)); Renderer::ITexture* computeOutputTexture2D = mTextureManager->createTexture2D(16, 16, textureFormat, nullptr, Renderer::TextureFlag::SHADER_RESOURCE | Renderer::TextureFlag::UNORDERED_ACCESS); { // Create the framebuffer object (FBO) instance const Renderer::FramebufferAttachment colorFramebufferAttachment(computeInputTexture2D); mFramebuffer = renderer->createFramebuffer(*renderer->createRenderPass(1, &textureFormat), &colorFramebufferAttachment); } { // Create first compute resource group Renderer::IResource* resources[7] = { // Input computeInputTexture2D, mComputeInputIndexBuffer, mComputeInputVertexBuffer, mComputeInputUniformBuffer, // Output computeOutputTexture2D, mComputeOutputIndexBuffer, mComputeOutputVertexBuffer }; Renderer::ISamplerState* samplerStates[7] = { // Input static_cast<Renderer::ISamplerState*>(samplerStateResource), nullptr, nullptr, nullptr, // Output nullptr, nullptr, nullptr }; mComputeResourceGroup1 = mComputeRootSignature1->createResourceGroup(0, static_cast<uint32_t>(GLM_COUNTOF(resources)), resources, samplerStates); } { // Create second compute resource group Renderer::IResource* resources[6] = { // Input mComputeInputTextureBuffer, mComputeInputStructuredBuffer, mComputeInputIndirectBuffer, // Output mComputeOutputTextureBuffer, mComputeOutputStructuredBuffer, mComputeOutputIndirectBuffer }; mComputeResourceGroup2 = mComputeRootSignature2->createResourceGroup(0, static_cast<uint32_t>(GLM_COUNTOF(resources)), resources, nullptr); } { // Create graphics resource group Renderer::IResource* resources[4] = { mComputeInputUniformBuffer, mComputeOutputTextureBuffer, mComputeOutputStructuredBuffer, computeOutputTexture2D }; Renderer::ISamplerState* samplerStates[4] = { nullptr, nullptr, nullptr, static_cast<Renderer::ISamplerState*>(samplerStateResource) }; mGraphicsResourceGroup = mGraphicsRootSignature->createResourceGroup(0, static_cast<uint32_t>(GLM_COUNTOF(resources)), resources, samplerStates); } } { // Create the graphics program Renderer::IGraphicsProgramPtr graphicsProgram; { // Get the shader source code (outsourced to keep an overview) const char* vertexShaderSourceCode = nullptr; const char* fragmentShaderSourceCode = nullptr; const char* computeShaderSourceCode1 = nullptr; const char* computeShaderSourceCode2 = nullptr; #include "FirstComputeShader_GLSL_450.h" // For Vulkan #include "FirstComputeShader_GLSL_430.h" // macOS 10.11 only supports OpenGL 4.1 and hence can't be supported by this example #include "FirstComputeShader_HLSL_D3D11_D3D12.h" #include "FirstComputeShader_Null.h" // Create the graphics program Renderer::IShaderLanguage& shaderLanguage = renderer->getDefaultShaderLanguage(); graphicsProgram = shaderLanguage.createGraphicsProgram( *mGraphicsRootSignature, vertexAttributes, shaderLanguage.createVertexShaderFromSourceCode(vertexAttributes, vertexShaderSourceCode), shaderLanguage.createFragmentShaderFromSourceCode(fragmentShaderSourceCode)); // Create the compute pipeline state objects (PSO) mComputePipelineState1 = renderer->createComputePipelineState(*mComputeRootSignature1, *shaderLanguage.createComputeShaderFromSourceCode(computeShaderSourceCode1)); mComputePipelineState2 = renderer->createComputePipelineState(*mComputeRootSignature2, *shaderLanguage.createComputeShaderFromSourceCode(computeShaderSourceCode2)); } // Create the graphics pipeline state object (PSO) if (nullptr != graphicsProgram) { mGraphicsPipelineState = renderer->createGraphicsPipelineState(Renderer::GraphicsPipelineStateBuilder(mGraphicsRootSignature, graphicsProgram, vertexAttributes, getMainRenderTarget()->getRenderPass())); } } // Since we're always submitting the same commands to the renderer, we can fill the command buffer once during initialization and then reuse it multiple times during runtime fillCommandBuffer(); } }