From 3efcf2172def7f0a41ebb1c61f874a3321e4f10e Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Tue, 30 May 2017 16:25:20 -0400 Subject: [PATCH] Add DepthStencilState Add depth and stencil tests. This is currently only implemented for the OpenGL API. HelloDepthStencil is a test using the depth and stencil buffers to do reflections. Currently clearing / stencil clearing is not working properly. --- examples/CMakeLists.txt | 154 +- examples/HelloDepthStencil.cpp | 343 +++++ next.json | 1733 ++++++++++++---------- src/backend/CMakeLists.txt | 296 ++-- src/backend/common/DepthStencilState.cpp | 137 ++ src/backend/common/DepthStencilState.h | 90 ++ src/backend/common/Device.cpp | 270 ++-- src/backend/common/Device.h | 204 +-- src/backend/common/Forward.h | 154 +- src/backend/common/Pipeline.cpp | 334 +++-- src/backend/common/Pipeline.h | 196 +-- src/backend/common/ToBackend.h | 265 ++-- src/backend/null/NullBackend.cpp | 243 +-- src/backend/null/NullBackend.h | 254 ++-- src/backend/opengl/OpenGLBackend.cpp | 499 ++++--- src/backend/opengl/OpenGLBackend.h | 363 ++--- src/backend/opengl/PipelineGL.cpp | 428 +++--- 17 files changed, 3414 insertions(+), 2549 deletions(-) create mode 100644 examples/HelloDepthStencil.cpp create mode 100644 src/backend/common/DepthStencilState.cpp create mode 100644 src/backend/common/DepthStencilState.h diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index ccb8fa4890..d868c6d37d 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,75 +1,79 @@ -# Copyright 2017 The NXT Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -list(APPEND UTILS_SOURCES - Utils.h - Utils.cpp - BackendBinding.h -) - -if (APPLE) - list(APPEND UTILS_SOURCES - MetalBinding.mm - ) -endif() - -add_library(utils STATIC ${UTILS_SOURCES}) -target_link_libraries(utils nxt_backend nxt_wire shaderc nxtcpp nxt) -SetCXX14(utils) - -add_executable(CHelloTriangle HelloTriangle.c) -target_link_libraries(CHelloTriangle utils) - -add_executable(CppHelloTriangle HelloTriangle.cpp) -target_link_libraries(CppHelloTriangle utils) -SetCXX14(CppHelloTriangle) - -add_executable(ComputeBoids ComputeBoids.cpp) -target_link_libraries(ComputeBoids utils) -target_include_directories(ComputeBoids PUBLIC ../ ${GLM_INCLUDE_DIR}) -SetCXX14(ComputeBoids) - -add_executable(HelloVertices HelloVertices.cpp) -target_link_libraries(HelloVertices utils) -SetCXX14(HelloVertices) - -add_executable(HelloInstancing HelloInstancing.cpp) -target_link_libraries(HelloInstancing utils) -SetCXX14(HelloInstancing) - -add_executable(HelloIndices HelloIndices.cpp) -target_link_libraries(HelloIndices utils) -SetCXX14(HelloIndices) - -add_executable(HelloUBO HelloUBO.cpp) -target_link_libraries(HelloUBO utils) -SetCXX14(HelloUBO) - -add_executable(HelloCompute HelloCompute.cpp) -target_link_libraries(HelloCompute utils) -SetCXX14(HelloCompute) - -add_executable(RenderToTexture RenderToTexture.cpp) -target_link_libraries(RenderToTexture utils) -SetCXX14(RenderToTexture) - -add_executable(Animometer Animometer.cpp) -target_link_libraries(Animometer utils) -SetCXX14(Animometer) - -add_executable(SpirvTest SpirvTest.cpp) -target_link_libraries(SpirvTest shaderc spirv-cross nxtcpp) -SetCXX14(SpirvTest) - -add_subdirectory(glTFViewer) +# Copyright 2017 The NXT Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +list(APPEND UTILS_SOURCES + Utils.h + Utils.cpp + BackendBinding.h +) + +if (APPLE) + list(APPEND UTILS_SOURCES + MetalBinding.mm + ) +endif() + +add_library(utils STATIC ${UTILS_SOURCES}) +target_link_libraries(utils nxt_backend nxt_wire shaderc nxtcpp nxt) +SetCXX14(utils) + +add_executable(CHelloTriangle HelloTriangle.c) +target_link_libraries(CHelloTriangle utils) + +add_executable(CppHelloTriangle HelloTriangle.cpp) +target_link_libraries(CppHelloTriangle utils) +SetCXX14(CppHelloTriangle) + +add_executable(ComputeBoids ComputeBoids.cpp) +target_link_libraries(ComputeBoids utils) +target_include_directories(ComputeBoids PUBLIC ../ ${GLM_INCLUDE_DIR}) +SetCXX14(ComputeBoids) + +add_executable(HelloVertices HelloVertices.cpp) +target_link_libraries(HelloVertices utils) +SetCXX14(HelloVertices) + +add_executable(HelloInstancing HelloInstancing.cpp) +target_link_libraries(HelloInstancing utils) +SetCXX14(HelloInstancing) + +add_executable(HelloIndices HelloIndices.cpp) +target_link_libraries(HelloIndices utils) +SetCXX14(HelloIndices) + +add_executable(HelloUBO HelloUBO.cpp) +target_link_libraries(HelloUBO utils) +SetCXX14(HelloUBO) + +add_executable(HelloCompute HelloCompute.cpp) +target_link_libraries(HelloCompute utils) +SetCXX14(HelloCompute) + +add_executable(RenderToTexture RenderToTexture.cpp) +target_link_libraries(RenderToTexture utils) +SetCXX14(RenderToTexture) + +add_executable(Animometer Animometer.cpp) +target_link_libraries(Animometer utils) +SetCXX14(Animometer) + +add_executable(SpirvTest SpirvTest.cpp) +target_link_libraries(SpirvTest shaderc spirv-cross nxtcpp) +SetCXX14(SpirvTest) + +add_executable(CppHelloDepthStencil HelloDepthStencil.cpp) +target_link_libraries(CppHelloDepthStencil utils) +SetCXX14(CppHelloDepthStencil) + +add_subdirectory(glTFViewer) diff --git a/examples/HelloDepthStencil.cpp b/examples/HelloDepthStencil.cpp new file mode 100644 index 0000000000..e89bbf53ef --- /dev/null +++ b/examples/HelloDepthStencil.cpp @@ -0,0 +1,343 @@ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Utils.h" + +#include +#include +#include +#include + +nxt::Device device; + +nxt::Buffer indexBuffer; +nxt::Buffer vertexBuffer; +nxt::Buffer planeBuffer; +nxt::Buffer cameraBuffer; +nxt::Buffer transformBuffer[2]; + +nxt::BindGroup cameraBindGroup; +nxt::BindGroup bindGroup[2]; +nxt::BindGroup cubeTransformBindGroup[2]; + +nxt::Queue queue; +nxt::Pipeline pipeline; +nxt::Pipeline planePipeline; +nxt::Pipeline reflectionPipeline; +nxt::RenderPass renderpass; +nxt::Framebuffer framebuffer; + +void initBuffers() { + static const uint32_t indexData[6*6] = { + 0, 1, 2, + 0, 2, 3, + + 4, 5, 6, + 4, 6, 7, + + 8, 9, 10, + 8, 10, 11, + + 12, 13, 14, + 12, 14, 15, + + 16, 17, 18, + 16, 18, 19, + + 20, 21, 22, + 20, 22, 23 + }; + indexBuffer = device.CreateBufferBuilder() + .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Index) + .SetInitialUsage(nxt::BufferUsageBit::Mapped) + .SetSize(sizeof(indexData)) + .GetResult(); + indexBuffer.SetSubData(0, sizeof(indexData) / sizeof(uint32_t), indexData); + indexBuffer.FreezeUsage(nxt::BufferUsageBit::Index); + + static const float vertexData[6 * 4 * 6] = { + -1.0, -1.0, 1.0, 1.0, 0.0, 0.0, + 1.0, -1.0, 1.0, 1.0, 0.0, 0.0, + 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, + -1.0, 1.0, 1.0, 1.0, 0.0, 0.0, + + -1.0, -1.0, -1.0, 1.0, 1.0, 0.0, + -1.0, 1.0, -1.0, 1.0, 1.0, 0.0, + 1.0, 1.0, -1.0, 1.0, 1.0, 0.0, + 1.0, -1.0, -1.0, 1.0, 1.0, 0.0, + + -1.0, 1.0, -1.0, 1.0, 0.0, 1.0, + -1.0, 1.0, 1.0, 1.0, 0.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, + 1.0, 1.0, -1.0, 1.0, 0.0, 1.0, + + -1.0, -1.0, -1.0, 0.0, 1.0, 0.0, + 1.0, -1.0, -1.0, 0.0, 1.0, 0.0, + 1.0, -1.0, 1.0, 0.0, 1.0, 0.0, + -1.0, -1.0, 1.0, 0.0, 1.0, 0.0, + + 1.0, -1.0, -1.0, 0.0, 1.0, 1.0, + 1.0, 1.0, -1.0, 0.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, + 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, + + -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, + -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + -1.0, 1.0, -1.0, 1.0, 1.0, 1.0 + }; + + vertexBuffer = device.CreateBufferBuilder() + .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex) + .SetInitialUsage(nxt::BufferUsageBit::Mapped) + .SetSize(sizeof(vertexData)) + .GetResult(); + vertexBuffer.SetSubData(0, sizeof(vertexData) / sizeof(uint32_t), + reinterpret_cast(vertexData)); + vertexBuffer.FreezeUsage(nxt::BufferUsageBit::Vertex); + + static const float planeData[6 * 4] = { + -2.0, -1.0, -2.0, 0.5, 0.5, 0.5, + 2.0, -1.0, -2.0, 0.5, 0.5, 0.5, + 2.0, -1.0, 2.0, 0.5, 0.5, 0.5, + -2.0, -1.0, 2.0, 0.5, 0.5, 0.5, + }; + + planeBuffer = device.CreateBufferBuilder() + .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Vertex) + .SetInitialUsage(nxt::BufferUsageBit::Mapped) + .SetSize(sizeof(planeData)) + .GetResult(); + planeBuffer.SetSubData(0, sizeof(planeData) / sizeof(uint32_t), + reinterpret_cast(planeData)); + planeBuffer.FreezeUsage(nxt::BufferUsageBit::Vertex); +} + +struct { + glm::mat4 view; + glm::mat4 proj; +} cameraData; + +void init() { + device = CreateCppNXTDevice(); + + queue = device.CreateQueueBuilder().GetResult(); + + initBuffers(); + + nxt::ShaderModule vsModule = CreateShaderModule(device, nxt::ShaderStage::Vertex, R"( + #version 450 + layout(set = 0, binding = 0) uniform cameraData { + mat4 view; + mat4 proj; + } camera; + layout(set = 0, binding = 1) uniform modelData { + mat4 modelMatrix; + }; + layout(location = 0) in vec3 pos; + layout(location = 1) in vec3 col; + layout(location = 2) out vec3 f_col; + void main() { + f_col = col; + gl_Position = camera.proj * camera.view * modelMatrix * vec4(pos, 1.0); + })" + ); + + nxt::ShaderModule fsModule = CreateShaderModule(device, nxt::ShaderStage::Fragment, R"( + #version 450 + layout(location = 2) in vec3 f_col; + out vec4 fragColor; + void main() { + fragColor = vec4(f_col, 1.0); + })" + ); + + auto inputState = device.CreateInputStateBuilder() + .SetAttribute(0, 0, nxt::VertexFormat::FloatR32G32B32, 0) + .SetAttribute(1, 0, nxt::VertexFormat::FloatR32G32B32, 3 * sizeof(float)) + .SetInput(0, 6 * sizeof(float), nxt::InputStepMode::Vertex) + .SetInput(1, 6 * sizeof(float), nxt::InputStepMode::Vertex) + .GetResult(); + + auto depthStencilState = device.CreateDepthStencilStateBuilder() + .SetDepthEnabled(true) + .GetResult(); + + nxt::BindGroupLayout bgl = device.CreateBindGroupLayoutBuilder() + .SetBindingsType(nxt::ShaderStageBit::Vertex, nxt::BindingType::UniformBuffer, 0, 2) + .GetResult(); + + nxt::PipelineLayout pl = device.CreatePipelineLayoutBuilder() + .SetBindGroupLayout(0, bgl) + .GetResult(); + + cameraBuffer = device.CreateBufferBuilder() + .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Uniform) + .SetInitialUsage(nxt::BufferUsageBit::Mapped) + .SetSize(sizeof(cameraData)) + .GetResult(); + + glm::mat4 transform(1.0); + + transformBuffer[0] = device.CreateBufferBuilder() + .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Uniform) + .SetInitialUsage(nxt::BufferUsageBit::Mapped) + .SetSize(sizeof(glm::mat4)) + .GetResult(); + transformBuffer[0].SetSubData(0, sizeof(glm::mat4) / sizeof(uint32_t), reinterpret_cast(&transform)); + transformBuffer[0].FreezeUsage(nxt::BufferUsageBit::Uniform); + + transform = glm::translate(transform, glm::vec3(0.f, -2.f, 0.f)); + + transformBuffer[1] = device.CreateBufferBuilder() + .SetAllowedUsage(nxt::BufferUsageBit::Mapped | nxt::BufferUsageBit::Uniform) + .SetInitialUsage(nxt::BufferUsageBit::Mapped) + .SetSize(sizeof(glm::mat4)) + .GetResult(); + transformBuffer[1].SetSubData(0, sizeof(glm::mat4) / sizeof(uint32_t), reinterpret_cast(&transform)); + transformBuffer[1].FreezeUsage(nxt::BufferUsageBit::Uniform); + + nxt::BufferView cameraBufferView = cameraBuffer.CreateBufferViewBuilder() + .SetExtent(0, sizeof(cameraData)) + .GetResult(); + + nxt::BufferView transformBufferView[2] = { + transformBuffer[0].CreateBufferViewBuilder() + .SetExtent(0, sizeof(glm::mat4)) + .GetResult(), + transformBuffer[1].CreateBufferViewBuilder() + .SetExtent(0, sizeof(glm::mat4)) + .GetResult(), + }; + + bindGroup[0] = device.CreateBindGroupBuilder() + .SetLayout(bgl) + .SetUsage(nxt::BindGroupUsage::Frozen) + .SetBufferViews(0, 1, &cameraBufferView) + .SetBufferViews(1, 1, &transformBufferView[0]) + .GetResult(); + + bindGroup[1] = device.CreateBindGroupBuilder() + .SetLayout(bgl) + .SetUsage(nxt::BindGroupUsage::Frozen) + .SetBufferViews(0, 1, &cameraBufferView) + .SetBufferViews(1, 1, &transformBufferView[1]) + .GetResult(); + + CreateDefaultRenderPass(device, &renderpass, &framebuffer); + pipeline = device.CreatePipelineBuilder() + .SetSubpass(renderpass, 0) + .SetLayout(pl) + .SetStage(nxt::ShaderStage::Vertex, vsModule, "main") + .SetStage(nxt::ShaderStage::Fragment, fsModule, "main") + .SetInputState(inputState) + .SetDepthStencilState(depthStencilState) + .GetResult(); + + auto planeStencilState = device.CreateDepthStencilStateBuilder() + .SetDepthEnabled(true) + .SetDepthWrite(nxt::DepthWriteMode::Disabled) + .SetStencilEnabled(true) + .SetStencilReferenceMode(nxt::StencilReferenceMode::Static) + .SetStencilReference(nxt::Face::Both, 1) + .SetStencilCompareFunction(nxt::Face::Both, nxt::CompareFunction::Always) + .SetStencilOperation(nxt::Face::Both, nxt::StencilOperation::Keep, nxt::StencilOperation::Keep, nxt::StencilOperation::Replace) + .SetStencilMask(nxt::Face::Both, 0xff, 0xff) + .GetResult(); + + planePipeline = device.CreatePipelineBuilder() + .SetSubpass(renderpass, 0) + .SetLayout(pl) + .SetStage(nxt::ShaderStage::Vertex, vsModule, "main") + .SetStage(nxt::ShaderStage::Fragment, fsModule, "main") + .SetInputState(inputState) + .SetDepthStencilState(planeStencilState) + .GetResult(); + + auto reflectionStencilState = device.CreateDepthStencilStateBuilder() + .SetDepthEnabled(true) + .SetDepthWrite(nxt::DepthWriteMode::Enabled) + .SetStencilEnabled(true) + .SetStencilReferenceMode(nxt::StencilReferenceMode::Static) + .SetStencilReference(nxt::Face::Both, 1) + .SetStencilCompareFunction(nxt::Face::Both, nxt::CompareFunction::Equal) + .SetStencilOperation(nxt::Face::Both, nxt::StencilOperation::Keep, nxt::StencilOperation::Keep, nxt::StencilOperation::Replace) + .SetStencilMask(nxt::Face::Both, 0xff, 0x00) + .GetResult(); + + reflectionPipeline = device.CreatePipelineBuilder() + .SetSubpass(renderpass, 0) + .SetLayout(pl) + .SetStage(nxt::ShaderStage::Vertex, vsModule, "main") + .SetStage(nxt::ShaderStage::Fragment, fsModule, "main") + .SetInputState(inputState) + .SetDepthStencilState(reflectionStencilState) + .GetResult(); + + cameraData.proj = glm::perspective(glm::radians(45.0f), 1.f, 1.0f, 100.0f); +} + +struct {uint32_t a; float b;} s; +void frame() { + s.a = (s.a + 1) % 256; + s.b += 0.01; + if (s.b >= 1.0f) {s.b = 0.0f;} + static const uint32_t vertexBufferOffsets[1] = {0}; + + cameraData.view = glm::lookAt( + glm::vec3(10.f * std::sin(glm::radians(s.b * 360.f)), 2.f, 10.f * std::cos(glm::radians(s.b * 360.f))), + glm::vec3(0.0f, -1.0f, 0.0f), + glm::vec3(0.0f, 1.0f, 0.0f) + ); + + cameraBuffer.TransitionUsage(nxt::BufferUsageBit::Mapped); + cameraBuffer.SetSubData(0, sizeof(cameraData) / sizeof(uint32_t), reinterpret_cast(&cameraData)); + + nxt::CommandBuffer commands = device.CreateCommandBufferBuilder() + .BeginRenderPass(renderpass, framebuffer) + .SetPipeline(pipeline) + .TransitionBufferUsage(cameraBuffer, nxt::BufferUsageBit::Uniform) + .SetBindGroup(0, bindGroup[0]) + .SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets) + .SetIndexBuffer(indexBuffer, 0, nxt::IndexFormat::Uint32) + .DrawElements(36, 1, 0, 0) + + .SetPipeline(planePipeline) + .SetVertexBuffers(0, 1, &planeBuffer, vertexBufferOffsets) + .DrawElements(6, 1, 0, 0) + + .SetPipeline(reflectionPipeline) + .SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets) + .SetBindGroup(0, bindGroup[1]) + .DrawElements(36, 1, 0, 0) + .EndRenderPass() + .GetResult(); + + queue.Submit(1, &commands); + DoSwapBuffers(); +} + +int main(int argc, const char* argv[]) { + if (!InitUtils(argc, argv)) { + return 1; + } + init(); + + while (!ShouldQuit()) { + frame(); + USleep(16000); + } + + // TODO release stuff +} diff --git a/next.json b/next.json index 08e1d484b4..e321e22887 100644 --- a/next.json +++ b/next.json @@ -1,798 +1,935 @@ -{ - "_comment": [ - "Copyright 2017 The NXT Authors", - "", - "Licensed under the Apache License, Version 2.0 (the \"License\");", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - " http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an \"AS IS\" BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "bind group": { - "category": "object" - }, - "bind group builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "bind group" - }, - { - "name": "set layout", - "args": [ - {"name": "layout", "type": "bind group layout"} - ] - }, - { - "name": "set usage", - "args": [ - {"name": "usage", "type": "bind group usage"} - ] - }, - { - "name": "set buffer views", - "args": [ - {"name": "start", "type": "uint32_t"}, - {"name": "count", "type": "uint32_t"}, - {"name": "buffer views", "type": "buffer view", "annotation": "const*", "length": "count"} - ] - }, - { - "name": "set samplers", - "args": [ - {"name": "start", "type": "uint32_t"}, - {"name": "count", "type": "uint32_t"}, - {"name": "samplers", "type": "sampler", "annotation": "const*", "length": "count"} - ] - }, - { - "name": "set texture views", - "args": [ - {"name": "start", "type": "uint32_t"}, - {"name": "count", "type": "uint32_t"}, - {"name": "texture views", "type": "texture view", "annotation": "const*", "length": "count"} - ] - } - ], - "TODO": [ - "When resource are added, add methods for setting the content of the bind group" - ] - }, - "bind group usage": { - "category": "enum", - "values": [ - {"value": 0, "name": "frozen"}, - {"value": 1, "name": "dynamic"} - ] - }, - "bind group layout": { - "category": "object" - }, - "bind group layout builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "bind group layout" - }, - { - "name": "set bindings type", - "args": [ - {"name": "visibility", "type": "shader stage bit"}, - {"name": "binding type", "type": "binding type"}, - {"name": "start", "type": "uint32_t"}, - {"name": "count", "type": "uint32_t"} - ] - } - ] - }, - "binding type": { - "category": "enum", - "values": [ - {"value": 0, "name": "uniform buffer"}, - {"value": 1, "name": "sampler"}, - {"value": 2, "name": "sampled texture"}, - {"value": 3, "name": "storage buffer"} - ] - }, - "builder error status": { - "category": "enum", - "values": [ - {"value": 0, "name": "success"}, - {"value": 1, "name": "error", "TODO": "cwallez@chromium.org: recoverable errors like GPU OOM"}, - {"value": 2, "name": "unknown"}, - {"value": 3, "name": "context lost"} - ] - }, - "builder error callback": { - "category": "natively defined" - }, - "buffer": { - "category": "object", - "methods": [ - { - "name": "create buffer view builder", - "returns": "buffer view builder" - }, - { - "name": "set sub data", - "args": [ - {"name": "start", "type": "uint32_t"}, - {"name": "count", "type": "uint32_t"}, - {"name": "data", "type": "uint32_t", "annotation": "const*", "length": "count"} - ] - }, - { - "name": "transition usage", - "args": [ - {"name": "usage", "type": "buffer usage bit"} - ] - }, - { - "name": "freeze usage", - "args": [ - {"name": "usage", "type": "buffer usage bit"} - ] - } - ] - }, - "buffer builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "buffer" - }, - { - "name": "set allowed usage", - "args": [ - {"name": "usage", "type": "buffer usage bit"} - ] - }, - { - "name": "set initial usage", - "args": [ - {"name": "usage", "type": "buffer usage bit"} - ] - }, - { - "name": "set size", - "args": [ - {"name": "size", "type": "uint32_t"} - ] - } - ] - }, - "buffer usage bit": { - "category": "bitmask", - "values": [ - {"value": 0, "name": "none"}, - {"value": 1, "name": "mapped"}, - {"value": 2, "name": "transfer src"}, - {"value": 4, "name": "transfer dst"}, - {"value": 8, "name": "index"}, - {"value": 16, "name": "vertex"}, - {"value": 32, "name": "uniform"}, - {"value": 64, "name": "storage"} - ] - }, - "buffer view": { - "category": "object" - }, - "buffer view builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "buffer view" - }, - { - "name": "set extent", - "args": [ - {"name": "offset", "type": "uint32_t"}, - {"name": "size", "type": "uint32_t"} - ] - } - ] - }, - "callback userdata": { - "category": "natively defined" - }, - "char": { - "category": "native" - }, - "command buffer": { - "category": "object" - }, - "command buffer builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "command buffer" - }, - { - "name": "begin render pass", - "args": [ - {"name": "render pass", "type": "render pass"}, - {"name": "framebuffer", "type": "framebuffer"} - ] - }, - { - "name": "advance subpass" - }, - { - "name": "end render pass" - }, - { - "name": "copy buffer to texture", - "args": [ - {"name": "buffer", "type": "buffer"}, - {"name": "buffer offset", "type": "uint32_t"}, - {"name": "texture", "type": "texture"}, - {"name": "x", "type": "uint32_t"}, - {"name": "y", "type": "uint32_t"}, - {"name": "z", "type": "uint32_t"}, - {"name": "width", "type": "uint32_t"}, - {"name": "height", "type": "uint32_t"}, - {"name": "depth", "type": "uint32_t"}, - {"name": "level", "type": "uint32_t"} - ], - "TODO": [ - "Make pretty with Offset and Extents structures", - "Allow choosing the aspect (depth vs. stencil)?", - "Add these arguments too", - {"name": "row length", "type": "uint32_t"}, - {"name": "image height", "type": "uint32_t"} - ] - }, - { - "name": "dispatch", - "args": [ - {"name": "x", "type": "uint32_t"}, - {"name": "y", "type": "uint32_t"}, - {"name": "z", "type": "uint32_t"} - ] - }, - { - "name": "draw arrays", - "args": [ - {"name": "vertex count", "type": "uint32_t"}, - {"name": "instance count", "type": "uint32_t"}, - {"name": "first vertex", "type": "uint32_t"}, - {"name": "first instance", "type": "uint32_t"} - ] - }, - { - "name": "draw elements", - "args": [ - {"name": "index count", "type": "uint32_t"}, - {"name": "instance count", "type": "uint32_t"}, - {"name": "first index", "type": "uint32_t"}, - {"name": "first instance", "type": "uint32_t"} - ] - }, - { - "name": "set bind group", - "args": [ - {"name": "group index", "type": "uint32_t"}, - {"name": "group", "type": "bind group"} - ] - }, - { - "name": "set index buffer", - "args": [ - {"name": "buffer", "type": "buffer"}, - {"name": "offset", "type": "uint32_t"}, - {"name": "format", "type": "index format"} - ] - }, - { - "name": "set push constants", - "TODO": [ - "data should be void*", - "TODO Vulkan has an additional stage mask" - ], - "args": [ - {"name": "stage", "type": "shader stage bit"}, - {"name": "offset", "type": "uint32_t"}, - {"name": "count", "type": "uint32_t"}, - {"name": "data", "type": "uint32_t", "annotation": "const*", "length": "count"} - ] - }, - { - "name": "set pipeline", - "args": [ - {"name": "pipeline", "type": "pipeline"} - ], - "notes": [ - "Not specifying graphics or compute because we know from render pass" - ] - }, - { - "name": "set vertex buffers", - "args": [ - {"name": "start slot", "type": "uint32_t"}, - {"name": "count", "type": "uint32_t"}, - {"name": "buffers", "type": "buffer", "annotation": "const*", "length": "count"}, - {"name": "offsets", "type": "uint32_t", "annotation": "const*", "length": "count"} - ] - }, - { - "name": "transition buffer usage", - "args": [ - {"name": "buffer", "type": "buffer"}, - {"name": "usage", "type": "buffer usage bit"} - ] - }, - { - "name": "transition texture usage", - "args": [ - {"name": "texture", "type": "texture"}, - {"name": "usage", "type": "texture usage bit"} - ] - } - ] - }, - "device": { - "category": "object", - "methods": [ - { - "name": "create bind group builder", - "returns": "bind group builder" - }, - { - "name": "create bind group layout builder", - "returns": "bind group layout builder" - }, - { - "name": "create buffer builder", - "returns": "buffer builder" - }, - { - "name": "create command buffer builder", - "returns": "command buffer builder" - }, - { - "name": "create framebuffer builder", - "returns": "framebuffer builder" - }, - { - "name": "create input state builder", - "returns": "input state builder" - }, - { - "name": "create pipeline builder", - "returns": "pipeline builder" - }, - { - "name": "create pipeline layout builder", - "returns": "pipeline layout builder" - }, - { - "name": "create queue builder", - "returns": "queue builder" - }, - { - "name": "create render pass builder", - "returns": "render pass builder" - }, - { - "name": "create sampler builder", - "returns": "sampler builder" - }, - { - "name": "create shader module builder", - "returns": "shader module builder" - }, - { - "name": "create texture builder", - "returns": "texture builder" - }, - { - "name": "copy bind groups", - "args": [ - {"name": "start", "type": "uint32_t"}, - {"name": "count", "type": "uint32_t"}, - {"name": "source", "type": "bind group"}, - {"name": "target", "type": "bind group"} - ] - }, - { - "name": "set error callback", - "args": [ - {"name": "callback", "type": "device error callback"}, - {"name": "userdata", "type": "callback userdata"} - ] - } - ] - }, - "device error callback": { - "category": "natively defined" - }, - "filter mode": { - "category": "enum", - "values": [ - {"value": 0, "name":"nearest"}, - {"value": 1, "name":"linear"} - ] - }, - "framebuffer": { - "category": "object" - }, - "framebuffer builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "framebuffer" - }, - { - "name": "set render pass", - "args": [ - {"name": "render pass", "type": "render pass"} - ] - }, - { - "name": "set dimensions", - "args": [ - {"name": "width", "type": "uint32_t"}, - {"name": "height", "type": "uint32_t"} - ] - }, - { - "name": "set attachment", - "args": [ - {"name": "attachment slot", "type": "uint32_t"}, - {"name": "texture views", "type": "texture view"} - ] - } - ] - }, - "index format": { - "category": "enum", - "values": [ - {"value": 0, "name": "uint16"}, - {"value": 1, "name": "uint32"} - ] - }, - "input state": { - "category": "object" - }, - "input state builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "input state" - }, - { - "name": "set attribute", - "args": [ - {"name": "shader location", "type": "uint32_t"}, - {"name": "binding slot", "type": "uint32_t"}, - {"name": "format", "type": "vertex format"}, - {"name": "offset", "type": "uint32_t"} - ] - }, - { - "name": "set input", - "args": [ - {"name": "binding slot", "type": "uint32_t"}, - {"name": "stride", "type": "uint32_t"}, - {"name": "step mode", "type": "input step mode"} - ] - } - ] - }, - "input step mode": { - "category": "enum", - "values": [ - {"value": 0, "name": "vertex"}, - {"value": 1, "name": "instance"} - ] - }, - "pipeline": { - "category": "object" - }, - "pipeline builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "pipeline" - }, - { - "name": "set layout", - "args": [ - {"name": "layout", "type": "pipeline layout"} - ] - }, - { - "name": "set subpass", - "args": [ - {"name": "render pass", "type": "render pass"}, - {"name": "subpass", "type": "uint32_t"} - ] - }, - { - "name": "set stage", - "args": [ - {"name": "stage", "type": "shader stage"}, - {"name": "module", "type": "shader module"}, - {"name": "entry point", "type": "char", "annotation": "const*", "length": "strlen"} - ] - }, - { - "name": "set input state", - "args": [ - {"name": "input", "type": "input state"} - ] - } - ] - }, - "pipeline layout": { - "category": "object" - }, - "pipeline layout builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "pipeline layout" - }, - { - "name": "set bind group layout", - "args": [ - {"name": "group index", "type": "uint32_t"}, - {"name": "layout", "type": "bind group layout"} - ] - } - ] - }, - "queue": { - "category": "object", - "methods": [ - { - "name": "submit", - "args": [ - {"name": "num commands", "type": "uint32_t"}, - {"name": "commands", "type": "command buffer", "annotation": "const*", "length": "num commands"} - ] - } - ] - }, - "queue builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "queue" - } - ] - }, - "render pass builder": { - "category": "object", - "TODO": { - "attachments": "Also need load op, store op, depth/stencil attachments and depth/stencil ops, and maybe usages for the implicit attachment transitions", - "subpasses": "Also need input attachments, resolve attachments, and preserve attachments" - }, - "methods": [ - { - "name": "get result", - "returns": "render pass" - }, - { - "name": "set attachment count", - "args": [ - {"name": "attachment count", "type": "uint32_t"} - ] - }, - { - "name": "attachment set format", - "TODO": "Also need sample count", - "args": [ - {"name": "attachment slot", "type": "uint32_t"}, - {"name": "format", "type": "texture format"} - ] - }, - { - "name": "set subpass count", - "args": [ - {"name": "subpass count", "type": "uint32_t"} - ] - }, - { - "name": "subpass set color attachment", - "args": [ - {"name": "subpass index", "type": "uint32_t"}, - {"name": "output attachment location", "type": "uint32_t"}, - {"name": "attachment slot", "type": "uint32_t"} - ] - } - ] - }, - "render pass": { - "category": "object" - }, - "sampler": { - "category": "object" - }, - "sampler builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "sampler" - }, - { - "name": "set filter mode", - "args": [ - {"name": "mag filter", "type": "filter mode"}, - {"name": "min filter", "type": "filter mode"}, - {"name": "mipmap filter", "type": "filter mode"} - ] - } - ] - }, - "shader module": { - "category": "object" - }, - "shader module builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "shader module" - }, - { - "name": "set source", - "args": [ - {"name": "code size", "type": "uint32_t"}, - {"name": "code", "type": "uint32_t", "annotation": "const*", "length": "code size"} - ] - } - ] - }, - "shader stage": { - "category": "enum", - "values": [ - {"value": 0, "name": "vertex"}, - {"value": 1, "name": "fragment"}, - {"value": 2, "name": "compute"} - ] - }, - "shader stage bit": { - "category": "bitmask", - "values": [ - {"value": 1, "name": "vertex"}, - {"value": 2, "name": "fragment"}, - {"value": 4, "name": "compute"} - ] - }, - "texture": { - "category": "object", - "methods": [ - { - "name": "create texture view builder", - "returns": "texture view builder" - }, - { - "name": "transition usage", - "args": [ - {"name": "usage", "type": "texture usage bit"} - ] - }, - { - "name": "freeze usage", - "args": [ - {"name": "usage", "type": "texture usage bit"} - ] - } - ] - }, - "texture builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "texture" - }, - { - "name": "set dimension", - "args": [ - {"name": "dimension", "type": "texture dimension"} - ] - }, - { - "name": "set extent", - "args": [ - {"name": "width", "type": "uint32_t"}, - {"name": "height", "type": "uint32_t"}, - {"name": "depth", "type": "uint32_t"} - ] - }, - { - "name": "set format", - "args": [ - {"name": "format", "type": "texture format"} - ] - }, - { - "name": "set mip levels", - "args": [ - {"name": "num mip levels", "type": "uint32_t"} - ] - }, - { - "name": "set allowed usage", - "args": [ - {"name": "usage", "type": "texture usage bit"} - ] - }, - { - "name": "set initial usage", - "args": [ - {"name": "usage", "type": "texture usage bit"} - ] - } - ] - }, - "texture dimension": { - "category": "enum", - "values": [ - {"value": 0, "name": "2D"} - ] - }, - "texture usage bit": { - "category": "bitmask", - "values": [ - {"value": 0, "name": "none"}, - {"value": 1, "name": "transfer src"}, - {"value": 2, "name": "transfer dst"}, - {"value": 4, "name": "sampled"}, - {"value": 8, "name": "storage"}, - {"value": 16, "name": "color attachment"}, - {"value": 32, "name": "depth stencil attachment"} - ] - }, - "texture view": { - "category": "object" - }, - "texture view builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "texture view" - } - ] - }, - "texture format": { - "category": "enum", - "values": [ - {"value": 0, "name": "r8 g8 b8 a8 unorm"} - ] - }, - "vertex format": { - "category": "enum", - "values": [ - {"value": 0, "name": "float r32 g32 b32 a32"}, - {"value": 1, "name": "float r32 g32 b32"}, - {"value": 2, "name": "float r32 g32"} - ] - }, - "void": { - "category": "native" - }, - "uint32_t": { - "category": "native" - } -} +{ + "_comment": [ + "Copyright 2017 The NXT Authors", + "", + "Licensed under the Apache License, Version 2.0 (the \"License\");", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + " http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an \"AS IS\" BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "bind group": { + "category": "object" + }, + "bind group builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "bind group" + }, + { + "name": "set layout", + "args": [ + {"name": "layout", "type": "bind group layout"} + ] + }, + { + "name": "set usage", + "args": [ + {"name": "usage", "type": "bind group usage"} + ] + }, + { + "name": "set buffer views", + "args": [ + {"name": "start", "type": "uint32_t"}, + {"name": "count", "type": "uint32_t"}, + {"name": "buffer views", "type": "buffer view", "annotation": "const*", "length": "count"} + ] + }, + { + "name": "set samplers", + "args": [ + {"name": "start", "type": "uint32_t"}, + {"name": "count", "type": "uint32_t"}, + {"name": "samplers", "type": "sampler", "annotation": "const*", "length": "count"} + ] + }, + { + "name": "set texture views", + "args": [ + {"name": "start", "type": "uint32_t"}, + {"name": "count", "type": "uint32_t"}, + {"name": "texture views", "type": "texture view", "annotation": "const*", "length": "count"} + ] + } + ], + "TODO": [ + "When resource are added, add methods for setting the content of the bind group" + ] + }, + "bind group usage": { + "category": "enum", + "values": [ + {"value": 0, "name": "frozen"}, + {"value": 1, "name": "dynamic"} + ] + }, + "bind group layout": { + "category": "object" + }, + "bind group layout builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "bind group layout" + }, + { + "name": "set bindings type", + "args": [ + {"name": "visibility", "type": "shader stage bit"}, + {"name": "binding type", "type": "binding type"}, + {"name": "start", "type": "uint32_t"}, + {"name": "count", "type": "uint32_t"} + ] + } + ] + }, + "binding type": { + "category": "enum", + "values": [ + {"value": 0, "name": "uniform buffer"}, + {"value": 1, "name": "sampler"}, + {"value": 2, "name": "sampled texture"}, + {"value": 3, "name": "storage buffer"} + ] + }, + "builder error status": { + "category": "enum", + "values": [ + {"value": 0, "name": "success"}, + {"value": 1, "name": "error", "TODO": "cwallez@chromium.org: recoverable errors like GPU OOM"}, + {"value": 2, "name": "unknown"}, + {"value": 3, "name": "context lost"} + ] + }, + "builder error callback": { + "category": "natively defined" + }, + "buffer": { + "category": "object", + "methods": [ + { + "name": "create buffer view builder", + "returns": "buffer view builder" + }, + { + "name": "set sub data", + "args": [ + {"name": "start", "type": "uint32_t"}, + {"name": "count", "type": "uint32_t"}, + {"name": "data", "type": "uint32_t", "annotation": "const*", "length": "count"} + ] + }, + { + "name": "transition usage", + "args": [ + {"name": "usage", "type": "buffer usage bit"} + ] + }, + { + "name": "freeze usage", + "args": [ + {"name": "usage", "type": "buffer usage bit"} + ] + } + ] + }, + "buffer builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "buffer" + }, + { + "name": "set allowed usage", + "args": [ + {"name": "usage", "type": "buffer usage bit"} + ] + }, + { + "name": "set initial usage", + "args": [ + {"name": "usage", "type": "buffer usage bit"} + ] + }, + { + "name": "set size", + "args": [ + {"name": "size", "type": "uint32_t"} + ] + } + ] + }, + "buffer usage bit": { + "category": "bitmask", + "values": [ + {"value": 0, "name": "none"}, + {"value": 1, "name": "mapped"}, + {"value": 2, "name": "transfer src"}, + {"value": 4, "name": "transfer dst"}, + {"value": 8, "name": "index"}, + {"value": 16, "name": "vertex"}, + {"value": 32, "name": "uniform"}, + {"value": 64, "name": "storage"} + ] + }, + "buffer view": { + "category": "object" + }, + "buffer view builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "buffer view" + }, + { + "name": "set extent", + "args": [ + {"name": "offset", "type": "uint32_t"}, + {"name": "size", "type": "uint32_t"} + ] + } + ] + }, + "callback userdata": { + "category": "natively defined" + }, + "char": { + "category": "native" + }, + "command buffer": { + "category": "object" + }, + "command buffer builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "command buffer" + }, + { + "name": "begin render pass", + "args": [ + {"name": "render pass", "type": "render pass"}, + {"name": "framebuffer", "type": "framebuffer"} + ] + }, + { + "name": "advance subpass" + }, + { + "name": "end render pass" + }, + { + "name": "copy buffer to texture", + "args": [ + {"name": "buffer", "type": "buffer"}, + {"name": "buffer offset", "type": "uint32_t"}, + {"name": "texture", "type": "texture"}, + {"name": "x", "type": "uint32_t"}, + {"name": "y", "type": "uint32_t"}, + {"name": "z", "type": "uint32_t"}, + {"name": "width", "type": "uint32_t"}, + {"name": "height", "type": "uint32_t"}, + {"name": "depth", "type": "uint32_t"}, + {"name": "level", "type": "uint32_t"} + ], + "TODO": [ + "Make pretty with Offset and Extents structures", + "Allow choosing the aspect (depth vs. stencil)?", + "Add these arguments too", + {"name": "row length", "type": "uint32_t"}, + {"name": "image height", "type": "uint32_t"} + ] + }, + { + "name": "dispatch", + "args": [ + {"name": "x", "type": "uint32_t"}, + {"name": "y", "type": "uint32_t"}, + {"name": "z", "type": "uint32_t"} + ] + }, + { + "name": "draw arrays", + "args": [ + {"name": "vertex count", "type": "uint32_t"}, + {"name": "instance count", "type": "uint32_t"}, + {"name": "first vertex", "type": "uint32_t"}, + {"name": "first instance", "type": "uint32_t"} + ] + }, + { + "name": "draw elements", + "args": [ + {"name": "index count", "type": "uint32_t"}, + {"name": "instance count", "type": "uint32_t"}, + {"name": "first index", "type": "uint32_t"}, + {"name": "first instance", "type": "uint32_t"} + ] + }, + { + "name": "set bind group", + "args": [ + {"name": "group index", "type": "uint32_t"}, + {"name": "group", "type": "bind group"} + ] + }, + { + "name": "set index buffer", + "args": [ + {"name": "buffer", "type": "buffer"}, + {"name": "offset", "type": "uint32_t"}, + {"name": "format", "type": "index format"} + ] + }, + { + "name": "set push constants", + "TODO": [ + "data should be void*", + "TODO Vulkan has an additional stage mask" + ], + "args": [ + {"name": "stage", "type": "shader stage bit"}, + {"name": "offset", "type": "uint32_t"}, + {"name": "count", "type": "uint32_t"}, + {"name": "data", "type": "uint32_t", "annotation": "const*", "length": "count"} + ] + }, + { + "name": "set pipeline", + "args": [ + {"name": "pipeline", "type": "pipeline"} + ], + "notes": [ + "Not specifying graphics or compute because we know from render pass" + ] + }, + { + "name": "set vertex buffers", + "args": [ + {"name": "start slot", "type": "uint32_t"}, + {"name": "count", "type": "uint32_t"}, + {"name": "buffers", "type": "buffer", "annotation": "const*", "length": "count"}, + {"name": "offsets", "type": "uint32_t", "annotation": "const*", "length": "count"} + ] + }, + { + "name": "transition buffer usage", + "args": [ + {"name": "buffer", "type": "buffer"}, + {"name": "usage", "type": "buffer usage bit"} + ] + }, + { + "name": "transition texture usage", + "args": [ + {"name": "texture", "type": "texture"}, + {"name": "usage", "type": "texture usage bit"} + ] + } + ] + }, + "compare function": { + "category": "enum", + "values": [ + {"value": 0, "name": "never"}, + {"value": 1, "name": "less"}, + {"value": 2, "name": "less equal"}, + {"value": 3, "name": "greater"}, + {"value": 4, "name": "greater equal"}, + {"value": 5, "name": "equal"}, + {"value": 6, "name": "not equal"}, + {"value": 7, "name": "always"} + ] + }, + "device": { + "category": "object", + "methods": [ + { + "name": "create bind group builder", + "returns": "bind group builder" + }, + { + "name": "create bind group layout builder", + "returns": "bind group layout builder" + }, + { + "name": "create buffer builder", + "returns": "buffer builder" + }, + { + "name": "create command buffer builder", + "returns": "command buffer builder" + }, + { + "name": "create depth stencil state builder", + "returns": "depth stencil state builder" + }, + { + "name": "create framebuffer builder", + "returns": "framebuffer builder" + }, + { + "name": "create input state builder", + "returns": "input state builder" + }, + { + "name": "create pipeline builder", + "returns": "pipeline builder" + }, + { + "name": "create pipeline layout builder", + "returns": "pipeline layout builder" + }, + { + "name": "create queue builder", + "returns": "queue builder" + }, + { + "name": "create render pass builder", + "returns": "render pass builder" + }, + { + "name": "create sampler builder", + "returns": "sampler builder" + }, + { + "name": "create shader module builder", + "returns": "shader module builder" + }, + { + "name": "create texture builder", + "returns": "texture builder" + }, + { + "name": "copy bind groups", + "args": [ + {"name": "start", "type": "uint32_t"}, + {"name": "count", "type": "uint32_t"}, + {"name": "source", "type": "bind group"}, + {"name": "target", "type": "bind group"} + ] + }, + { + "name": "set error callback", + "args": [ + {"name": "callback", "type": "device error callback"}, + {"name": "userdata", "type": "callback userdata"} + ] + } + ] + }, + "depth stencil state": { + "category": "object" + }, + "depth stencil state builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "depth stencil state" + }, + { + "name": "set depth enabled", + "args": [ + {"name": "depth enabled", "type": "bool"} + ] + }, + { + "name": "set depth compare function", + "args": [ + {"name": "depth compare function", "type": "compare function"} + ] + }, + { + "name": "set depth write", + "args" : [ + {"name": "depth write mode", "type": "depth write mode"} + ] + }, + { + "name": "set stencil enabled", + "args": [ + {"name": "stencil enabled", "type": "bool"} + ] + }, + { + "name": "set stencil reference mode", + "args": [ + {"name": "reference mode", "type": "stencil reference mode"} + ] + }, + { + "name": "set stencil operation", + "args": [ + {"name": "face", "type": "face"}, + {"name": "stencil failure operation", "type": "stencil operation"}, + {"name": "depth failure operation", "type": "stencil operation"}, + {"name": "stencil pass operation", "type": "stencil operation"} + ] + }, + { + "name": "set stencil compare function", + "args": [ + {"name": "face", "type": "face"}, + {"name": "stencil compare function", "type": "compare function"} + ] + }, + { + "name": "set stencil mask", + "args": [ + {"name": "face", "type": "face"}, + {"name": "read mask", "type": "uint32_t"}, + {"name": "write mask", "type": "uint32_t"} + ] + }, + { + "name": "set stencil reference", + "args": [ + {"name": "face", "type": "face"}, + {"name": "reference", "type": "int"} + ] + } + ] + }, + "depth write mode": { + "category": "enum", + "values": [ + {"value": 0, "name": "disabled"}, + {"value": 1, "name": "enabled"} + ] + }, + "device error callback": { + "category": "natively defined" + }, + "face": { + "category": "bitmask", + "values": [ + {"value": 1, "name": "back"}, + {"value": 2, "name": "front"}, + {"value": 3, "name": "both"} + ] + }, + "filter mode": { + "category": "enum", + "values": [ + {"value": 0, "name":"nearest"}, + {"value": 1, "name":"linear"} + ] + }, + "framebuffer": { + "category": "object" + }, + "framebuffer builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "framebuffer" + }, + { + "name": "set render pass", + "args": [ + {"name": "render pass", "type": "render pass"} + ] + }, + { + "name": "set dimensions", + "args": [ + {"name": "width", "type": "uint32_t"}, + {"name": "height", "type": "uint32_t"} + ] + }, + { + "name": "set attachment", + "args": [ + {"name": "attachment slot", "type": "uint32_t"}, + {"name": "texture views", "type": "texture view"} + ] + } + ] + }, + "index format": { + "category": "enum", + "values": [ + {"value": 0, "name": "uint16"}, + {"value": 1, "name": "uint32"} + ] + }, + "input state": { + "category": "object" + }, + "input state builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "input state" + }, + { + "name": "set attribute", + "args": [ + {"name": "shader location", "type": "uint32_t"}, + {"name": "binding slot", "type": "uint32_t"}, + {"name": "format", "type": "vertex format"}, + {"name": "offset", "type": "uint32_t"} + ] + }, + { + "name": "set input", + "args": [ + {"name": "binding slot", "type": "uint32_t"}, + {"name": "stride", "type": "uint32_t"}, + {"name": "step mode", "type": "input step mode"} + ] + } + ] + }, + "input step mode": { + "category": "enum", + "values": [ + {"value": 0, "name": "vertex"}, + {"value": 1, "name": "instance"} + ] + }, + "pipeline": { + "category": "object" + }, + "pipeline builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "pipeline" + }, + { + "name": "set layout", + "args": [ + {"name": "layout", "type": "pipeline layout"} + ] + }, + { + "name": "set subpass", + "args": [ + {"name": "render pass", "type": "render pass"}, + {"name": "subpass", "type": "uint32_t"} + ] + }, + { + "name": "set stage", + "args": [ + {"name": "stage", "type": "shader stage"}, + {"name": "module", "type": "shader module"}, + {"name": "entry point", "type": "char", "annotation": "const*", "length": "strlen"} + ] + }, + { + "name": "set input state", + "args": [ + {"name": "input", "type": "input state"} + ] + }, + { + "name": "set depth stencil state", + "args": [ + {"name": "input", "type": "depth stencil state"} + ] + } + ] + }, + "pipeline layout": { + "category": "object" + }, + "pipeline layout builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "pipeline layout" + }, + { + "name": "set bind group layout", + "args": [ + {"name": "group index", "type": "uint32_t"}, + {"name": "layout", "type": "bind group layout"} + ] + } + ] + }, + "queue": { + "category": "object", + "methods": [ + { + "name": "submit", + "args": [ + {"name": "num commands", "type": "uint32_t"}, + {"name": "commands", "type": "command buffer", "annotation": "const*", "length": "num commands"} + ] + } + ] + }, + "queue builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "queue" + } + ] + }, + "render pass builder": { + "category": "object", + "TODO": { + "attachments": "Also need load op, store op, depth/stencil attachments and depth/stencil ops, and maybe usages for the implicit attachment transitions", + "subpasses": "Also need input attachments, resolve attachments, and preserve attachments" + }, + "methods": [ + { + "name": "get result", + "returns": "render pass" + }, + { + "name": "set attachment count", + "args": [ + {"name": "attachment count", "type": "uint32_t"} + ] + }, + { + "name": "attachment set format", + "TODO": "Also need sample count", + "args": [ + {"name": "attachment slot", "type": "uint32_t"}, + {"name": "format", "type": "texture format"} + ] + }, + { + "name": "set subpass count", + "args": [ + {"name": "subpass count", "type": "uint32_t"} + ] + }, + { + "name": "subpass set color attachment", + "args": [ + {"name": "subpass index", "type": "uint32_t"}, + {"name": "output attachment location", "type": "uint32_t"}, + {"name": "attachment slot", "type": "uint32_t"} + ] + } + ] + }, + "render pass": { + "category": "object" + }, + "sampler": { + "category": "object" + }, + "sampler builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "sampler" + }, + { + "name": "set filter mode", + "args": [ + {"name": "mag filter", "type": "filter mode"}, + {"name": "min filter", "type": "filter mode"}, + {"name": "mipmap filter", "type": "filter mode"} + ] + } + ] + }, + "shader module": { + "category": "object" + }, + "shader module builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "shader module" + }, + { + "name": "set source", + "args": [ + {"name": "code size", "type": "uint32_t"}, + {"name": "code", "type": "uint32_t", "annotation": "const*", "length": "code size"} + ] + } + ] + }, + "shader stage": { + "category": "enum", + "values": [ + {"value": 0, "name": "vertex"}, + {"value": 1, "name": "fragment"}, + {"value": 2, "name": "compute"} + ] + }, + "shader stage bit": { + "category": "bitmask", + "values": [ + {"value": 1, "name": "vertex"}, + {"value": 2, "name": "fragment"}, + {"value": 4, "name": "compute"} + ] + }, + "stencil reference mode": { + "category": "enum", + "values": [ + {"value": 0, "name": "static"}, + {"value": 1, "name": "dynamic"} + ] + }, + "stencil operation": { + "category": "enum", + "values": [ + {"value": 0, "name": "keep"}, + {"value": 1, "name": "zero"}, + {"value": 2, "name": "replace"}, + {"value": 3, "name": "invert"}, + {"value": 4, "name": "increment clamp"}, + {"value": 5, "name": "decrement clamp"}, + {"value": 6, "name": "increment wrap"}, + {"value": 7, "name": "decrement wrap"} + ] + }, + "texture": { + "category": "object", + "methods": [ + { + "name": "create texture view builder", + "returns": "texture view builder" + }, + { + "name": "transition usage", + "args": [ + {"name": "usage", "type": "texture usage bit"} + ] + }, + { + "name": "freeze usage", + "args": [ + {"name": "usage", "type": "texture usage bit"} + ] + } + ] + }, + "texture builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "texture" + }, + { + "name": "set dimension", + "args": [ + {"name": "dimension", "type": "texture dimension"} + ] + }, + { + "name": "set extent", + "args": [ + {"name": "width", "type": "uint32_t"}, + {"name": "height", "type": "uint32_t"}, + {"name": "depth", "type": "uint32_t"} + ] + }, + { + "name": "set format", + "args": [ + {"name": "format", "type": "texture format"} + ] + }, + { + "name": "set mip levels", + "args": [ + {"name": "num mip levels", "type": "uint32_t"} + ] + }, + { + "name": "set allowed usage", + "args": [ + {"name": "usage", "type": "texture usage bit"} + ] + }, + { + "name": "set initial usage", + "args": [ + {"name": "usage", "type": "texture usage bit"} + ] + } + ] + }, + "texture dimension": { + "category": "enum", + "values": [ + {"value": 0, "name": "2D"} + ] + }, + "texture usage bit": { + "category": "bitmask", + "values": [ + {"value": 0, "name": "none"}, + {"value": 1, "name": "transfer src"}, + {"value": 2, "name": "transfer dst"}, + {"value": 4, "name": "sampled"}, + {"value": 8, "name": "storage"}, + {"value": 16, "name": "color attachment"}, + {"value": 32, "name": "depth stencil attachment"} + ] + }, + "texture view": { + "category": "object" + }, + "texture view builder": { + "category": "object", + "methods": [ + { + "name": "get result", + "returns": "texture view" + } + ] + }, + "texture format": { + "category": "enum", + "values": [ + {"value": 0, "name": "r8 g8 b8 a8 unorm"} + ] + }, + "vertex format": { + "category": "enum", + "values": [ + {"value": 0, "name": "float r32 g32 b32 a32"}, + {"value": 1, "name": "float r32 g32 b32"}, + {"value": 2, "name": "float r32 g32"} + ] + }, + "void": { + "category": "native" + }, + "uint32_t": { + "category": "native" + }, + "bool": { + "category": "native" + }, + "int": { + "category": "native" + } +} diff --git a/src/backend/CMakeLists.txt b/src/backend/CMakeLists.txt index 5978c5985e..b790bd07da 100644 --- a/src/backend/CMakeLists.txt +++ b/src/backend/CMakeLists.txt @@ -1,147 +1,149 @@ -# Copyright 2017 The NXT Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set(COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/common) -set(METAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/metal) -set(NULL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/null) -set(OPENGL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/opengl) -set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests) - -list(APPEND BACKEND_SOURCES - ${COMMON_DIR}/BindGroup.cpp - ${COMMON_DIR}/BindGroup.h - ${COMMON_DIR}/BindGroupLayout.cpp - ${COMMON_DIR}/BindGroupLayout.h - ${COMMON_DIR}/BitSetIterator.h - ${COMMON_DIR}/Builder.cpp - ${COMMON_DIR}/Builder.h - ${COMMON_DIR}/Buffer.cpp - ${COMMON_DIR}/Buffer.h - ${COMMON_DIR}/CommandAllocator.cpp - ${COMMON_DIR}/CommandAllocator.h - ${COMMON_DIR}/CommandBuffer.cpp - ${COMMON_DIR}/CommandBuffer.h - ${COMMON_DIR}/Device.cpp - ${COMMON_DIR}/Device.h - ${COMMON_DIR}/Forward.h - ${COMMON_DIR}/Framebuffer.cpp - ${COMMON_DIR}/Framebuffer.h - ${COMMON_DIR}/InputState.cpp - ${COMMON_DIR}/InputState.h - ${COMMON_DIR}/Math.cpp - ${COMMON_DIR}/Math.h - ${COMMON_DIR}/PerStage.cpp - ${COMMON_DIR}/PerStage.h - ${COMMON_DIR}/Pipeline.cpp - ${COMMON_DIR}/Pipeline.h - ${COMMON_DIR}/PipelineLayout.cpp - ${COMMON_DIR}/PipelineLayout.h - ${COMMON_DIR}/Queue.cpp - ${COMMON_DIR}/Queue.h - ${COMMON_DIR}/RenderPass.cpp - ${COMMON_DIR}/RenderPass.h - ${COMMON_DIR}/RefCounted.cpp - ${COMMON_DIR}/RefCounted.h - ${COMMON_DIR}/Sampler.cpp - ${COMMON_DIR}/Sampler.h - ${COMMON_DIR}/ShaderModule.cpp - ${COMMON_DIR}/ShaderModule.h - ${COMMON_DIR}/Texture.cpp - ${COMMON_DIR}/Texture.h - ${COMMON_DIR}/ToBackend.h -) - -# OpenGL Backend - -Generate( - LIB_NAME opengl_autogen - LIB_TYPE STATIC - PRINT_NAME "OpenGL backend autogenerated files" - COMMAND_LINE_ARGS - ${GENERATOR_COMMON_ARGS} - -T opengl -) -target_link_libraries(opengl_autogen glfw glad nxtcpp) -target_include_directories(opengl_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(opengl_autogen PUBLIC ${GENERATED_DIR}) -SetCXX14(opengl_autogen) -SetPIC(opengl_autogen) - -list(APPEND BACKEND_SOURCES - ${OPENGL_DIR}/CommandBufferGL.cpp - ${OPENGL_DIR}/CommandBufferGL.h - ${OPENGL_DIR}/OpenGLBackend.cpp - ${OPENGL_DIR}/OpenGLBackend.h - ${OPENGL_DIR}/PipelineGL.cpp - ${OPENGL_DIR}/PipelineGL.h - ${OPENGL_DIR}/PipelineLayoutGL.cpp - ${OPENGL_DIR}/PipelineLayoutGL.h - ${OPENGL_DIR}/SamplerGL.cpp - ${OPENGL_DIR}/SamplerGL.h - ${OPENGL_DIR}/ShaderModuleGL.cpp - ${OPENGL_DIR}/ShaderModuleGL.h - ${OPENGL_DIR}/TextureGL.cpp - ${OPENGL_DIR}/TextureGL.h -) - -# Null backend -Generate( - LIB_NAME null_autogen - LIB_TYPE STATIC - PRINT_NAME "Null backend autogenerated files" - COMMAND_LINE_ARGS - ${GENERATOR_COMMON_ARGS} - -T null -) -target_link_libraries(null_autogen nxtcpp) -target_include_directories(null_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_include_directories(null_autogen PUBLIC ${GENERATED_DIR}) -SetCXX14(null_autogen) -SetPIC(null_autogen) - -list(APPEND BACKEND_SOURCES - ${NULL_DIR}/NullBackend.cpp - ${NULL_DIR}/NullBackend.h -) - -# Metal Backend - -if (APPLE) - Generate( - LIB_NAME metal_autogen - LIB_TYPE STATIC - PRINT_NAME "Metal backend autogenerated files" - COMMAND_LINE_ARGS - ${GENERATOR_COMMON_ARGS} - -T metal - ) - target_link_libraries(metal_autogen glfw glad nxtcpp "-framework QuartzCore" "-framework Metal") - target_include_directories(metal_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - target_include_directories(metal_autogen PUBLIC ${GENERATED_DIR}) - SetCXX14(metal_autogen) - SetPIC(metal_autogen) - - list(APPEND BACKEND_SOURCES - ${METAL_DIR}/MetalBackend.mm - ${METAL_DIR}/MetalBackend.h - ) -endif() - -add_library(nxt_backend STATIC ${BACKEND_SOURCES}) -target_link_libraries(nxt_backend opengl_autogen null_autogen glfw glad spirv-cross) -if (APPLE) - target_link_libraries(nxt_backend metal_autogen) -endif() -target_include_directories(nxt_backend PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -SetCXX14(nxt_backend) +# Copyright 2017 The NXT Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set(COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/common) +set(METAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/metal) +set(NULL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/null) +set(OPENGL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/opengl) +set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests) + +list(APPEND BACKEND_SOURCES + ${COMMON_DIR}/BindGroup.cpp + ${COMMON_DIR}/BindGroup.h + ${COMMON_DIR}/BindGroupLayout.cpp + ${COMMON_DIR}/BindGroupLayout.h + ${COMMON_DIR}/BitSetIterator.h + ${COMMON_DIR}/Builder.cpp + ${COMMON_DIR}/Builder.h + ${COMMON_DIR}/Buffer.cpp + ${COMMON_DIR}/Buffer.h + ${COMMON_DIR}/CommandAllocator.cpp + ${COMMON_DIR}/CommandAllocator.h + ${COMMON_DIR}/CommandBuffer.cpp + ${COMMON_DIR}/CommandBuffer.h + ${COMMON_DIR}/DepthStencilState.cpp + ${COMMON_DIR}/DepthStencilState.h + ${COMMON_DIR}/Device.cpp + ${COMMON_DIR}/Device.h + ${COMMON_DIR}/Forward.h + ${COMMON_DIR}/Framebuffer.cpp + ${COMMON_DIR}/Framebuffer.h + ${COMMON_DIR}/InputState.cpp + ${COMMON_DIR}/InputState.h + ${COMMON_DIR}/Math.cpp + ${COMMON_DIR}/Math.h + ${COMMON_DIR}/PerStage.cpp + ${COMMON_DIR}/PerStage.h + ${COMMON_DIR}/Pipeline.cpp + ${COMMON_DIR}/Pipeline.h + ${COMMON_DIR}/PipelineLayout.cpp + ${COMMON_DIR}/PipelineLayout.h + ${COMMON_DIR}/Queue.cpp + ${COMMON_DIR}/Queue.h + ${COMMON_DIR}/RenderPass.cpp + ${COMMON_DIR}/RenderPass.h + ${COMMON_DIR}/RefCounted.cpp + ${COMMON_DIR}/RefCounted.h + ${COMMON_DIR}/Sampler.cpp + ${COMMON_DIR}/Sampler.h + ${COMMON_DIR}/ShaderModule.cpp + ${COMMON_DIR}/ShaderModule.h + ${COMMON_DIR}/Texture.cpp + ${COMMON_DIR}/Texture.h + ${COMMON_DIR}/ToBackend.h +) + +# OpenGL Backend + +Generate( + LIB_NAME opengl_autogen + LIB_TYPE STATIC + PRINT_NAME "OpenGL backend autogenerated files" + COMMAND_LINE_ARGS + ${GENERATOR_COMMON_ARGS} + -T opengl +) +target_link_libraries(opengl_autogen glfw glad nxtcpp) +target_include_directories(opengl_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(opengl_autogen PUBLIC ${GENERATED_DIR}) +SetCXX14(opengl_autogen) +SetPIC(opengl_autogen) + +list(APPEND BACKEND_SOURCES + ${OPENGL_DIR}/CommandBufferGL.cpp + ${OPENGL_DIR}/CommandBufferGL.h + ${OPENGL_DIR}/OpenGLBackend.cpp + ${OPENGL_DIR}/OpenGLBackend.h + ${OPENGL_DIR}/PipelineGL.cpp + ${OPENGL_DIR}/PipelineGL.h + ${OPENGL_DIR}/PipelineLayoutGL.cpp + ${OPENGL_DIR}/PipelineLayoutGL.h + ${OPENGL_DIR}/SamplerGL.cpp + ${OPENGL_DIR}/SamplerGL.h + ${OPENGL_DIR}/ShaderModuleGL.cpp + ${OPENGL_DIR}/ShaderModuleGL.h + ${OPENGL_DIR}/TextureGL.cpp + ${OPENGL_DIR}/TextureGL.h +) + +# Null backend +Generate( + LIB_NAME null_autogen + LIB_TYPE STATIC + PRINT_NAME "Null backend autogenerated files" + COMMAND_LINE_ARGS + ${GENERATOR_COMMON_ARGS} + -T null +) +target_link_libraries(null_autogen nxtcpp) +target_include_directories(null_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(null_autogen PUBLIC ${GENERATED_DIR}) +SetCXX14(null_autogen) +SetPIC(null_autogen) + +list(APPEND BACKEND_SOURCES + ${NULL_DIR}/NullBackend.cpp + ${NULL_DIR}/NullBackend.h +) + +# Metal Backend + +if (APPLE) + Generate( + LIB_NAME metal_autogen + LIB_TYPE STATIC + PRINT_NAME "Metal backend autogenerated files" + COMMAND_LINE_ARGS + ${GENERATOR_COMMON_ARGS} + -T metal + ) + target_link_libraries(metal_autogen glfw glad nxtcpp "-framework QuartzCore" "-framework Metal") + target_include_directories(metal_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_include_directories(metal_autogen PUBLIC ${GENERATED_DIR}) + SetCXX14(metal_autogen) + SetPIC(metal_autogen) + + list(APPEND BACKEND_SOURCES + ${METAL_DIR}/MetalBackend.mm + ${METAL_DIR}/MetalBackend.h + ) +endif() + +add_library(nxt_backend STATIC ${BACKEND_SOURCES}) +target_link_libraries(nxt_backend opengl_autogen null_autogen glfw glad spirv-cross) +if (APPLE) + target_link_libraries(nxt_backend metal_autogen) +endif() +target_include_directories(nxt_backend PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +SetCXX14(nxt_backend) diff --git a/src/backend/common/DepthStencilState.cpp b/src/backend/common/DepthStencilState.cpp new file mode 100644 index 0000000000..13ec722d3d --- /dev/null +++ b/src/backend/common/DepthStencilState.cpp @@ -0,0 +1,137 @@ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "DepthStencilState.h" + +#include "Device.h" + +namespace backend { + + // DepthStencilStateBase + + DepthStencilStateBase::DepthStencilStateBase(DepthStencilStateBuilder* builder) + : depthEnabled(builder->depthEnabled), stencilEnabled(builder->stencilEnabled), + depthInfo(builder->depthInfo), + stencilInfos { builder->stencilInfos[0], builder->stencilInfos[1] } { + } + + bool DepthStencilStateBase::DepthIsEnabled() const { + return depthEnabled; + } + + bool DepthStencilStateBase::StencilIsEnabled() const { + return stencilEnabled; + } + + nxt::StencilReferenceMode DepthStencilStateBase::GetStencilReferenceMode() const { + return referenceMode; + } + + const DepthStencilStateBase::DepthInfo& DepthStencilStateBase::GetDepth() const { + return depthInfo; + } + + const DepthStencilStateBase::StencilInfo& DepthStencilStateBase::GetStencil(nxt::Face face) const { + switch (face) { + case nxt::Face::Back: + return stencilInfos[0]; + case nxt::Face::Front: + return stencilInfos[1]; + default: + ASSERT(false); + } + } + + + // DepthStencilStateBuilder + + DepthStencilStateBuilder::DepthStencilStateBuilder(DeviceBase* device) : Builder(device) { + } + + DepthStencilStateBase* DepthStencilStateBuilder::GetResultImpl() { + return device->CreateDepthStencilState(this); + } + + void DepthStencilStateBuilder::SetDepthEnabled(bool depthEnabled) { + this->depthEnabled = depthEnabled; + } + + void DepthStencilStateBuilder::SetDepthCompareFunction(nxt::CompareFunction depthCompareFunction) { + depthInfo.compareFunction = depthCompareFunction; + } + + void DepthStencilStateBuilder::SetDepthWrite(nxt::DepthWriteMode depthWriteMode) { + depthInfo.depthWriteMode = depthWriteMode; + } + + void DepthStencilStateBuilder::SetStencilEnabled(bool stencilEnabled) { + this->stencilEnabled = stencilEnabled; + } + + void DepthStencilStateBuilder::SetStencilReferenceMode(nxt::StencilReferenceMode referenceMode) { + this->referenceMode = referenceMode; + } + + void DepthStencilStateBuilder::SetStencilOperation(nxt::Face face, nxt::StencilOperation stencilFail, + nxt::StencilOperation depthFail, nxt::StencilOperation stencilPass) { + if (face & nxt::Face::Back) { + auto& stencilInfo = stencilInfos[0]; + stencilInfo.stencilFail = stencilFail; + stencilInfo.depthFail = stencilFail; + stencilInfo.stencilPass = stencilPass; + } + if (face & nxt::Face::Front) { + auto& stencilInfo = stencilInfos[1]; + stencilInfo.stencilFail = stencilFail; + stencilInfo.depthFail = stencilFail; + stencilInfo.stencilPass = stencilPass; + } + } + + void DepthStencilStateBuilder::SetStencilCompareFunction(nxt::Face face, nxt::CompareFunction stencilCompareFunction) { + if (face & nxt::Face::Back) { + auto& stencilInfo = stencilInfos[0]; + stencilInfo.compareFunction = stencilCompareFunction; + } + if (face & nxt::Face::Front) { + auto& stencilInfo = stencilInfos[1]; + stencilInfo.compareFunction = stencilCompareFunction; + } + } + + void DepthStencilStateBuilder::SetStencilMask(nxt::Face face, uint32_t readMask, uint32_t writeMask) { + if (face & nxt::Face::Back) { + auto& stencilInfo = stencilInfos[0]; + stencilInfo.readMask = readMask; + stencilInfo.writeMask = writeMask; + } + if (face & nxt::Face::Front) { + auto& stencilInfo = stencilInfos[1]; + stencilInfo.readMask = readMask; + stencilInfo.writeMask = writeMask; + } + } + + void DepthStencilStateBuilder::SetStencilReference(nxt::Face face, int reference) { + if (face & nxt::Face::Back) { + auto& stencilInfo = stencilInfos[0]; + stencilInfo.reference = reference; + } + if (face & nxt::Face::Front) { + auto& stencilInfo = stencilInfos[1]; + stencilInfo.reference = reference; + } + } + +} diff --git a/src/backend/common/DepthStencilState.h b/src/backend/common/DepthStencilState.h new file mode 100644 index 0000000000..e69fcdf4c0 --- /dev/null +++ b/src/backend/common/DepthStencilState.h @@ -0,0 +1,90 @@ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_COMMON_DEPTHSTENCILSTATE_H_ +#define BACKEND_COMMON_DEPTHSTENCILSTATE_H_ + +#include "Forward.h" +#include "Builder.h" +#include "RefCounted.h" + +#include "nxt/nxtcpp.h" + +namespace backend { + + + class DepthStencilStateBase : public RefCounted { + public: + DepthStencilStateBase(DepthStencilStateBuilder* builder); + + struct DepthInfo { + nxt::CompareFunction compareFunction = nxt::CompareFunction::Less; + nxt::DepthWriteMode depthWriteMode = nxt::DepthWriteMode::Enabled; + }; + + struct StencilInfo { + nxt::CompareFunction compareFunction = nxt::CompareFunction::Always; + nxt::StencilOperation stencilFail = nxt::StencilOperation::Keep; + nxt::StencilOperation depthFail = nxt::StencilOperation::Keep; + nxt::StencilOperation stencilPass = nxt::StencilOperation::Keep; + uint32_t readMask = 0xff; + uint32_t writeMask = 0xff; + int reference = 0; + }; + + bool DepthIsEnabled() const; + bool StencilIsEnabled() const; + nxt::StencilReferenceMode GetStencilReferenceMode() const; + const DepthInfo& GetDepth() const; + const StencilInfo& GetStencil(nxt::Face face) const; + + private: + bool depthEnabled = false; + bool stencilEnabled = false; + nxt::StencilReferenceMode referenceMode = nxt::StencilReferenceMode::Static; + DepthInfo depthInfo; + StencilInfo stencilInfos[2]; + }; + + class DepthStencilStateBuilder : public Builder { + public: + DepthStencilStateBuilder(DeviceBase* device); + + // NXT API + void SetDepthEnabled(bool depthEnabled); + void SetDepthCompareFunction(nxt::CompareFunction depthCompareFunction); + void SetDepthWrite(nxt::DepthWriteMode depthWriteMode); + void SetStencilEnabled(bool stencilEnabled); + void SetStencilReferenceMode(nxt::StencilReferenceMode referenceMode); + void SetStencilOperation(nxt::Face face, nxt::StencilOperation stencilFail, + nxt::StencilOperation depthFail, nxt::StencilOperation stencilPass); + void SetStencilCompareFunction(nxt::Face face, nxt::CompareFunction stencilCompareFunction); + void SetStencilMask(nxt::Face face, uint32_t readMask, uint32_t writeMask); + void SetStencilReference(nxt::Face face, int reference); + + private: + friend class DepthStencilStateBase; + + DepthStencilStateBase* GetResultImpl() override; + + bool depthEnabled; + bool stencilEnabled; + nxt::StencilReferenceMode referenceMode; + DepthStencilStateBase::DepthInfo depthInfo; + DepthStencilStateBase::StencilInfo stencilInfos[2]; + }; + +} + +#endif // BACKEND_COMMON_DEPTHSTENCILSTATE_H_ diff --git a/src/backend/common/Device.cpp b/src/backend/common/Device.cpp index 713c7a5660..2db6c2b332 100644 --- a/src/backend/common/Device.cpp +++ b/src/backend/common/Device.cpp @@ -1,133 +1,137 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "Device.h" - -#include "BindGroup.h" -#include "BindGroupLayout.h" -#include "Buffer.h" -#include "CommandBuffer.h" -#include "Framebuffer.h" -#include "InputState.h" -#include "Pipeline.h" -#include "PipelineLayout.h" -#include "Queue.h" -#include "RenderPass.h" -#include "Sampler.h" -#include "ShaderModule.h" -#include "Texture.h" - -#include - -namespace backend { - - // DeviceBase::Caches - - // The caches are unordered_sets of pointers with special hash and compare functions - // to compare the value of the objects, instead of the pointers. - using BindGroupLayoutCache = std::unordered_set; - - struct DeviceBase::Caches { - BindGroupLayoutCache bindGroupLayouts; - }; - - // DeviceBase - - DeviceBase::DeviceBase() { - caches = new DeviceBase::Caches(); - } - - DeviceBase::~DeviceBase() { - delete caches; - } - - void DeviceBase::HandleError(const char* message) { - if (errorCallback) { - errorCallback(message, errorUserdata); - } - } - - void DeviceBase::SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata) { - this->errorCallback = callback; - this->errorUserdata = userdata; - } - - DeviceBase* DeviceBase::GetDevice() { - return this; - } - - BindGroupLayoutBase* DeviceBase::GetOrCreateBindGroupLayout(const BindGroupLayoutBase* blueprint, BindGroupLayoutBuilder* builder) { - // The blueprint is only used to search in the cache and is not modified. However cached - // objects can be modified, and unordered_set cannot search for a const pointer in a non - // const pointer set. That's why we do a const_cast here, but the blueprint won't be - // modified. - auto iter = caches->bindGroupLayouts.find(const_cast(blueprint)); - if (iter != caches->bindGroupLayouts.end()) { - return *iter; - } - - BindGroupLayoutBase* backendObj = CreateBindGroupLayout(builder); - caches->bindGroupLayouts.insert(backendObj); - return backendObj; - } - - void DeviceBase::UncacheBindGroupLayout(BindGroupLayoutBase* obj) { - caches->bindGroupLayouts.erase(obj); - } - - BindGroupBuilder* DeviceBase::CreateBindGroupBuilder() { - return new BindGroupBuilder(this); - } - BindGroupLayoutBuilder* DeviceBase::CreateBindGroupLayoutBuilder() { - return new BindGroupLayoutBuilder(this); - } - BufferBuilder* DeviceBase::CreateBufferBuilder() { - return new BufferBuilder(this); - } - CommandBufferBuilder* DeviceBase::CreateCommandBufferBuilder() { - return new CommandBufferBuilder(this); - } - FramebufferBuilder* DeviceBase::CreateFramebufferBuilder() { - return new FramebufferBuilder(this); - } - InputStateBuilder* DeviceBase::CreateInputStateBuilder() { - return new InputStateBuilder(this); - } - PipelineBuilder* DeviceBase::CreatePipelineBuilder() { - return new PipelineBuilder(this); - } - PipelineLayoutBuilder* DeviceBase::CreatePipelineLayoutBuilder() { - return new PipelineLayoutBuilder(this); - } - QueueBuilder* DeviceBase::CreateQueueBuilder() { - return new QueueBuilder(this); - } - RenderPassBuilder* DeviceBase::CreateRenderPassBuilder() { - return new RenderPassBuilder(this); - } - SamplerBuilder* DeviceBase::CreateSamplerBuilder() { - return new SamplerBuilder(this); - } - ShaderModuleBuilder* DeviceBase::CreateShaderModuleBuilder() { - return new ShaderModuleBuilder(this); - } - TextureBuilder* DeviceBase::CreateTextureBuilder() { - return new TextureBuilder(this); - } - - void DeviceBase::CopyBindGroups(uint32_t start, uint32_t count, BindGroupBase* source, BindGroupBase* target) { - // TODO(cwallez@chromium.org): update state tracking then call the backend - } - -} +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Device.h" + +#include "BindGroup.h" +#include "BindGroupLayout.h" +#include "Buffer.h" +#include "CommandBuffer.h" +#include "DepthStencilState.h" +#include "Framebuffer.h" +#include "InputState.h" +#include "Pipeline.h" +#include "PipelineLayout.h" +#include "Queue.h" +#include "RenderPass.h" +#include "Sampler.h" +#include "ShaderModule.h" +#include "Texture.h" + +#include + +namespace backend { + + // DeviceBase::Caches + + // The caches are unordered_sets of pointers with special hash and compare functions + // to compare the value of the objects, instead of the pointers. + using BindGroupLayoutCache = std::unordered_set; + + struct DeviceBase::Caches { + BindGroupLayoutCache bindGroupLayouts; + }; + + // DeviceBase + + DeviceBase::DeviceBase() { + caches = new DeviceBase::Caches(); + } + + DeviceBase::~DeviceBase() { + delete caches; + } + + void DeviceBase::HandleError(const char* message) { + if (errorCallback) { + errorCallback(message, errorUserdata); + } + } + + void DeviceBase::SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata) { + this->errorCallback = callback; + this->errorUserdata = userdata; + } + + DeviceBase* DeviceBase::GetDevice() { + return this; + } + + BindGroupLayoutBase* DeviceBase::GetOrCreateBindGroupLayout(const BindGroupLayoutBase* blueprint, BindGroupLayoutBuilder* builder) { + // The blueprint is only used to search in the cache and is not modified. However cached + // objects can be modified, and unordered_set cannot search for a const pointer in a non + // const pointer set. That's why we do a const_cast here, but the blueprint won't be + // modified. + auto iter = caches->bindGroupLayouts.find(const_cast(blueprint)); + if (iter != caches->bindGroupLayouts.end()) { + return *iter; + } + + BindGroupLayoutBase* backendObj = CreateBindGroupLayout(builder); + caches->bindGroupLayouts.insert(backendObj); + return backendObj; + } + + void DeviceBase::UncacheBindGroupLayout(BindGroupLayoutBase* obj) { + caches->bindGroupLayouts.erase(obj); + } + + BindGroupBuilder* DeviceBase::CreateBindGroupBuilder() { + return new BindGroupBuilder(this); + } + BindGroupLayoutBuilder* DeviceBase::CreateBindGroupLayoutBuilder() { + return new BindGroupLayoutBuilder(this); + } + BufferBuilder* DeviceBase::CreateBufferBuilder() { + return new BufferBuilder(this); + } + CommandBufferBuilder* DeviceBase::CreateCommandBufferBuilder() { + return new CommandBufferBuilder(this); + } + DepthStencilStateBuilder* DeviceBase::CreateDepthStencilStateBuilder() { + return new DepthStencilStateBuilder(this); + } + FramebufferBuilder* DeviceBase::CreateFramebufferBuilder() { + return new FramebufferBuilder(this); + } + InputStateBuilder* DeviceBase::CreateInputStateBuilder() { + return new InputStateBuilder(this); + } + PipelineBuilder* DeviceBase::CreatePipelineBuilder() { + return new PipelineBuilder(this); + } + PipelineLayoutBuilder* DeviceBase::CreatePipelineLayoutBuilder() { + return new PipelineLayoutBuilder(this); + } + QueueBuilder* DeviceBase::CreateQueueBuilder() { + return new QueueBuilder(this); + } + RenderPassBuilder* DeviceBase::CreateRenderPassBuilder() { + return new RenderPassBuilder(this); + } + SamplerBuilder* DeviceBase::CreateSamplerBuilder() { + return new SamplerBuilder(this); + } + ShaderModuleBuilder* DeviceBase::CreateShaderModuleBuilder() { + return new ShaderModuleBuilder(this); + } + TextureBuilder* DeviceBase::CreateTextureBuilder() { + return new TextureBuilder(this); + } + + void DeviceBase::CopyBindGroups(uint32_t start, uint32_t count, BindGroupBase* source, BindGroupBase* target) { + // TODO(cwallez@chromium.org): update state tracking then call the backend + } + +} diff --git a/src/backend/common/Device.h b/src/backend/common/Device.h index 7ba0705f2d..05cb13bccb 100644 --- a/src/backend/common/Device.h +++ b/src/backend/common/Device.h @@ -1,101 +1,103 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef BACKEND_COMMON_DEVICEBASE_H_ -#define BACKEND_COMMON_DEVICEBASE_H_ - -#include "common/Forward.h" -#include "common/RefCounted.h" - -#include "nxt/nxtcpp.h" - -namespace backend { - - using ErrorCallback = void (*)(const char* errorMessage, void* userData); - - class DeviceBase { - public: - DeviceBase(); - ~DeviceBase(); - - void HandleError(const char* message); - void SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata); - - // Used by autogenerated code, returns itself - DeviceBase* GetDevice(); - - virtual BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) = 0; - virtual BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) = 0; - virtual BufferBase* CreateBuffer(BufferBuilder* builder) = 0; - virtual BufferViewBase* CreateBufferView(BufferViewBuilder* builder) = 0; - virtual CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) = 0; - virtual FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) = 0; - virtual InputStateBase* CreateInputState(InputStateBuilder* builder) = 0; - virtual PipelineBase* CreatePipeline(PipelineBuilder* builder) = 0; - virtual PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) = 0; - virtual QueueBase* CreateQueue(QueueBuilder* builder) = 0; - virtual RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) = 0; - virtual SamplerBase* CreateSampler(SamplerBuilder* builder) = 0; - virtual ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) = 0; - virtual TextureBase* CreateTexture(TextureBuilder* builder) = 0; - virtual TextureViewBase* CreateTextureView(TextureViewBuilder* builder) = 0; - - // Many NXT objects are completely immutable once created which means that if two - // builders are given the same arguments, they can return the same object. Reusing - // objects will help make comparisons between objects by a single pointer comparison. - // - // Technically no object is immutable as they have a reference count, and an - // application with reference-counting issues could "see" that objects are reused. - // This is solved by automatic-reference counting, and also the fact that when using - // the client-server wire every creation will get a different proxy object, with a - // different reference count. - // - // When trying to create an object, we give both the builder and an example of what - // the built object will be, the "blueprint". The blueprint is just a FooBase object - // instead of a backend Foo object. If the blueprint doesn't match an object in the - // cache, then the builder is used to make a new object. - BindGroupLayoutBase* GetOrCreateBindGroupLayout(const BindGroupLayoutBase* blueprint, BindGroupLayoutBuilder* builder); - void UncacheBindGroupLayout(BindGroupLayoutBase* obj); - - // NXT API - BindGroupBuilder* CreateBindGroupBuilder(); - BindGroupLayoutBuilder* CreateBindGroupLayoutBuilder(); - BufferBuilder* CreateBufferBuilder(); - BufferViewBuilder* CreateBufferViewBuilder(); - CommandBufferBuilder* CreateCommandBufferBuilder(); - FramebufferBuilder* CreateFramebufferBuilder(); - InputStateBuilder* CreateInputStateBuilder(); - PipelineBuilder* CreatePipelineBuilder(); - PipelineLayoutBuilder* CreatePipelineLayoutBuilder(); - QueueBuilder* CreateQueueBuilder(); - RenderPassBuilder* CreateRenderPassBuilder(); - SamplerBuilder* CreateSamplerBuilder(); - ShaderModuleBuilder* CreateShaderModuleBuilder(); - TextureBuilder* CreateTextureBuilder(); - - void CopyBindGroups(uint32_t start, uint32_t count, BindGroupBase* source, BindGroupBase* target); - - private: - // The object caches aren't exposed in the header as they would require a lot of - // additional includes. - struct Caches; - Caches* caches = nullptr; - - nxt::DeviceErrorCallback errorCallback = nullptr; - nxt::CallbackUserdata errorUserdata = 0; - }; - -} - -#endif // BACKEND_COMMON_DEVICEBASE_H_ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_COMMON_DEVICEBASE_H_ +#define BACKEND_COMMON_DEVICEBASE_H_ + +#include "common/Forward.h" +#include "common/RefCounted.h" + +#include "nxt/nxtcpp.h" + +namespace backend { + + using ErrorCallback = void (*)(const char* errorMessage, void* userData); + + class DeviceBase { + public: + DeviceBase(); + ~DeviceBase(); + + void HandleError(const char* message); + void SetErrorCallback(nxt::DeviceErrorCallback callback, nxt::CallbackUserdata userdata); + + // Used by autogenerated code, returns itself + DeviceBase* GetDevice(); + + virtual BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) = 0; + virtual BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) = 0; + virtual BufferBase* CreateBuffer(BufferBuilder* builder) = 0; + virtual BufferViewBase* CreateBufferView(BufferViewBuilder* builder) = 0; + virtual CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) = 0; + virtual DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) = 0; + virtual FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) = 0; + virtual InputStateBase* CreateInputState(InputStateBuilder* builder) = 0; + virtual PipelineBase* CreatePipeline(PipelineBuilder* builder) = 0; + virtual PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) = 0; + virtual QueueBase* CreateQueue(QueueBuilder* builder) = 0; + virtual RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) = 0; + virtual SamplerBase* CreateSampler(SamplerBuilder* builder) = 0; + virtual ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) = 0; + virtual TextureBase* CreateTexture(TextureBuilder* builder) = 0; + virtual TextureViewBase* CreateTextureView(TextureViewBuilder* builder) = 0; + + // Many NXT objects are completely immutable once created which means that if two + // builders are given the same arguments, they can return the same object. Reusing + // objects will help make comparisons between objects by a single pointer comparison. + // + // Technically no object is immutable as they have a reference count, and an + // application with reference-counting issues could "see" that objects are reused. + // This is solved by automatic-reference counting, and also the fact that when using + // the client-server wire every creation will get a different proxy object, with a + // different reference count. + // + // When trying to create an object, we give both the builder and an example of what + // the built object will be, the "blueprint". The blueprint is just a FooBase object + // instead of a backend Foo object. If the blueprint doesn't match an object in the + // cache, then the builder is used to make a new object. + BindGroupLayoutBase* GetOrCreateBindGroupLayout(const BindGroupLayoutBase* blueprint, BindGroupLayoutBuilder* builder); + void UncacheBindGroupLayout(BindGroupLayoutBase* obj); + + // NXT API + BindGroupBuilder* CreateBindGroupBuilder(); + BindGroupLayoutBuilder* CreateBindGroupLayoutBuilder(); + BufferBuilder* CreateBufferBuilder(); + BufferViewBuilder* CreateBufferViewBuilder(); + CommandBufferBuilder* CreateCommandBufferBuilder(); + DepthStencilStateBuilder* CreateDepthStencilStateBuilder(); + FramebufferBuilder* CreateFramebufferBuilder(); + InputStateBuilder* CreateInputStateBuilder(); + PipelineBuilder* CreatePipelineBuilder(); + PipelineLayoutBuilder* CreatePipelineLayoutBuilder(); + QueueBuilder* CreateQueueBuilder(); + RenderPassBuilder* CreateRenderPassBuilder(); + SamplerBuilder* CreateSamplerBuilder(); + ShaderModuleBuilder* CreateShaderModuleBuilder(); + TextureBuilder* CreateTextureBuilder(); + + void CopyBindGroups(uint32_t start, uint32_t count, BindGroupBase* source, BindGroupBase* target); + + private: + // The object caches aren't exposed in the header as they would require a lot of + // additional includes. + struct Caches; + Caches* caches = nullptr; + + nxt::DeviceErrorCallback errorCallback = nullptr; + nxt::CallbackUserdata errorUserdata = 0; + }; + +} + +#endif // BACKEND_COMMON_DEVICEBASE_H_ diff --git a/src/backend/common/Forward.h b/src/backend/common/Forward.h index 6b501f86ad..a1cc1b7bcd 100644 --- a/src/backend/common/Forward.h +++ b/src/backend/common/Forward.h @@ -1,76 +1,78 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef BACKEND_COMMON_FORWARD_H_ -#define BACKEND_COMMON_FORWARD_H_ - -#include -#include - -#define ASSERT assert - -namespace backend { - - class BindGroupBase; - class BindGroupBuilder; - class BindGroupLayoutBase; - class BindGroupLayoutBuilder; - class BufferBase; - class BufferBuilder; - class BufferViewBase; - class BufferViewBuilder; - class CommandBufferBase; - class CommandBufferBuilder; - class FramebufferBase; - class FramebufferBuilder; - class InputStateBase; - class InputStateBuilder; - class PipelineBase; - class PipelineBuilder; - class PipelineLayoutBase; - class PipelineLayoutBuilder; - class QueueBase; - class QueueBuilder; - class RenderPassBase; - class RenderPassBuilder; - class SamplerBase; - class SamplerBuilder; - class ShaderModuleBase; - class ShaderModuleBuilder; - class TextureBase; - class TextureBuilder; - class TextureViewBase; - class TextureViewBuilder; - - class DeviceBase; - - template - class Ref; - - template - class PerStage; - - // TODO(cwallez@chromium.org): where should constants live? - static constexpr uint32_t kMaxPushConstants = 32u; - static constexpr uint32_t kMaxBindGroups = 4u; - static constexpr uint32_t kMaxBindingsPerGroup = 16u; // TODO(cwallez@chromium.org): investigate bindgroup limits - static constexpr uint32_t kMaxVertexAttributes = 16u; - static constexpr uint32_t kMaxVertexInputs = 16u; - static constexpr uint32_t kNumStages = 3; - static constexpr uint32_t kMaxColorAttachments = 4u; - - enum PushConstantType : uint8_t; -} - -#endif // BACKEND_COMMON_FORWARD_H_ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_COMMON_FORWARD_H_ +#define BACKEND_COMMON_FORWARD_H_ + +#include +#include + +#define ASSERT assert + +namespace backend { + + class BindGroupBase; + class BindGroupBuilder; + class BindGroupLayoutBase; + class BindGroupLayoutBuilder; + class BufferBase; + class BufferBuilder; + class BufferViewBase; + class BufferViewBuilder; + class CommandBufferBase; + class CommandBufferBuilder; + class DepthStencilStateBase; + class DepthStencilStateBuilder; + class FramebufferBase; + class FramebufferBuilder; + class InputStateBase; + class InputStateBuilder; + class PipelineBase; + class PipelineBuilder; + class PipelineLayoutBase; + class PipelineLayoutBuilder; + class QueueBase; + class QueueBuilder; + class RenderPassBase; + class RenderPassBuilder; + class SamplerBase; + class SamplerBuilder; + class ShaderModuleBase; + class ShaderModuleBuilder; + class TextureBase; + class TextureBuilder; + class TextureViewBase; + class TextureViewBuilder; + + class DeviceBase; + + template + class Ref; + + template + class PerStage; + + // TODO(cwallez@chromium.org): where should constants live? + static constexpr uint32_t kMaxPushConstants = 32u; + static constexpr uint32_t kMaxBindGroups = 4u; + static constexpr uint32_t kMaxBindingsPerGroup = 16u; // TODO(cwallez@chromium.org): investigate bindgroup limits + static constexpr uint32_t kMaxVertexAttributes = 16u; + static constexpr uint32_t kMaxVertexInputs = 16u; + static constexpr uint32_t kNumStages = 3; + static constexpr uint32_t kMaxColorAttachments = 4u; + + enum PushConstantType : uint8_t; +} + +#endif // BACKEND_COMMON_FORWARD_H_ diff --git a/src/backend/common/Pipeline.cpp b/src/backend/common/Pipeline.cpp index 2ed03164ac..e644492633 100644 --- a/src/backend/common/Pipeline.cpp +++ b/src/backend/common/Pipeline.cpp @@ -1,161 +1,173 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "Pipeline.h" - -#include "Device.h" -#include "InputState.h" -#include "PipelineLayout.h" -#include "RenderPass.h" -#include "ShaderModule.h" - -namespace backend { - - // PipelineBase - - PipelineBase::PipelineBase(PipelineBuilder* builder) - : device(builder->device), stageMask(builder->stageMask), layout(std::move(builder->layout)), - renderPass(std::move(builder->renderPass)), subpass(builder->subpass), - inputState(std::move(builder->inputState)) { - - if (stageMask != (nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment) && - stageMask != nxt::ShaderStageBit::Compute) { - builder->HandleError("Wrong combination of stage for pipeline"); - return; - } - - if (!IsCompute() && !renderPass) { - builder->HandleError("Pipeline render pass not set"); - return; - } - // TODO(kainino@chromium.org): Need to verify the pipeline against its render subpass. - - auto FillPushConstants = [](const ShaderModuleBase* module, PushConstantInfo* info) { - const auto& moduleInfo = module->GetPushConstants(); - info->mask = moduleInfo.mask; - - for (uint32_t i = 0; i < moduleInfo.names.size(); i++) { - unsigned int size = moduleInfo.sizes[i]; - if (size == 0) { - continue; - } - - for (uint32_t offset = 0; offset < size; offset++) { - info->types[i + offset] = moduleInfo.types[i]; - } - i += size - 1; - } - }; - - for (auto stageBit : IterateStages(builder->stageMask)) { - if (!builder->stages[stageBit].module->IsCompatibleWithPipelineLayout(layout.Get())) { - builder->HandleError("Stage not compatible with layout"); - return; - } - - FillPushConstants(builder->stages[stageBit].module.Get(), &pushConstants[stageBit]); - } - - if (!IsCompute()) { - if ((builder->stages[nxt::ShaderStage::Vertex].module->GetUsedVertexAttributes() & ~inputState->GetAttributesSetMask()).any()) { - builder->HandleError("Pipeline vertex stage uses inputs not in the input state"); - return; - } - } - } - - const PipelineBase::PushConstantInfo& PipelineBase::GetPushConstants(nxt::ShaderStage stage) const { - return pushConstants[stage]; - } - - nxt::ShaderStageBit PipelineBase::GetStageMask() const { - return stageMask; - } - - PipelineLayoutBase* PipelineBase::GetLayout() { - return layout.Get(); - } - - RenderPassBase* PipelineBase::GetRenderPass() { - return renderPass.Get(); - } - - InputStateBase* PipelineBase::GetInputState() { - return inputState.Get(); - } - - bool PipelineBase::IsCompute() const { - return stageMask == nxt::ShaderStageBit::Compute; - } - - // PipelineBuilder - - PipelineBuilder::PipelineBuilder(DeviceBase* device) - : Builder(device), stageMask(static_cast(0)) { - } - - const PipelineBuilder::StageInfo& PipelineBuilder::GetStageInfo(nxt::ShaderStage stage) const { - ASSERT(stageMask & StageBit(stage)); - return stages[stage]; - } - - PipelineBase* PipelineBuilder::GetResultImpl() { - // TODO(cwallez@chromium.org): the layout should be required, and put the default objects in the device - if (!layout) { - layout = device->CreatePipelineLayoutBuilder()->GetResult(); - } - if (!inputState) { - inputState = device->CreateInputStateBuilder()->GetResult(); - } - - return device->CreatePipeline(this); - } - - void PipelineBuilder::SetLayout(PipelineLayoutBase* layout) { - this->layout = layout; - } - - void PipelineBuilder::SetSubpass(RenderPassBase* renderPass, uint32_t subpass) { - this->renderPass = renderPass; - this->subpass = subpass; - } - - void PipelineBuilder::SetStage(nxt::ShaderStage stage, ShaderModuleBase* module, const char* entryPoint) { - if (entryPoint != std::string("main")) { - HandleError("Currently the entry point has to be main()"); - return; - } - - if (stage != module->GetExecutionModel()) { - HandleError("Setting module with wrong execution model"); - return; - } - - nxt::ShaderStageBit bit = StageBit(stage); - if (stageMask & bit) { - HandleError("Setting already set stage"); - return; - } - stageMask |= bit; - - stages[stage].module = module; - stages[stage].entryPoint = entryPoint; - } - - void PipelineBuilder::SetInputState(InputStateBase* inputState) { - this->inputState = inputState; - } - - -} +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Pipeline.h" + +#include "Device.h" +#include "DepthStencilState.h" +#include "InputState.h" +#include "PipelineLayout.h" +#include "RenderPass.h" +#include "ShaderModule.h" + +namespace backend { + + // PipelineBase + + PipelineBase::PipelineBase(PipelineBuilder* builder) + : device(builder->device), stageMask(builder->stageMask), layout(std::move(builder->layout)), + renderPass(std::move(builder->renderPass)), subpass(builder->subpass), + inputState(std::move(builder->inputState)), depthStencilState(std::move(builder->depthStencilState)) { + + if (stageMask != (nxt::ShaderStageBit::Vertex | nxt::ShaderStageBit::Fragment) && + stageMask != nxt::ShaderStageBit::Compute) { + builder->HandleError("Wrong combination of stage for pipeline"); + return; + } + + if (!IsCompute() && !renderPass) { + builder->HandleError("Pipeline render pass not set"); + return; + } + // TODO(kainino@chromium.org): Need to verify the pipeline against its render subpass. + + auto FillPushConstants = [](const ShaderModuleBase* module, PushConstantInfo* info) { + const auto& moduleInfo = module->GetPushConstants(); + info->mask = moduleInfo.mask; + + for (uint32_t i = 0; i < moduleInfo.names.size(); i++) { + unsigned int size = moduleInfo.sizes[i]; + if (size == 0) { + continue; + } + + for (uint32_t offset = 0; offset < size; offset++) { + info->types[i + offset] = moduleInfo.types[i]; + } + i += size - 1; + } + }; + + for (auto stageBit : IterateStages(builder->stageMask)) { + if (!builder->stages[stageBit].module->IsCompatibleWithPipelineLayout(layout.Get())) { + builder->HandleError("Stage not compatible with layout"); + return; + } + + FillPushConstants(builder->stages[stageBit].module.Get(), &pushConstants[stageBit]); + } + + if (!IsCompute()) { + if ((builder->stages[nxt::ShaderStage::Vertex].module->GetUsedVertexAttributes() & ~inputState->GetAttributesSetMask()).any()) { + builder->HandleError("Pipeline vertex stage uses inputs not in the input state"); + return; + } + } + } + + const PipelineBase::PushConstantInfo& PipelineBase::GetPushConstants(nxt::ShaderStage stage) const { + return pushConstants[stage]; + } + + nxt::ShaderStageBit PipelineBase::GetStageMask() const { + return stageMask; + } + + PipelineLayoutBase* PipelineBase::GetLayout() { + return layout.Get(); + } + + RenderPassBase* PipelineBase::GetRenderPass() { + return renderPass.Get(); + } + + InputStateBase* PipelineBase::GetInputState() { + return inputState.Get(); + } + + DepthStencilStateBase* PipelineBase::GetDepthStencilState() { + return depthStencilState.Get(); + } + + bool PipelineBase::IsCompute() const { + return stageMask == nxt::ShaderStageBit::Compute; + } + + // PipelineBuilder + + PipelineBuilder::PipelineBuilder(DeviceBase* device) + : Builder(device), stageMask(static_cast(0)) { + } + + const PipelineBuilder::StageInfo& PipelineBuilder::GetStageInfo(nxt::ShaderStage stage) const { + ASSERT(stageMask & StageBit(stage)); + return stages[stage]; + } + + PipelineBase* PipelineBuilder::GetResultImpl() { + // TODO(cwallez@chromium.org): the layout should be required, and put the default objects in the device + if (!layout) { + layout = device->CreatePipelineLayoutBuilder()->GetResult(); + } + if (!inputState) { + inputState = device->CreateInputStateBuilder()->GetResult(); + } + if (!depthStencilState) { + depthStencilState = device->CreateDepthStencilStateBuilder()->GetResult(); + } + + return device->CreatePipeline(this); + } + + void PipelineBuilder::SetLayout(PipelineLayoutBase* layout) { + this->layout = layout; + } + + void PipelineBuilder::SetSubpass(RenderPassBase* renderPass, uint32_t subpass) { + this->renderPass = renderPass; + this->subpass = subpass; + } + + void PipelineBuilder::SetStage(nxt::ShaderStage stage, ShaderModuleBase* module, const char* entryPoint) { + if (entryPoint != std::string("main")) { + HandleError("Currently the entry point has to be main()"); + return; + } + + if (stage != module->GetExecutionModel()) { + HandleError("Setting module with wrong execution model"); + return; + } + + nxt::ShaderStageBit bit = StageBit(stage); + if (stageMask & bit) { + HandleError("Setting already set stage"); + return; + } + stageMask |= bit; + + stages[stage].module = module; + stages[stage].entryPoint = entryPoint; + } + + void PipelineBuilder::SetInputState(InputStateBase* inputState) { + this->inputState = inputState; + } + + void PipelineBuilder::SetDepthStencilState(DepthStencilStateBase* depthStencilState) { + this->depthStencilState = depthStencilState; + } + + +} diff --git a/src/backend/common/Pipeline.h b/src/backend/common/Pipeline.h index 756e5add21..89f9c7c70e 100644 --- a/src/backend/common/Pipeline.h +++ b/src/backend/common/Pipeline.h @@ -1,96 +1,100 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef BACKEND_COMMON_PIPELINE_H_ -#define BACKEND_COMMON_PIPELINE_H_ - -#include "Forward.h" -#include "Builder.h" -#include "PerStage.h" -#include "RefCounted.h" - -#include "nxt/nxtcpp.h" - -#include -#include - -namespace backend { - - enum PushConstantType : uint8_t { - Int, - UInt, - Float, - }; - - class PipelineBase : public RefCounted { - public: - PipelineBase(PipelineBuilder* builder); - - struct PushConstantInfo { - std::bitset mask; - std::array types; - }; - const PushConstantInfo& GetPushConstants(nxt::ShaderStage stage) const; - nxt::ShaderStageBit GetStageMask() const; - - PipelineLayoutBase* GetLayout(); - RenderPassBase* GetRenderPass(); - InputStateBase* GetInputState(); - - // TODO(cwallez@chromium.org): split compute and render pipelines - bool IsCompute() const; - - private: - DeviceBase* device; - - nxt::ShaderStageBit stageMask; - Ref layout; - Ref renderPass; - uint32_t subpass; - PerStage pushConstants; - Ref inputState; - }; - - class PipelineBuilder : public Builder { - public: - PipelineBuilder(DeviceBase* device); - - struct StageInfo { - std::string entryPoint; - Ref module; - }; - const StageInfo& GetStageInfo(nxt::ShaderStage stage) const; - - // NXT API - void SetLayout(PipelineLayoutBase* layout); - void SetSubpass(RenderPassBase* renderPass, uint32_t subpass); - void SetStage(nxt::ShaderStage stage, ShaderModuleBase* module, const char* entryPoint); - void SetInputState(InputStateBase* inputState); - - private: - friend class PipelineBase; - - PipelineBase* GetResultImpl() override; - - Ref layout; - Ref renderPass; - uint32_t subpass; - nxt::ShaderStageBit stageMask; - PerStage stages; - Ref inputState; - }; - -} - -#endif // BACKEND_COMMON_PIPELINE_H_ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_COMMON_PIPELINE_H_ +#define BACKEND_COMMON_PIPELINE_H_ + +#include "Forward.h" +#include "Builder.h" +#include "PerStage.h" +#include "RefCounted.h" + +#include "nxt/nxtcpp.h" + +#include +#include + +namespace backend { + + enum PushConstantType : uint8_t { + Int, + UInt, + Float, + }; + + class PipelineBase : public RefCounted { + public: + PipelineBase(PipelineBuilder* builder); + + struct PushConstantInfo { + std::bitset mask; + std::array types; + }; + const PushConstantInfo& GetPushConstants(nxt::ShaderStage stage) const; + nxt::ShaderStageBit GetStageMask() const; + + PipelineLayoutBase* GetLayout(); + RenderPassBase* GetRenderPass(); + InputStateBase* GetInputState(); + DepthStencilStateBase* GetDepthStencilState(); + + // TODO(cwallez@chromium.org): split compute and render pipelines + bool IsCompute() const; + + private: + DeviceBase* device; + + nxt::ShaderStageBit stageMask; + Ref layout; + Ref renderPass; + uint32_t subpass; + PerStage pushConstants; + Ref inputState; + Ref depthStencilState; + }; + + class PipelineBuilder : public Builder { + public: + PipelineBuilder(DeviceBase* device); + + struct StageInfo { + std::string entryPoint; + Ref module; + }; + const StageInfo& GetStageInfo(nxt::ShaderStage stage) const; + + // NXT API + void SetLayout(PipelineLayoutBase* layout); + void SetSubpass(RenderPassBase* renderPass, uint32_t subpass); + void SetStage(nxt::ShaderStage stage, ShaderModuleBase* module, const char* entryPoint); + void SetInputState(InputStateBase* inputState); + void SetDepthStencilState(DepthStencilStateBase* depthStencilState); + + private: + friend class PipelineBase; + + PipelineBase* GetResultImpl() override; + + Ref layout; + Ref renderPass; + uint32_t subpass; + nxt::ShaderStageBit stageMask; + PerStage stages; + Ref inputState; + Ref depthStencilState; + }; + +} + +#endif // BACKEND_COMMON_PIPELINE_H_ diff --git a/src/backend/common/ToBackend.h b/src/backend/common/ToBackend.h index 09f8ab3a4b..4f5b9345b6 100644 --- a/src/backend/common/ToBackend.h +++ b/src/backend/common/ToBackend.h @@ -1,130 +1,135 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef BACKEND_COMMON_TOBACKEND_H_ -#define BACKEND_COMMON_TOBACKEND_H_ - -#include "Forward.h" - -namespace backend { - - // ToBackendTraits implements the mapping from base type to member type of BackendTraits - template - struct ToBackendTraits; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::BindGroupType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::BindGroupLayoutType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::BufferType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::BufferViewType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::CommandBufferType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::FramebufferType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::InputStateType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::PipelineType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::PipelineLayoutType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::QueueType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::RenderPassType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::SamplerType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::ShaderModuleType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::TextureType; - }; - - template - struct ToBackendTraits { - using BackendType = typename BackendTraits::TextureViewType; - }; - - // ToBackendBase implements conversion to the given BackendTraits - // To use it in a backend, use the following: - // template - // auto ToBackend(T&& common) -> decltype(ToBackendBase(common)) { - // return ToBackendBase(common); - // } - - template - Ref::BackendType>& ToBackendBase(Ref& common) { - return reinterpret_cast::BackendType>&>(common); - } - - template - const Ref::BackendType>& ToBackendBase(const Ref& common) { - return reinterpret_cast::BackendType>&>(common); - } - - template - typename ToBackendTraits::BackendType* ToBackendBase(T* common) { - return reinterpret_cast::BackendType*>(common); - } - - template - const typename ToBackendTraits::BackendType* ToBackendBase(const T* common) { - return reinterpret_cast::BackendType*>(common); - } - -} - -#endif // BACKEND_COMMON_TOBACKEND_H_ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_COMMON_TOBACKEND_H_ +#define BACKEND_COMMON_TOBACKEND_H_ + +#include "Forward.h" + +namespace backend { + + // ToBackendTraits implements the mapping from base type to member type of BackendTraits + template + struct ToBackendTraits; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::BindGroupType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::BindGroupLayoutType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::BufferType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::BufferViewType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::CommandBufferType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::DepthStencilStateType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::FramebufferType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::InputStateType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::PipelineType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::PipelineLayoutType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::QueueType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::RenderPassType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::SamplerType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::ShaderModuleType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::TextureType; + }; + + template + struct ToBackendTraits { + using BackendType = typename BackendTraits::TextureViewType; + }; + + // ToBackendBase implements conversion to the given BackendTraits + // To use it in a backend, use the following: + // template + // auto ToBackend(T&& common) -> decltype(ToBackendBase(common)) { + // return ToBackendBase(common); + // } + + template + Ref::BackendType>& ToBackendBase(Ref& common) { + return reinterpret_cast::BackendType>&>(common); + } + + template + const Ref::BackendType>& ToBackendBase(const Ref& common) { + return reinterpret_cast::BackendType>&>(common); + } + + template + typename ToBackendTraits::BackendType* ToBackendBase(T* common) { + return reinterpret_cast::BackendType*>(common); + } + + template + const typename ToBackendTraits::BackendType* ToBackendBase(const T* common) { + return reinterpret_cast::BackendType*>(common); + } + +} + +#endif // BACKEND_COMMON_TOBACKEND_H_ diff --git a/src/backend/null/NullBackend.cpp b/src/backend/null/NullBackend.cpp index ac7eba660c..c9eda8e38d 100644 --- a/src/backend/null/NullBackend.cpp +++ b/src/backend/null/NullBackend.cpp @@ -1,120 +1,123 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "NullBackend.h" - -#include - -namespace backend { -namespace null { - - nxtProcTable GetNonValidatingProcs(); - nxtProcTable GetValidatingProcs(); - - void Init(nxtProcTable* procs, nxtDevice* device) { - *procs = GetValidatingProcs(); - *device = reinterpret_cast(new Device); - } - - // Device - - Device::Device() { - } - - Device::~Device() { - } - - BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) { - return new BindGroupBase(builder); - } - BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) { - return new BindGroupLayoutBase(builder); - } - BufferBase* Device::CreateBuffer(BufferBuilder* builder) { - return new Buffer(builder); - } - BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) { - return new BufferViewBase(builder); - } - CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { - return new CommandBufferBase(builder); - } - InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { - return new InputStateBase(builder); - } - FramebufferBase* Device::CreateFramebuffer(FramebufferBuilder* builder) { - return new FramebufferBase(builder); - } - PipelineBase* Device::CreatePipeline(PipelineBuilder* builder) { - return new PipelineBase(builder); - } - PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { - return new PipelineLayoutBase(builder); - } - QueueBase* Device::CreateQueue(QueueBuilder* builder) { - return new Queue(builder); - } - RenderPassBase* Device::CreateRenderPass(RenderPassBuilder* builder) { - return new RenderPassBase(builder); - } - SamplerBase* Device::CreateSampler(SamplerBuilder* builder) { - return new SamplerBase(builder); - } - ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) { - auto module = new ShaderModuleBase(builder); - - spirv_cross::Compiler compiler(builder->AcquireSpirv()); - module->ExtractSpirvInfo(compiler); - - return module; - } - TextureBase* Device::CreateTexture(TextureBuilder* builder) { - return new TextureBase(builder); - } - TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) { - return new TextureViewBase(builder); - } - - void Device::Reference() { - } - - void Device::Release() { - } - - // Buffer - - Buffer::Buffer(BufferBuilder* builder) - : BufferBase(builder) { - } - - Buffer::~Buffer() { - } - - void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) { - } - - // Queue - - Queue::Queue(QueueBuilder* builder) - : QueueBase(builder) { - } - - Queue::~Queue() { - } - - void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) { - } - -} -} +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "NullBackend.h" + +#include + +namespace backend { +namespace null { + + nxtProcTable GetNonValidatingProcs(); + nxtProcTable GetValidatingProcs(); + + void Init(nxtProcTable* procs, nxtDevice* device) { + *procs = GetValidatingProcs(); + *device = reinterpret_cast(new Device); + } + + // Device + + Device::Device() { + } + + Device::~Device() { + } + + BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) { + return new BindGroupBase(builder); + } + BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) { + return new BindGroupLayoutBase(builder); + } + BufferBase* Device::CreateBuffer(BufferBuilder* builder) { + return new Buffer(builder); + } + BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) { + return new BufferViewBase(builder); + } + CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { + return new CommandBufferBase(builder); + } + DepthStencilStateBase* Device::CreateDepthStencilState(DepthStencilStateBuilder* builder) { + return new DepthStencilStateBase(builder); + } + InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { + return new InputStateBase(builder); + } + FramebufferBase* Device::CreateFramebuffer(FramebufferBuilder* builder) { + return new FramebufferBase(builder); + } + PipelineBase* Device::CreatePipeline(PipelineBuilder* builder) { + return new PipelineBase(builder); + } + PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { + return new PipelineLayoutBase(builder); + } + QueueBase* Device::CreateQueue(QueueBuilder* builder) { + return new Queue(builder); + } + RenderPassBase* Device::CreateRenderPass(RenderPassBuilder* builder) { + return new RenderPassBase(builder); + } + SamplerBase* Device::CreateSampler(SamplerBuilder* builder) { + return new SamplerBase(builder); + } + ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) { + auto module = new ShaderModuleBase(builder); + + spirv_cross::Compiler compiler(builder->AcquireSpirv()); + module->ExtractSpirvInfo(compiler); + + return module; + } + TextureBase* Device::CreateTexture(TextureBuilder* builder) { + return new TextureBase(builder); + } + TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) { + return new TextureViewBase(builder); + } + + void Device::Reference() { + } + + void Device::Release() { + } + + // Buffer + + Buffer::Buffer(BufferBuilder* builder) + : BufferBase(builder) { + } + + Buffer::~Buffer() { + } + + void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) { + } + + // Queue + + Queue::Queue(QueueBuilder* builder) + : QueueBase(builder) { + } + + Queue::~Queue() { + } + + void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) { + } + +} +} diff --git a/src/backend/null/NullBackend.h b/src/backend/null/NullBackend.h index 1b61c462f9..e0cd371aae 100644 --- a/src/backend/null/NullBackend.h +++ b/src/backend/null/NullBackend.h @@ -1,125 +1,129 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef BACKEND_NULL_NULLBACKEND_H_ -#define BACKEND_NULL_NULLBACKEND_H_ - -#include "nxt/nxtcpp.h" - -#include "common/Buffer.h" -#include "common/BindGroup.h" -#include "common/BindGroupLayout.h" -#include "common/Device.h" -#include "common/CommandBuffer.h" -#include "common/InputState.h" -#include "common/Framebuffer.h" -#include "common/Pipeline.h" -#include "common/PipelineLayout.h" -#include "common/Queue.h" -#include "common/RenderPass.h" -#include "common/Sampler.h" -#include "common/ShaderModule.h" -#include "common/Texture.h" -#include "common/ToBackend.h" - -namespace backend { -namespace null { - - using BindGroup = BindGroupBase; - using BindGroupLayout = BindGroupLayoutBase; - class Buffer; - using BufferView = BufferViewBase; - using CommandBuffer = CommandBufferBase; - using InputState = InputStateBase; - using Framebuffer = FramebufferBase; - using Pipeline = PipelineBase; - using PipelineLayout = PipelineLayoutBase; - class Queue; - using RenderPass = RenderPassBase; - using Sampler = SamplerBase; - using ShaderModule = ShaderModuleBase; - using Texture = TextureBase; - using TextureView = TextureViewBase; - - struct NullBackendTraits { - using BindGroupType = BindGroup; - using BindGroupLayoutType = BindGroupLayout; - using BufferType = Buffer; - using BufferViewType = BufferView; - using CommandBufferType = CommandBuffer; - using InputStateType = InputState; - using FramebufferType = Framebuffer; - using PipelineType = Pipeline; - using PipelineLayoutType = PipelineLayout; - using QueueType = Queue; - using RenderPassType = RenderPass; - using SamplerType = Sampler; - using ShaderModuleType = ShaderModule; - using TextureType = Texture; - using TextureViewType = TextureView; - }; - - template - auto ToBackend(T&& common) -> decltype(ToBackendBase(common)) { - return ToBackendBase(common); - } - - class Device : public DeviceBase { - public: - Device(); - ~Device(); - - BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override; - BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override; - BufferBase* CreateBuffer(BufferBuilder* builder) override; - BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override; - CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; - InputStateBase* CreateInputState(InputStateBuilder* builder) override; - FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override; - PipelineBase* CreatePipeline(PipelineBuilder* builder) override; - PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override; - QueueBase* CreateQueue(QueueBuilder* builder) override; - RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override; - SamplerBase* CreateSampler(SamplerBuilder* builder) override; - ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override; - TextureBase* CreateTexture(TextureBuilder* builder) override; - TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override; - - // NXT API - void Reference(); - void Release(); - }; - - class Buffer : public BufferBase { - public: - Buffer(BufferBuilder* builder); - ~Buffer(); - - private: - void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override; - }; - - class Queue : public QueueBase { - public: - Queue(QueueBuilder* builder); - ~Queue(); - - // NXT API - void Submit(uint32_t numCommands, CommandBuffer* const * commands); - }; - -} -} - -#endif // BACKEND_NULL_NULLBACKEND_H_ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_NULL_NULLBACKEND_H_ +#define BACKEND_NULL_NULLBACKEND_H_ + +#include "nxt/nxtcpp.h" + +#include "common/Buffer.h" +#include "common/BindGroup.h" +#include "common/BindGroupLayout.h" +#include "common/Device.h" +#include "common/CommandBuffer.h" +#include "common/DepthStencilState.h" +#include "common/InputState.h" +#include "common/Framebuffer.h" +#include "common/Pipeline.h" +#include "common/PipelineLayout.h" +#include "common/Queue.h" +#include "common/RenderPass.h" +#include "common/Sampler.h" +#include "common/ShaderModule.h" +#include "common/Texture.h" +#include "common/ToBackend.h" + +namespace backend { +namespace null { + + using BindGroup = BindGroupBase; + using BindGroupLayout = BindGroupLayoutBase; + class Buffer; + using BufferView = BufferViewBase; + using CommandBuffer = CommandBufferBase; + using DepthStencilState = DepthStencilStateBase; + using InputState = InputStateBase; + using Framebuffer = FramebufferBase; + using Pipeline = PipelineBase; + using PipelineLayout = PipelineLayoutBase; + class Queue; + using RenderPass = RenderPassBase; + using Sampler = SamplerBase; + using ShaderModule = ShaderModuleBase; + using Texture = TextureBase; + using TextureView = TextureViewBase; + + struct NullBackendTraits { + using BindGroupType = BindGroup; + using BindGroupLayoutType = BindGroupLayout; + using BufferType = Buffer; + using BufferViewType = BufferView; + using CommandBufferType = CommandBuffer; + using DepthStencilStateType = DepthStencilState; + using InputStateType = InputState; + using FramebufferType = Framebuffer; + using PipelineType = Pipeline; + using PipelineLayoutType = PipelineLayout; + using QueueType = Queue; + using RenderPassType = RenderPass; + using SamplerType = Sampler; + using ShaderModuleType = ShaderModule; + using TextureType = Texture; + using TextureViewType = TextureView; + }; + + template + auto ToBackend(T&& common) -> decltype(ToBackendBase(common)) { + return ToBackendBase(common); + } + + class Device : public DeviceBase { + public: + Device(); + ~Device(); + + BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override; + BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override; + BufferBase* CreateBuffer(BufferBuilder* builder) override; + BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override; + CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; + DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override; + InputStateBase* CreateInputState(InputStateBuilder* builder) override; + FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override; + PipelineBase* CreatePipeline(PipelineBuilder* builder) override; + PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override; + QueueBase* CreateQueue(QueueBuilder* builder) override; + RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override; + SamplerBase* CreateSampler(SamplerBuilder* builder) override; + ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override; + TextureBase* CreateTexture(TextureBuilder* builder) override; + TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override; + + // NXT API + void Reference(); + void Release(); + }; + + class Buffer : public BufferBase { + public: + Buffer(BufferBuilder* builder); + ~Buffer(); + + private: + void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override; + }; + + class Queue : public QueueBase { + public: + Queue(QueueBuilder* builder); + ~Queue(); + + // NXT API + void Submit(uint32_t numCommands, CommandBuffer* const * commands); + }; + +} +} + +#endif // BACKEND_NULL_NULLBACKEND_H_ diff --git a/src/backend/opengl/OpenGLBackend.cpp b/src/backend/opengl/OpenGLBackend.cpp index 2fc671af69..d3cf1444a1 100644 --- a/src/backend/opengl/OpenGLBackend.cpp +++ b/src/backend/opengl/OpenGLBackend.cpp @@ -1,199 +1,300 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "OpenGLBackend.h" - -#include "CommandBufferGL.h" -#include "PipelineGL.h" -#include "PipelineLayoutGL.h" -#include "ShaderModuleGL.h" -#include "SamplerGL.h" -#include "TextureGL.h" - -namespace backend { -namespace opengl { - nxtProcTable GetNonValidatingProcs(); - nxtProcTable GetValidatingProcs(); - - void HACKCLEAR() { - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } - - void Init(void* (*getProc)(const char*), nxtProcTable* procs, nxtDevice* device) { - *device = nullptr; - - gladLoadGLLoader(reinterpret_cast(getProc)); - - glEnable(GL_DEPTH_TEST); - HACKCLEAR(); - - *procs = GetValidatingProcs(); - *device = reinterpret_cast(new Device); - } - - // Device - - BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) { - return new BindGroup(this, builder); - } - BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) { - return new BindGroupLayout(this, builder); - } - BufferBase* Device::CreateBuffer(BufferBuilder* builder) { - return new Buffer(this, builder); - } - BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) { - return new BufferView(this, builder); - } - CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { - return new CommandBuffer(this, builder); - } - InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { - return new InputState(this, builder); - } - FramebufferBase* Device::CreateFramebuffer(FramebufferBuilder* builder) { - return new Framebuffer(this, builder); - } - PipelineBase* Device::CreatePipeline(PipelineBuilder* builder) { - return new Pipeline(this, builder); - } - PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { - return new PipelineLayout(this, builder); - } - QueueBase* Device::CreateQueue(QueueBuilder* builder) { - return new Queue(this, builder); - } - RenderPassBase* Device::CreateRenderPass(RenderPassBuilder* builder) { - return new RenderPass(this, builder); - } - SamplerBase* Device::CreateSampler(SamplerBuilder* builder) { - return new Sampler(this, builder); - } - ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) { - return new ShaderModule(this, builder); - } - TextureBase* Device::CreateTexture(TextureBuilder* builder) { - return new Texture(this, builder); - } - TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) { - return new TextureView(this, builder); - } - - void Device::Reference() { - } - - void Device::Release() { - } - - // Bind Group - - BindGroup::BindGroup(Device* device, BindGroupBuilder* builder) - : BindGroupBase(builder), device(device) { - } - - // Bind Group Layout - - BindGroupLayout::BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder) - : BindGroupLayoutBase(builder), device(device) { - } - - // Buffer - - Buffer::Buffer(Device* device, BufferBuilder* builder) - : BufferBase(builder), device(device) { - glGenBuffers(1, &buffer); - glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferData(GL_ARRAY_BUFFER, GetSize(), nullptr, GL_STATIC_DRAW); - } - - GLuint Buffer::GetHandle() const { - return buffer; - } - - void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) { - glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferSubData(GL_ARRAY_BUFFER, start * sizeof(uint32_t), count * sizeof(uint32_t), data); - } - - // BufferView - - BufferView::BufferView(Device* device, BufferViewBuilder* builder) - : BufferViewBase(builder), device(device) { - } - - // InputState - - InputState::InputState(Device* device, InputStateBuilder* builder) - : InputStateBase(builder), device(device) { - glGenVertexArrays(1, &vertexArrayObject); - glBindVertexArray(vertexArrayObject); - auto& attributesSetMask = GetAttributesSetMask(); - for (uint32_t location = 0; location < attributesSetMask.size(); ++location) { - if (!attributesSetMask[location]) { - continue; - } - auto attribute = GetAttribute(location); - glEnableVertexAttribArray(location); - - auto input = GetInput(attribute.bindingSlot); - if (input.stride == 0) { - // Emulate a stride of zero (constant vertex attribute) by - // setting the attribute instance divisor to a huge number. - glVertexAttribDivisor(location, 0xffffffff); - } else { - switch (input.stepMode) { - case nxt::InputStepMode::Vertex: - break; - case nxt::InputStepMode::Instance: - glVertexAttribDivisor(location, 1); - break; - default: - ASSERT(false); - break; - } - } - } - } - - GLuint InputState::GetVAO() { - return vertexArrayObject; - } - - // Framebuffer - - Framebuffer::Framebuffer(Device* device, FramebufferBuilder* builder) - : FramebufferBase(builder), device(device) { - } - - // Queue - - Queue::Queue(Device* device, QueueBuilder* builder) - : QueueBase(builder), device(device) { - } - - void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) { - for (uint32_t i = 0; i < numCommands; ++i) { - commands[i]->Execute(); - } - } - - // RenderPass - - RenderPass::RenderPass(Device* device, RenderPassBuilder* builder) - : RenderPassBase(builder), device(device) { - } - -} -} +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "OpenGLBackend.h" + +#include "CommandBufferGL.h" +#include "PipelineGL.h" +#include "PipelineLayoutGL.h" +#include "ShaderModuleGL.h" +#include "SamplerGL.h" +#include "TextureGL.h" + +namespace backend { +namespace opengl { + nxtProcTable GetNonValidatingProcs(); + nxtProcTable GetValidatingProcs(); + + void HACKCLEAR() { + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + } + + void Init(void* (*getProc)(const char*), nxtProcTable* procs, nxtDevice* device) { + *device = nullptr; + + gladLoadGLLoader(reinterpret_cast(getProc)); + + glEnable(GL_DEPTH_TEST); + HACKCLEAR(); + + *procs = GetValidatingProcs(); + *device = reinterpret_cast(new Device); + } + + static GLuint OpenGLCompareFunction(nxt::CompareFunction compareFunction) { + switch (compareFunction) { + case nxt::CompareFunction::Never: + return GL_NEVER; + case nxt::CompareFunction::Less: + return GL_LESS; + case nxt::CompareFunction::LessEqual: + return GL_LEQUAL; + case nxt::CompareFunction::Greater: + return GL_GREATER; + case nxt::CompareFunction::GreaterEqual: + return GL_GEQUAL; + case nxt::CompareFunction::NotEqual: + return GL_NOTEQUAL; + case nxt::CompareFunction::Equal: + return GL_EQUAL; + case nxt::CompareFunction::Always: + return GL_ALWAYS; + default: + ASSERT(false); + } + } + + static GLuint OpenGLStencilOperation(nxt::StencilOperation stencilOperation) { + switch (stencilOperation) { + case nxt::StencilOperation::Keep: + return GL_KEEP; + case nxt::StencilOperation::Zero: + return GL_ZERO; + case nxt::StencilOperation::Replace: + return GL_REPLACE; + case nxt::StencilOperation::Invert: + return GL_INVERT; + case nxt::StencilOperation::IncrementClamp: + return GL_INCR; + case nxt::StencilOperation::DecrementClamp: + return GL_DECR; + case nxt::StencilOperation::IncrementWrap: + return GL_INCR_WRAP; + case nxt::StencilOperation::DecrementWrap: + return GL_DECR_WRAP; + default: + ASSERT(false); + } + } + + // Device + + BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) { + return new BindGroup(this, builder); + } + BindGroupLayoutBase* Device::CreateBindGroupLayout(BindGroupLayoutBuilder* builder) { + return new BindGroupLayout(this, builder); + } + BufferBase* Device::CreateBuffer(BufferBuilder* builder) { + return new Buffer(this, builder); + } + BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) { + return new BufferView(this, builder); + } + CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { + return new CommandBuffer(this, builder); + } + DepthStencilStateBase* Device::CreateDepthStencilState(DepthStencilStateBuilder* builder) { + return new DepthStencilState(this, builder); + } + InputStateBase* Device::CreateInputState(InputStateBuilder* builder) { + return new InputState(this, builder); + } + FramebufferBase* Device::CreateFramebuffer(FramebufferBuilder* builder) { + return new Framebuffer(this, builder); + } + PipelineBase* Device::CreatePipeline(PipelineBuilder* builder) { + return new Pipeline(this, builder); + } + PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) { + return new PipelineLayout(this, builder); + } + QueueBase* Device::CreateQueue(QueueBuilder* builder) { + return new Queue(this, builder); + } + RenderPassBase* Device::CreateRenderPass(RenderPassBuilder* builder) { + return new RenderPass(this, builder); + } + SamplerBase* Device::CreateSampler(SamplerBuilder* builder) { + return new Sampler(this, builder); + } + ShaderModuleBase* Device::CreateShaderModule(ShaderModuleBuilder* builder) { + return new ShaderModule(this, builder); + } + TextureBase* Device::CreateTexture(TextureBuilder* builder) { + return new Texture(this, builder); + } + TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) { + return new TextureView(this, builder); + } + + void Device::Reference() { + } + + void Device::Release() { + } + + // Bind Group + + BindGroup::BindGroup(Device* device, BindGroupBuilder* builder) + : BindGroupBase(builder), device(device) { + } + + // Bind Group Layout + + BindGroupLayout::BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder) + : BindGroupLayoutBase(builder), device(device) { + } + + // Buffer + + Buffer::Buffer(Device* device, BufferBuilder* builder) + : BufferBase(builder), device(device) { + glGenBuffers(1, &buffer); + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, GetSize(), nullptr, GL_STATIC_DRAW); + } + + GLuint Buffer::GetHandle() const { + return buffer; + } + + void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) { + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferSubData(GL_ARRAY_BUFFER, start * sizeof(uint32_t), count * sizeof(uint32_t), data); + } + + // BufferView + + BufferView::BufferView(Device* device, BufferViewBuilder* builder) + : BufferViewBase(builder), device(device) { + } + + DepthStencilState::DepthStencilState(Device* device, DepthStencilStateBuilder* builder) + : DepthStencilStateBase(builder), device(device) { + + } + + void DepthStencilState::Apply() { + if (DepthIsEnabled()) { + glEnable(GL_DEPTH_TEST); + auto& depth = GetDepth(); + glDepthFunc(OpenGLCompareFunction(depth.compareFunction)); + switch (depth.depthWriteMode) { + case nxt::DepthWriteMode::Disabled: + glDepthMask(GL_FALSE); + break; + case nxt::DepthWriteMode::Enabled: + glDepthMask(GL_TRUE); + break; + default: + ASSERT(false); + break; + } + } + else { + glDisable(GL_DEPTH_TEST); + } + + static const GLuint GL_FACES[2] = { GL_BACK, GL_FRONT }; + static const nxt::Face NXT_FACES[2] = { nxt::Face::Back, nxt::Face::Front }; + if (StencilIsEnabled()) { + glEnable(GL_STENCIL_TEST); + for (uint32_t i = 0; i < 2; ++i) { + auto& stencil = GetStencil(NXT_FACES[i]); + glStencilFuncSeparate(GL_FACES[i], + OpenGLCompareFunction(stencil.compareFunction), + stencil.reference, + stencil.readMask + ); + glStencilOpSeparate(GL_FACES[i], + OpenGLStencilOperation(stencil.stencilFail), + OpenGLStencilOperation(stencil.depthFail), + OpenGLStencilOperation(stencil.stencilPass) + ); + glStencilMaskSeparate(GL_FACES[i], stencil.writeMask); + } + } + else { + glDisable(GL_STENCIL_TEST); + } + } + + // InputState + + InputState::InputState(Device* device, InputStateBuilder* builder) + : InputStateBase(builder), device(device) { + glGenVertexArrays(1, &vertexArrayObject); + glBindVertexArray(vertexArrayObject); + auto& attributesSetMask = GetAttributesSetMask(); + for (uint32_t location = 0; location < attributesSetMask.size(); ++location) { + if (!attributesSetMask[location]) { + continue; + } + auto attribute = GetAttribute(location); + glEnableVertexAttribArray(location); + + auto input = GetInput(attribute.bindingSlot); + if (input.stride == 0) { + // Emulate a stride of zero (constant vertex attribute) by + // setting the attribute instance divisor to a huge number. + glVertexAttribDivisor(location, 0xffffffff); + } else { + switch (input.stepMode) { + case nxt::InputStepMode::Vertex: + break; + case nxt::InputStepMode::Instance: + glVertexAttribDivisor(location, 1); + break; + default: + ASSERT(false); + break; + } + } + } + } + + GLuint InputState::GetVAO() { + return vertexArrayObject; + } + + // Framebuffer + + Framebuffer::Framebuffer(Device* device, FramebufferBuilder* builder) + : FramebufferBase(builder), device(device) { + } + + // Queue + + Queue::Queue(Device* device, QueueBuilder* builder) + : QueueBase(builder), device(device) { + } + + void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) { + for (uint32_t i = 0; i < numCommands; ++i) { + commands[i]->Execute(); + } + } + + // RenderPass + + RenderPass::RenderPass(Device* device, RenderPassBuilder* builder) + : RenderPassBase(builder), device(device) { + } + +} +} diff --git a/src/backend/opengl/OpenGLBackend.h b/src/backend/opengl/OpenGLBackend.h index c7f5d56838..832aad38d5 100644 --- a/src/backend/opengl/OpenGLBackend.h +++ b/src/backend/opengl/OpenGLBackend.h @@ -1,175 +1,188 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef BACKEND_OPENGL_OPENGLBACKEND_H_ -#define BACKEND_OPENGL_OPENGLBACKEND_H_ - -#include "nxt/nxtcpp.h" - -#include "common/Buffer.h" -#include "common/BindGroup.h" -#include "common/BindGroupLayout.h" -#include "common/Device.h" -#include "common/Framebuffer.h" -#include "common/InputState.h" -#include "common/Queue.h" -#include "common/RenderPass.h" -#include "common/ToBackend.h" - -#include "glad/glad.h" - -namespace backend { -namespace opengl { - - class BindGroup; - class BindGroupLayout; - class Buffer; - class BufferView; - class CommandBuffer; - class InputState; - class Pipeline; - class PipelineLayout; - class Queue; - class Sampler; - class ShaderModule; - class Texture; - class TextureView; - class Framebuffer; - class RenderPass; - - struct OpenGLBackendTraits { - using BindGroupType = BindGroup; - using BindGroupLayoutType = BindGroupLayout; - using BufferType = Buffer; - using BufferViewType = BufferView; - using CommandBufferType = CommandBuffer; - using InputStateType = InputState; - using PipelineType = Pipeline; - using PipelineLayoutType = PipelineLayout; - using QueueType = Queue; - using SamplerType = Sampler; - using ShaderModuleType = ShaderModule; - using TextureType = Texture; - using TextureViewType = TextureView; - using FramebufferType = Framebuffer; - using RenderPassType = RenderPass; - }; - - template - auto ToBackend(T&& common) -> decltype(ToBackendBase(common)) { - return ToBackendBase(common); - } - - // Definition of backend types - class Device : public DeviceBase { - public: - BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override; - BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override; - BufferBase* CreateBuffer(BufferBuilder* builder) override; - BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override; - CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; - InputStateBase* CreateInputState(InputStateBuilder* builder) override; - FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override; - PipelineBase* CreatePipeline(PipelineBuilder* builder) override; - PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override; - QueueBase* CreateQueue(QueueBuilder* builder) override; - RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override; - SamplerBase* CreateSampler(SamplerBuilder* builder) override; - ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override; - TextureBase* CreateTexture(TextureBuilder* builder) override; - TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override; - - // NXT API - void Reference(); - void Release(); - }; - - class BindGroup : public BindGroupBase { - public: - BindGroup(Device* device, BindGroupBuilder* builder); - - private: - Device* device; - }; - - class BindGroupLayout : public BindGroupLayoutBase { - public: - BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder); - - private: - Device* device; - }; - - class Buffer : public BufferBase { - public: - Buffer(Device* device, BufferBuilder* builder); - - GLuint GetHandle() const; - - private: - void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override; - - Device* device; - GLuint buffer = 0; - }; - - class BufferView : public BufferViewBase { - public: - BufferView(Device* device, BufferViewBuilder* builder); - - private: - Device* device; - }; - - class Framebuffer : public FramebufferBase { - public: - Framebuffer(Device* device, FramebufferBuilder* builder); - - private: - Device* device; - }; - - class InputState : public InputStateBase { - public: - InputState(Device* device, InputStateBuilder* builder); - GLuint GetVAO(); - - private: - Device* device; - GLuint vertexArrayObject; - }; - - class Queue : public QueueBase { - public: - Queue(Device* device, QueueBuilder* builder); - - // NXT API - void Submit(uint32_t numCommands, CommandBuffer* const * commands); - - private: - Device* device; - }; - - class RenderPass : public RenderPassBase { - public: - RenderPass(Device* device, RenderPassBuilder* builder); - - private: - Device* device; - }; - -} -} - -#endif // BACKEND_OPENGL_OPENGLBACKEND_H_ +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_OPENGL_OPENGLBACKEND_H_ +#define BACKEND_OPENGL_OPENGLBACKEND_H_ + +#include "nxt/nxtcpp.h" + +#include "common/Buffer.h" +#include "common/BindGroup.h" +#include "common/BindGroupLayout.h" +#include "common/Device.h" +#include "common/DepthStencilState.h" +#include "common/Framebuffer.h" +#include "common/InputState.h" +#include "common/Queue.h" +#include "common/RenderPass.h" +#include "common/ToBackend.h" + +#include "glad/glad.h" + +namespace backend { +namespace opengl { + + class BindGroup; + class BindGroupLayout; + class Buffer; + class BufferView; + class CommandBuffer; + class DepthStencilState; + class InputState; + class Pipeline; + class PipelineLayout; + class Queue; + class Sampler; + class ShaderModule; + class Texture; + class TextureView; + class Framebuffer; + class RenderPass; + + struct OpenGLBackendTraits { + using BindGroupType = BindGroup; + using BindGroupLayoutType = BindGroupLayout; + using BufferType = Buffer; + using BufferViewType = BufferView; + using CommandBufferType = CommandBuffer; + using DepthStencilStateType = DepthStencilState; + using InputStateType = InputState; + using PipelineType = Pipeline; + using PipelineLayoutType = PipelineLayout; + using QueueType = Queue; + using SamplerType = Sampler; + using ShaderModuleType = ShaderModule; + using TextureType = Texture; + using TextureViewType = TextureView; + using FramebufferType = Framebuffer; + using RenderPassType = RenderPass; + }; + + template + auto ToBackend(T&& common) -> decltype(ToBackendBase(common)) { + return ToBackendBase(common); + } + + // Definition of backend types + class Device : public DeviceBase { + public: + BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override; + BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override; + BufferBase* CreateBuffer(BufferBuilder* builder) override; + BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override; + CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; + DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override; + InputStateBase* CreateInputState(InputStateBuilder* builder) override; + FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override; + PipelineBase* CreatePipeline(PipelineBuilder* builder) override; + PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override; + QueueBase* CreateQueue(QueueBuilder* builder) override; + RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override; + SamplerBase* CreateSampler(SamplerBuilder* builder) override; + ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override; + TextureBase* CreateTexture(TextureBuilder* builder) override; + TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override; + + // NXT API + void Reference(); + void Release(); + }; + + class BindGroup : public BindGroupBase { + public: + BindGroup(Device* device, BindGroupBuilder* builder); + + private: + Device* device; + }; + + class BindGroupLayout : public BindGroupLayoutBase { + public: + BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder); + + private: + Device* device; + }; + + class Buffer : public BufferBase { + public: + Buffer(Device* device, BufferBuilder* builder); + + GLuint GetHandle() const; + + private: + void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override; + + Device* device; + GLuint buffer = 0; + }; + + class BufferView : public BufferViewBase { + public: + BufferView(Device* device, BufferViewBuilder* builder); + + private: + Device* device; + }; + + class DepthStencilState : public DepthStencilStateBase { + public: + DepthStencilState(Device* device, DepthStencilStateBuilder* builder); + void Apply(); + + private: + Device* device; + }; + + class Framebuffer : public FramebufferBase { + public: + Framebuffer(Device* device, FramebufferBuilder* builder); + + private: + Device* device; + }; + + class InputState : public InputStateBase { + public: + InputState(Device* device, InputStateBuilder* builder); + GLuint GetVAO(); + + private: + Device* device; + GLuint vertexArrayObject; + }; + + class Queue : public QueueBase { + public: + Queue(Device* device, QueueBuilder* builder); + + // NXT API + void Submit(uint32_t numCommands, CommandBuffer* const * commands); + + private: + Device* device; + }; + + class RenderPass : public RenderPassBase { + public: + RenderPass(Device* device, RenderPassBuilder* builder); + + private: + Device* device; + }; + +} +} + +#endif // BACKEND_OPENGL_OPENGLBACKEND_H_ diff --git a/src/backend/opengl/PipelineGL.cpp b/src/backend/opengl/PipelineGL.cpp index 50b9f082ef..dcb40a579c 100644 --- a/src/backend/opengl/PipelineGL.cpp +++ b/src/backend/opengl/PipelineGL.cpp @@ -1,213 +1,215 @@ -// Copyright 2017 The NXT Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "PipelineGL.h" - -#include "OpenGLBackend.h" -#include "PipelineLayoutGL.h" -#include "ShaderModuleGL.h" - -#include -#include - -namespace backend { -namespace opengl { - - namespace { - - GLenum GLShaderType(nxt::ShaderStage stage) { - switch (stage) { - case nxt::ShaderStage::Vertex: - return GL_VERTEX_SHADER; - case nxt::ShaderStage::Fragment: - return GL_FRAGMENT_SHADER; - case nxt::ShaderStage::Compute: - return GL_COMPUTE_SHADER; - } - } - - } - - Pipeline::Pipeline(Device* device, PipelineBuilder* builder) : PipelineBase(builder), device(device) { - auto CreateShader = [](GLenum type, const char* source) -> GLuint { - GLuint shader = glCreateShader(type); - glShaderSource(shader, 1, &source, nullptr); - glCompileShader(shader); - - GLint compileStatus = GL_FALSE; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); - if (compileStatus == GL_FALSE) { - GLint infoLogLength = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); - - if (infoLogLength > 1) { - std::vector buffer(infoLogLength); - glGetShaderInfoLog(shader, infoLogLength, nullptr, &buffer[0]); - std::cout << source << std::endl; - std::cout << "Program compilation failed:\n"; - std::cout << buffer.data() << std::endl; - } - } - return shader; - }; - - auto FillPushConstants = [](const ShaderModule* module, GLPushConstantInfo* info, GLuint program) { - const auto& moduleInfo = module->GetPushConstants(); - for (uint32_t i = 0; i < moduleInfo.names.size(); i++) { - (*info)[i] = -1; - - unsigned int size = moduleInfo.sizes[i]; - if (size == 0) { - continue; - } - - GLint location = glGetUniformLocation(program, moduleInfo.names[i].c_str()); - if (location == -1) { - continue; - } - - for (uint32_t offset = 0; offset < size; offset++) { - (*info)[i + offset] = location + offset; - } - i += size - 1; - } - }; - - program = glCreateProgram(); - - for (auto stage : IterateStages(GetStageMask())) { - const ShaderModule* module = ToBackend(builder->GetStageInfo(stage).module.Get()); - - GLuint shader = CreateShader(GLShaderType(stage), module->GetSource()); - glAttachShader(program, shader); - } - - glLinkProgram(program); - - GLint linkStatus = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - if (linkStatus == GL_FALSE) { - GLint infoLogLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); - - if (infoLogLength > 1) { - std::vector buffer(infoLogLength); - glGetProgramInfoLog(program, infoLogLength, nullptr, &buffer[0]); - std::cout << "Program link failed:\n"; - std::cout << buffer.data() << std::endl; - } - } - - for (auto stage : IterateStages(GetStageMask())) { - const ShaderModule* module = ToBackend(builder->GetStageInfo(stage).module.Get()); - FillPushConstants(module, &glPushConstants[stage], program); - } - - glUseProgram(program); - - // The uniforms are part of the program state so we can pre-bind buffer units, texture units etc. - const auto& layout = ToBackend(GetLayout()); - const auto& indices = layout->GetBindingIndexInfo(); - - for (uint32_t group = 0; group < kMaxBindGroups; ++group) { - const auto& groupInfo = layout->GetBindGroupLayout(group)->GetBindingInfo(); - - for (uint32_t binding = 0; binding < kMaxBindingsPerGroup; ++binding) { - if (!groupInfo.mask[binding]) { - continue; - } - - std::string name = GetBindingName(group, binding); - switch (groupInfo.types[binding]) { - case nxt::BindingType::UniformBuffer: - { - GLint location = glGetUniformBlockIndex(program, name.c_str()); - glUniformBlockBinding(program, location, indices[group][binding]); - } - break; - - case nxt::BindingType::StorageBuffer: - { - GLuint location = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, name.c_str()); - glShaderStorageBlockBinding(program, location, indices[group][binding]); - } - break; - - case nxt::BindingType::Sampler: - case nxt::BindingType::SampledTexture: - // These binding types are handled in the separate sampler and texture emulation - break; - - } - } - } - - // Compute links between stages for combined samplers, then bind them to texture units - { - std::set combinedSamplersSet; - for (auto stage : IterateStages(GetStageMask())) { - const auto& module = ToBackend(builder->GetStageInfo(stage).module); - - for (const auto& combined : module->GetCombinedSamplerInfo()) { - combinedSamplersSet.insert(combined); - } - } - - unitsForSamplers.resize(layout->GetNumSamplers()); - unitsForTextures.resize(layout->GetNumSampledTextures()); - - GLuint textureUnit = layout->GetTextureUnitsUsed(); - for (const auto& combined : combinedSamplersSet) { - std::string name = combined.GetName(); - GLint location = glGetUniformLocation(program, name.c_str()); - glUniform1i(location, textureUnit); - - GLuint samplerIndex = indices[combined.samplerLocation.group][combined.samplerLocation.binding]; - unitsForSamplers[samplerIndex].push_back(textureUnit); - - GLuint textureIndex = indices[combined.textureLocation.group][combined.textureLocation.binding]; - unitsForTextures[textureIndex].push_back(textureUnit); - - textureUnit ++; - } - } - } - - const Pipeline::GLPushConstantInfo& Pipeline::GetGLPushConstants(nxt::ShaderStage stage) const { - return glPushConstants[stage]; - } - - const std::vector& Pipeline::GetTextureUnitsForSampler(GLuint index) const { - ASSERT(index >= 0 && index < unitsForSamplers.size()); - return unitsForSamplers[index]; - } - - const std::vector& Pipeline::GetTextureUnitsForTexture(GLuint index) const { - ASSERT(index >= 0 && index < unitsForSamplers.size()); - return unitsForTextures[index]; - } - - GLuint Pipeline::GetProgramHandle() const { - return program; - } - - void Pipeline::ApplyNow() { - glUseProgram(program); - - auto inputState = ToBackend(GetInputState()); - glBindVertexArray(inputState->GetVAO()); - } - -} -} +// Copyright 2017 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "PipelineGL.h" + +#include "OpenGLBackend.h" +#include "PipelineLayoutGL.h" +#include "ShaderModuleGL.h" + +#include +#include + +namespace backend { +namespace opengl { + + namespace { + + GLenum GLShaderType(nxt::ShaderStage stage) { + switch (stage) { + case nxt::ShaderStage::Vertex: + return GL_VERTEX_SHADER; + case nxt::ShaderStage::Fragment: + return GL_FRAGMENT_SHADER; + case nxt::ShaderStage::Compute: + return GL_COMPUTE_SHADER; + } + } + + } + + Pipeline::Pipeline(Device* device, PipelineBuilder* builder) : PipelineBase(builder), device(device) { + auto CreateShader = [](GLenum type, const char* source) -> GLuint { + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, &source, nullptr); + glCompileShader(shader); + + GLint compileStatus = GL_FALSE; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); + if (compileStatus == GL_FALSE) { + GLint infoLogLength = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); + + if (infoLogLength > 1) { + std::vector buffer(infoLogLength); + glGetShaderInfoLog(shader, infoLogLength, nullptr, &buffer[0]); + std::cout << source << std::endl; + std::cout << "Program compilation failed:\n"; + std::cout << buffer.data() << std::endl; + } + } + return shader; + }; + + auto FillPushConstants = [](const ShaderModule* module, GLPushConstantInfo* info, GLuint program) { + const auto& moduleInfo = module->GetPushConstants(); + for (uint32_t i = 0; i < moduleInfo.names.size(); i++) { + (*info)[i] = -1; + + unsigned int size = moduleInfo.sizes[i]; + if (size == 0) { + continue; + } + + GLint location = glGetUniformLocation(program, moduleInfo.names[i].c_str()); + if (location == -1) { + continue; + } + + for (uint32_t offset = 0; offset < size; offset++) { + (*info)[i + offset] = location + offset; + } + i += size - 1; + } + }; + + program = glCreateProgram(); + + for (auto stage : IterateStages(GetStageMask())) { + const ShaderModule* module = ToBackend(builder->GetStageInfo(stage).module.Get()); + + GLuint shader = CreateShader(GLShaderType(stage), module->GetSource()); + glAttachShader(program, shader); + } + + glLinkProgram(program); + + GLint linkStatus = GL_FALSE; + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); + if (linkStatus == GL_FALSE) { + GLint infoLogLength = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); + + if (infoLogLength > 1) { + std::vector buffer(infoLogLength); + glGetProgramInfoLog(program, infoLogLength, nullptr, &buffer[0]); + std::cout << "Program link failed:\n"; + std::cout << buffer.data() << std::endl; + } + } + + for (auto stage : IterateStages(GetStageMask())) { + const ShaderModule* module = ToBackend(builder->GetStageInfo(stage).module.Get()); + FillPushConstants(module, &glPushConstants[stage], program); + } + + glUseProgram(program); + + // The uniforms are part of the program state so we can pre-bind buffer units, texture units etc. + const auto& layout = ToBackend(GetLayout()); + const auto& indices = layout->GetBindingIndexInfo(); + + for (uint32_t group = 0; group < kMaxBindGroups; ++group) { + const auto& groupInfo = layout->GetBindGroupLayout(group)->GetBindingInfo(); + + for (uint32_t binding = 0; binding < kMaxBindingsPerGroup; ++binding) { + if (!groupInfo.mask[binding]) { + continue; + } + + std::string name = GetBindingName(group, binding); + switch (groupInfo.types[binding]) { + case nxt::BindingType::UniformBuffer: + { + GLint location = glGetUniformBlockIndex(program, name.c_str()); + glUniformBlockBinding(program, location, indices[group][binding]); + } + break; + + case nxt::BindingType::StorageBuffer: + { + GLuint location = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, name.c_str()); + glShaderStorageBlockBinding(program, location, indices[group][binding]); + } + break; + + case nxt::BindingType::Sampler: + case nxt::BindingType::SampledTexture: + // These binding types are handled in the separate sampler and texture emulation + break; + + } + } + } + + // Compute links between stages for combined samplers, then bind them to texture units + { + std::set combinedSamplersSet; + for (auto stage : IterateStages(GetStageMask())) { + const auto& module = ToBackend(builder->GetStageInfo(stage).module); + + for (const auto& combined : module->GetCombinedSamplerInfo()) { + combinedSamplersSet.insert(combined); + } + } + + unitsForSamplers.resize(layout->GetNumSamplers()); + unitsForTextures.resize(layout->GetNumSampledTextures()); + + GLuint textureUnit = layout->GetTextureUnitsUsed(); + for (const auto& combined : combinedSamplersSet) { + std::string name = combined.GetName(); + GLint location = glGetUniformLocation(program, name.c_str()); + glUniform1i(location, textureUnit); + + GLuint samplerIndex = indices[combined.samplerLocation.group][combined.samplerLocation.binding]; + unitsForSamplers[samplerIndex].push_back(textureUnit); + + GLuint textureIndex = indices[combined.textureLocation.group][combined.textureLocation.binding]; + unitsForTextures[textureIndex].push_back(textureUnit); + + textureUnit ++; + } + } + } + + const Pipeline::GLPushConstantInfo& Pipeline::GetGLPushConstants(nxt::ShaderStage stage) const { + return glPushConstants[stage]; + } + + const std::vector& Pipeline::GetTextureUnitsForSampler(GLuint index) const { + ASSERT(index >= 0 && index < unitsForSamplers.size()); + return unitsForSamplers[index]; + } + + const std::vector& Pipeline::GetTextureUnitsForTexture(GLuint index) const { + ASSERT(index >= 0 && index < unitsForSamplers.size()); + return unitsForTextures[index]; + } + + GLuint Pipeline::GetProgramHandle() const { + return program; + } + + void Pipeline::ApplyNow() { + glUseProgram(program); + + auto inputState = ToBackend(GetInputState()); + glBindVertexArray(inputState->GetVAO()); + auto depthStencilState = ToBackend(GetDepthStencilState()); + depthStencilState->Apply(); + } + +} +}