diff --git a/src/renderer_webgpu.cpp~RF2c45ef4.TMP b/src/renderer_webgpu.cpp~RF2c45ef4.TMP deleted file mode 100644 index b06e5f22e..000000000 --- a/src/renderer_webgpu.cpp~RF2c45ef4.TMP +++ /dev/null @@ -1,4775 +0,0 @@ -/* - * Copyright 2011-2019 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause - */ - -#include "bgfx_p.h" - -//#define DAWN_ENABLE_BACKEND_D3D12 -#define DAWN_ENABLE_BACKEND_VULKAN - -#if BGFX_CONFIG_RENDERER_WEBGPU -#include "renderer_webgpu.h" -#include "renderer.h" -#include "debug_renderdoc.h" - -#ifdef DAWN_ENABLE_BACKEND_VULKAN -#include "renderer_vk.h" -#endif - -#include -#include - -#if !BX_PLATFORM_EMSCRIPTEN -#ifdef DAWN_ENABLE_BACKEND_D3D12 -#include -#endif -#ifdef DAWN_ENABLE_BACKEND_VULKAN -#include -#endif -#include -#include -#include -#else -#include -#include -#endif - -#define UNIFORM_BUFFER_SIZE (8*1024*1024) - -#define INDIRECT 1 - - -#define VARIABLE_BIND_GROUPS 0 - -namespace bgfx { namespace webgpu -{ - // TODO (hugoam) cleanup - template - T defaultDescriptor() { return T(); } - - template <> wgpu::BlendDescriptor defaultDescriptor() { return { wgpu::BlendOperation::Add, wgpu::BlendFactor::One, wgpu::BlendFactor::Zero }; } - template <> wgpu::ColorStateDescriptor defaultDescriptor() { return { nullptr, wgpu::TextureFormat::RGBA8Unorm, defaultDescriptor(), defaultDescriptor(), wgpu::ColorWriteMask::All }; } - template <> wgpu::StencilStateFaceDescriptor defaultDescriptor() { return { wgpu::CompareFunction::Always, wgpu::StencilOperation::Keep, wgpu::StencilOperation::Keep, wgpu::StencilOperation::Keep }; } - template <> wgpu::VertexStateDescriptor defaultDescriptor() { return { nullptr, wgpu::IndexFormat::Uint32, 0, nullptr }; } - template <> wgpu::VertexBufferLayoutDescriptor defaultDescriptor() { return { 0, wgpu::InputStepMode::Vertex, 0, nullptr }; } - template <> wgpu::VertexAttributeDescriptor defaultDescriptor() { return { wgpu::VertexFormat::Float, 0, 0 }; } - template <> wgpu::RasterizationStateDescriptor defaultDescriptor() { return { nullptr, wgpu::FrontFace::CCW, wgpu::CullMode::None, 0, 0.f, 0.f }; } - template <> wgpu::ProgrammableStageDescriptor defaultDescriptor() { return { nullptr, {}, "main" }; } - template <> wgpu::DepthStencilStateDescriptor defaultDescriptor() { return { nullptr, wgpu::TextureFormat::Depth24PlusStencil8, false, wgpu::CompareFunction::Always, defaultDescriptor(), defaultDescriptor(), 0xff, 0xff }; } - template <> wgpu::PipelineLayoutDescriptor defaultDescriptor() { return { nullptr, "", 0, nullptr }; } - template <> wgpu::TextureViewDescriptor defaultDescriptor() { return {}; } - - template <> wgpu::RenderPassColorAttachmentDescriptor defaultDescriptor() { return { {}, {}, wgpu::LoadOp::Clear, wgpu::StoreOp::Store, { 0.0f, 0.0f, 0.0f, 0.0f } }; } - template <> wgpu::RenderPassDepthStencilAttachmentDescriptor defaultDescriptor() { return { {}, wgpu::LoadOp::Clear, wgpu::StoreOp::Store, 1.0f, wgpu::LoadOp::Clear, wgpu::StoreOp::Store, 0 }; } - - RenderPassDescriptor::RenderPassDescriptor() - { - depthStencilAttachment = defaultDescriptor(); - - for(uint32_t i = 0; i < kMaxColorAttachments; ++i) - { - colorAttachments[i] = defaultDescriptor(); - } - - desc = defaultDescriptor(); - //desc.colorAttachmentCount = colorAttachmentCount; - desc.colorAttachments = colorAttachments; - desc.colorAttachmentCount = 1; // TODO (hugoam) set it properly everywhere - } - - VertexStateDescriptor::VertexStateDescriptor() - { - for(uint32_t i = 0; i < kMaxVertexInputs; ++i) - { - vertexBuffers[i] = defaultDescriptor(); - } - - for (uint32_t i = 0; i < kMaxVertexAttributes; ++i) - { - attributes[i] = defaultDescriptor(); - } - - vertexBuffers[0].attributes = &attributes[0]; - //vertexBuffers[0].attributeCount = numAttributes; - - desc = defaultDescriptor(); - - desc.vertexBuffers = vertexBuffers; - //desc.vertexBufferCount = numVertexBuffers; - } - - RenderPipelineDescriptor::RenderPipelineDescriptor() - { - //vertexStage = defaultDescriptor(); - fragmentStage = defaultDescriptor(); - rasterizationState = defaultDescriptor(); - depthStencilState = defaultDescriptor(); - - for(uint32_t i = 0; i < kMaxColorAttachments; ++i) - { - colorStates[i] = defaultDescriptor(); - } - - desc = defaultDescriptor(); - - desc.primitiveTopology = wgpu::PrimitiveTopology::TriangleList; - desc.sampleCount = 1; - desc.colorStateCount = 1; - - //wgpu::VertexStateDescriptor inputState = inputState.descriptor(); - - desc.vertexStage = defaultDescriptor(); - desc.fragmentStage = &fragmentStage; - //desc.vertexState = &inputState; - desc.rasterizationState = &rasterizationState; - desc.depthStencilState = nullptr; - desc.colorStates = colorStates; - } - // TODO (hugoam) cleanup (end) - - static char s_viewName[BGFX_CONFIG_MAX_VIEWS][BGFX_CONFIG_MAX_VIEW_NAME]; - - inline void setViewType(ViewId _view, const bx::StringView _str) - { - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION || BGFX_CONFIG_PROFILER) ) - { - bx::memCopy(&s_viewName[_view][3], _str.getPtr(), _str.getLength() ); - } - } - - struct PrimInfo - { - wgpu::PrimitiveTopology m_type; - uint32_t m_min; - uint32_t m_div; - uint32_t m_sub; - }; - - static const PrimInfo s_primInfo[] = - { - { wgpu::PrimitiveTopology::TriangleList, 3, 3, 0 }, - { wgpu::PrimitiveTopology::TriangleStrip, 3, 1, 2 }, - { wgpu::PrimitiveTopology::LineList, 2, 2, 0 }, - { wgpu::PrimitiveTopology::LineStrip, 2, 1, 1 }, - { wgpu::PrimitiveTopology::PointList, 1, 1, 0 }, - }; - BX_STATIC_ASSERT(Topology::Count == BX_COUNTOF(s_primInfo) ); - - static const wgpu::VertexFormat s_attribType[][4][2] = - { - { // Uint8 - { wgpu::VertexFormat::UChar2, wgpu::VertexFormat::UChar2Norm }, - { wgpu::VertexFormat::UChar2, wgpu::VertexFormat::UChar2Norm }, - { wgpu::VertexFormat::UChar4, wgpu::VertexFormat::UChar4Norm }, - { wgpu::VertexFormat::UChar4, wgpu::VertexFormat::UChar4Norm }, - }, - { // Uint10 - { wgpu::VertexFormat::UShort2, wgpu::VertexFormat::UShort2Norm }, - { wgpu::VertexFormat::UShort2, wgpu::VertexFormat::UShort2Norm }, - { wgpu::VertexFormat::UShort4, wgpu::VertexFormat::UShort4Norm }, - { wgpu::VertexFormat::UShort4, wgpu::VertexFormat::UShort4Norm }, - }, - { // Int16 - { wgpu::VertexFormat::Short2, wgpu::VertexFormat::Short2Norm }, - { wgpu::VertexFormat::Short2, wgpu::VertexFormat::Short2Norm }, - { wgpu::VertexFormat::Short4, wgpu::VertexFormat::Short4Norm }, - { wgpu::VertexFormat::Short4, wgpu::VertexFormat::Short4Norm }, - }, - { // Half - { wgpu::VertexFormat::Half2, wgpu::VertexFormat::Half2 }, - { wgpu::VertexFormat::Half2, wgpu::VertexFormat::Half2 }, - { wgpu::VertexFormat::Half4, wgpu::VertexFormat::Half4 }, - { wgpu::VertexFormat::Half4, wgpu::VertexFormat::Half4 }, - }, - { // Float - { wgpu::VertexFormat::Float, wgpu::VertexFormat::Float }, - { wgpu::VertexFormat::Float2, wgpu::VertexFormat::Float2 }, - { wgpu::VertexFormat::Float3, wgpu::VertexFormat::Float3 }, - { wgpu::VertexFormat::Float4, wgpu::VertexFormat::Float4 }, - }, - }; - BX_STATIC_ASSERT(AttribType::Count == BX_COUNTOF(s_attribType) ); - - static const wgpu::CullMode s_cullMode[] = - { - wgpu::CullMode::None, - wgpu::CullMode::Front, - wgpu::CullMode::Back, - wgpu::CullMode::None, - }; - - static const wgpu::BlendFactor s_blendFactor[][2] = - { - { wgpu::BlendFactor(0), wgpu::BlendFactor(0) }, // ignored - { wgpu::BlendFactor::Zero, wgpu::BlendFactor::Zero }, // ZERO - { wgpu::BlendFactor::One, wgpu::BlendFactor::One }, // ONE - { wgpu::BlendFactor::SrcColor, wgpu::BlendFactor::SrcAlpha }, // SRC_COLOR - { wgpu::BlendFactor::OneMinusSrcColor, wgpu::BlendFactor::OneMinusSrcAlpha }, // INV_SRC_COLOR - { wgpu::BlendFactor::SrcAlpha, wgpu::BlendFactor::SrcAlpha }, // SRC_ALPHA - { wgpu::BlendFactor::OneMinusSrcAlpha, wgpu::BlendFactor::OneMinusSrcAlpha }, // INV_SRC_ALPHA - { wgpu::BlendFactor::DstAlpha, wgpu::BlendFactor::DstAlpha }, // DST_ALPHA - { wgpu::BlendFactor::OneMinusDstAlpha, wgpu::BlendFactor::OneMinusDstAlpha }, // INV_DST_ALPHA - { wgpu::BlendFactor::DstColor, wgpu::BlendFactor::DstAlpha }, // DST_COLOR - { wgpu::BlendFactor::OneMinusDstColor, wgpu::BlendFactor::OneMinusDstAlpha }, // INV_DST_COLOR - { wgpu::BlendFactor::SrcAlphaSaturated, wgpu::BlendFactor::One }, // SRC_ALPHA_SAT - { wgpu::BlendFactor::BlendColor, wgpu::BlendFactor::BlendColor }, // FACTOR - { wgpu::BlendFactor::OneMinusBlendColor, wgpu::BlendFactor::OneMinusBlendColor }, // INV_FACTOR - }; - - static const wgpu::BlendOperation s_blendEquation[] = - { - wgpu::BlendOperation::Add, - wgpu::BlendOperation::Subtract, - wgpu::BlendOperation::ReverseSubtract, - wgpu::BlendOperation::Min, - wgpu::BlendOperation::Max, - }; - - static const wgpu::CompareFunction s_cmpFunc[] = - { - wgpu::CompareFunction::Always, // ignored - wgpu::CompareFunction::Less, - wgpu::CompareFunction::LessEqual, - wgpu::CompareFunction::Equal, - wgpu::CompareFunction::GreaterEqual, - wgpu::CompareFunction::Greater, - wgpu::CompareFunction::NotEqual, - wgpu::CompareFunction::Never, - wgpu::CompareFunction::Always, - }; - - static const wgpu::StencilOperation s_stencilOp[] = - { - wgpu::StencilOperation::Zero, - wgpu::StencilOperation::Keep, - wgpu::StencilOperation::Replace, - wgpu::StencilOperation::IncrementWrap, - wgpu::StencilOperation::IncrementClamp, - wgpu::StencilOperation::DecrementWrap, - wgpu::StencilOperation::DecrementClamp, - wgpu::StencilOperation::Invert, - }; - - static const wgpu::AddressMode s_textureAddress[] = - { - wgpu::AddressMode::Repeat, - wgpu::AddressMode::MirrorRepeat, - wgpu::AddressMode::ClampToEdge, - wgpu::AddressMode(0), // Border ? ClampToZero ? - }; - - static const wgpu::FilterMode s_textureFilterMinMag[] = - { - wgpu::FilterMode::Linear, - wgpu::FilterMode::Nearest, - wgpu::FilterMode::Linear, - }; - - static const wgpu::FilterMode s_textureFilterMip[] = - { - wgpu::FilterMode::Linear, - wgpu::FilterMode::Nearest, - }; - - struct TextureFormatInfo - { - wgpu::TextureFormat m_fmt; - wgpu::TextureFormat m_fmtSrgb; - }; - - static TextureFormatInfo s_textureFormat[] = - { - { wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb }, // BC1 - { wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb }, // BC2 - { wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb }, // BC3 - { wgpu::TextureFormat::BC4RUnorm, wgpu::TextureFormat::Undefined }, // BC4 // BC4RSnorm ?? - { wgpu::TextureFormat::BC5RGUnorm, wgpu::TextureFormat::Undefined }, // BC5 // BC5RGSnorm ?? - { wgpu::TextureFormat::BC6HRGBUfloat, wgpu::TextureFormat::Undefined }, // BC6H // BC6HRGBSfloat ?? - { wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb }, // BC7 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ETC1 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ETC2 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ETC2A - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ETC2A1 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // PTC12 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // PTC14 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // PTC12A - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // PTC14A - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // PTC22 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // PTC24 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ATC - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ATCE - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ATCI - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ASTC4x4 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ASTC5x5 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ASTC6x6 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ASTC8x5 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ASTC8x6 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // ASTC10x5 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // Unknown - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // R1 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // A8 - { wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::Undefined }, // R8 - { wgpu::TextureFormat::R8Sint, wgpu::TextureFormat::Undefined }, // R8I - { wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::Undefined }, // R8U - { wgpu::TextureFormat::R8Snorm, wgpu::TextureFormat::Undefined }, // R8S - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // R16 - { wgpu::TextureFormat::R16Sint, wgpu::TextureFormat::Undefined }, // R16I - { wgpu::TextureFormat::R16Uint, wgpu::TextureFormat::Undefined }, // R16U - { wgpu::TextureFormat::R16Float, wgpu::TextureFormat::Undefined }, // R16F - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // R16S - { wgpu::TextureFormat::R32Sint, wgpu::TextureFormat::Undefined }, // R32I - { wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::Undefined }, // R32U - { wgpu::TextureFormat::R32Float, wgpu::TextureFormat::Undefined }, // R32F - { wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::Undefined }, // RG8 - { wgpu::TextureFormat::RG8Sint, wgpu::TextureFormat::Undefined }, // RG8I - { wgpu::TextureFormat::RG8Uint, wgpu::TextureFormat::Undefined }, // RG8U - { wgpu::TextureFormat::RG8Snorm, wgpu::TextureFormat::Undefined }, // RG8S - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RG16 - { wgpu::TextureFormat::RG16Sint, wgpu::TextureFormat::Undefined }, // RG16I - { wgpu::TextureFormat::RG16Uint, wgpu::TextureFormat::Undefined }, // RG16U - { wgpu::TextureFormat::RG16Float, wgpu::TextureFormat::Undefined }, // RG16F - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RG16S - { wgpu::TextureFormat::RG32Sint, wgpu::TextureFormat::Undefined }, // RG32I - { wgpu::TextureFormat::RG32Uint, wgpu::TextureFormat::Undefined }, // RG32U - { wgpu::TextureFormat::RG32Float, wgpu::TextureFormat::Undefined }, // RG32F - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RGB8 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RGB8I - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RGB8U - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RGB8S - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RGB9E5F - { wgpu::TextureFormat::BGRA8Unorm, wgpu::TextureFormat::BGRA8UnormSrgb }, // BGRA8 - { wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureFormat::RGBA8UnormSrgb }, // RGBA8 - { wgpu::TextureFormat::RGBA8Sint, wgpu::TextureFormat::Undefined }, // RGBA8I - { wgpu::TextureFormat::RGBA8Uint, wgpu::TextureFormat::Undefined }, // RGBA8U - { wgpu::TextureFormat::RGBA8Snorm, wgpu::TextureFormat::Undefined }, // RGBA8S - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RGBA16 - { wgpu::TextureFormat::RGBA16Sint, wgpu::TextureFormat::Undefined }, // RGBA16I - { wgpu::TextureFormat::RGBA16Uint, wgpu::TextureFormat::Undefined }, // RGBA16U - { wgpu::TextureFormat::RGBA16Float, wgpu::TextureFormat::Undefined }, // RGBA16F - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RGBA16S - { wgpu::TextureFormat::RGBA32Sint, wgpu::TextureFormat::Undefined }, // RGBA32I - { wgpu::TextureFormat::RGBA32Uint, wgpu::TextureFormat::Undefined }, // RGBA32U - { wgpu::TextureFormat::RGBA32Float, wgpu::TextureFormat::Undefined }, // RGBA32F - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // R5G6B5 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RGBA4 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // RGB5A1 - { wgpu::TextureFormat::RGB10A2Unorm, wgpu::TextureFormat::Undefined }, // RGB10A2 - { wgpu::TextureFormat::RG11B10Float, wgpu::TextureFormat::Undefined }, // RG11B10F - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // UnknownDepth - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // D16 - { wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Undefined }, // D24 - { wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureFormat::Undefined }, // D24S8 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // D32 - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // D16F - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // D24F - { wgpu::TextureFormat::Depth32Float, wgpu::TextureFormat::Undefined }, // D32F - { wgpu::TextureFormat::Undefined, wgpu::TextureFormat::Undefined }, // D0S8 - }; - BX_STATIC_ASSERT(TextureFormat::Count == BX_COUNTOF(s_textureFormat)); - - int32_t s_msaa[] = - { - 1, - 2, - 4, - 8, - 16, - }; - - struct RendererContextWgpu; - static RendererContextWgpu* s_renderWgpu; - - static bool s_ignoreError = false; - -#if !BX_PLATFORM_EMSCRIPTEN - DawnSwapChainImplementation(*createSwapChain)(wgpu::Device device, void* nwh); - -#ifdef DAWN_ENABLE_BACKEND_D3D12 - DawnSwapChainImplementation CreateSwapChainD3D12(wgpu::Device device, void* nwh) - { - HWND win32Window = (HWND)nwh; - return dawn_native::d3d12::CreateNativeSwapChainImpl(device.Get(), win32Window); - } -#endif - -#ifdef DAWN_ENABLE_BACKEND_VULKAN - DawnSwapChainImplementation CreateSwapChainVulkan(wgpu::Device device, void* nwh) - { - VkInstance instance = dawn_native::vulkan::GetInstance(device.Get()); - - PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)dawn_native::vulkan::GetInstanceProcAddr(device.Get(), "vkCreateWin32SurfaceKHR"); - - VkSurfaceKHR surface; -#if BX_PLATFORM_WINDOWS - // Copied from renderer_vk.cpp -> needs refactor - { - VkWin32SurfaceCreateInfoKHR sci; - sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - sci.pNext = NULL; - sci.flags = 0; - sci.hinstance = (HINSTANCE)GetModuleHandle(NULL); - sci.hwnd = (HWND)nwh; - VkResult result = vkCreateWin32SurfaceKHR(instance, &sci, NULL, &surface); - } -#endif - return dawn_native::vulkan::CreateNativeSwapChainImpl(device.Get(), surface); - } -#endif - -#endif - - struct RendererContextWgpu : public RendererContextI - { - RendererContextWgpu() - : m_frameIndex(0) - , m_numWindows(0) - , m_rtMsaa(false) - , m_capture(NULL) - , m_captureSize(0) - { - bx::memSet(&m_windows, 0xff, sizeof(m_windows) ); - } - - ~RendererContextWgpu() - { - } - - bool init(const Init& _init) - { - BX_UNUSED(_init); - BX_TRACE("Init."); - - if (_init.debug - || _init.profile) - { - m_renderDocDll = loadRenderDoc(); - } - - setGraphicsDebuggerPresent(NULL != m_renderDocDll); - - m_fbh.idx = kInvalidHandle; - bx::memSet(m_uniforms, 0, sizeof(m_uniforms) ); - bx::memSet(&m_resolution, 0, sizeof(m_resolution) ); - -#if !BX_PLATFORM_EMSCRIPTEN - // Default to D3D12, Metal, Vulkan, OpenGL in that order as D3D12 and Metal are the preferred on - // their respective platforms, and Vulkan is preferred to OpenGL -#if defined(DAWN_ENABLE_BACKEND_D3D12) - static dawn_native::BackendType backendType = dawn_native::BackendType::D3D12; -#elif defined(DAWN_ENABLE_BACKEND_METAL) - static dawn_native::BackendType backendType = dawn_native::BackendType::Metal; -#elif defined(DAWN_ENABLE_BACKEND_OPENGL) - static dawn_native::BackendType backendType = dawn_native::BackendType::OpenGL; -#elif defined(DAWN_ENABLE_BACKEND_VULKAN) - static dawn_native::BackendType backendType = dawn_native::BackendType::Vulkan; -#else -#error -#endif - - m_instance.EnableBackendValidation(true); - m_instance.DiscoverDefaultAdapters(); - - dawn_native::Adapter backendAdapter; - std::vector adapters = m_instance.GetAdapters(); - for (dawn_native::Adapter& adapter : adapters) - { - if (adapter.GetBackendType() == backendType) - { - backendAdapter = adapter; - break; - } - } -#endif - - //BX_ASSERT(adapterIt != adapters.end()); - - WGPUDevice backendDevice = backendAdapter.CreateDevice(); - DawnProcTable backendProcs = dawn_native::GetProcs(); - - using CreateSwapChain = DawnSwapChainImplementation (*)(wgpu::Device device, void* nwh); - -#if defined(DAWN_ENABLE_BACKEND_D3D12) - createSwapChain = CreateSwapChainD3D12; -#elif defined(DAWN_ENABLE_BACKEND_METAL) - createSwapChain = CreateSwapChainMetal; -#elif defined(DAWN_ENABLE_BACKEND_NULL) - createSwapChain = CreateSwapChainNull; -#elif defined(DAWN_ENABLE_BACKEND_OPENGL) - createSwapChain = CreateSwapChainOpenGL; -#elif defined(DAWN_ENABLE_BACKEND_VULKAN) - createSwapChain = CreateSwapChainVulkan; -#endif - - // Choose whether to use the backend procs and devices directly, or set up the wire. - WGPUDevice cDevice = backendDevice; - DawnProcTable procs = backendProcs; - dawnProcSetProcs(&procs); - - m_device = wgpu::Device::Acquire(cDevice); -#else - m_device = wgpu::Device(emscripten_webgpu_get_device()); -#endif - - auto PrintDeviceError = [](WGPUErrorType errorType, const char* message, void*) { - BX_UNUSED(errorType); - - if (s_ignoreError) - { - BX_TRACE("Device error: %s", message); - } - else - { - BX_CHECK(false, "Device error: %s", message); - } - s_ignoreError = false; - }; - - m_device.SetUncapturedErrorCallback(PrintDeviceError, nullptr); - - if (!m_device) - { - BX_WARN(!m_device, "Unable to create WebGPU device."); - return false; - } - - bool success = m_mainFrameBuffer.create( - 0 - , g_platformData.nwh - , _init.resolution.width - , _init.resolution.height - , TextureFormat::Unknown - , TextureFormat::UnknownDepth - ); - m_numWindows = 1; - - if (!success) - { - return false; - } - - m_queue = m_device.GetDefaultQueue(); - - m_cmd.init(m_queue); - //BGFX_FATAL(NULL != m_cmd.m_commandQueue, Fatal::UnableToInitialize, "Unable to create Metal device."); - - for (uint8_t ii = 0; ii < WEBGPU_MAX_FRAMES_IN_FLIGHT; ++ii) - { - BX_TRACE("Create scratch buffer %d", ii); - m_scratchBuffers[ii].create(BGFX_CONFIG_MAX_DRAW_CALLS * 128); - m_bindStateCache[ii].create(); // (1024); - } - - g_caps.supported |= (0 - | BGFX_CAPS_ALPHA_TO_COVERAGE - | BGFX_CAPS_BLEND_INDEPENDENT - | BGFX_CAPS_FRAGMENT_DEPTH - | BGFX_CAPS_INDEX32 - | BGFX_CAPS_INSTANCING - // | BGFX_CAPS_OCCLUSION_QUERY - | BGFX_CAPS_SWAP_CHAIN - | BGFX_CAPS_TEXTURE_2D_ARRAY - // | BGFX_CAPS_TEXTURE_3D - | BGFX_CAPS_TEXTURE_BLIT - | BGFX_CAPS_TEXTURE_COMPARE_ALL - | BGFX_CAPS_TEXTURE_COMPARE_LEQUAL - | BGFX_CAPS_TEXTURE_READ_BACK - | BGFX_CAPS_VERTEX_ATTRIB_HALF - | BGFX_CAPS_VERTEX_ATTRIB_UINT10 - | BGFX_CAPS_COMPUTE - ); - - g_caps.limits.maxTextureSize = 16384; - g_caps.limits.maxFBAttachments = 4; - g_caps.supported |= BGFX_CAPS_TEXTURE_CUBE_ARRAY; - - if (BX_ENABLED(INDIRECT) ) - { - g_caps.supported |= BGFX_CAPS_DRAW_INDIRECT; - } - - g_caps.limits.maxTextureLayers = 2048; - g_caps.limits.maxVertexStreams = BGFX_CONFIG_MAX_VERTEX_STREAMS; - // Maximum number of entries in the buffer argument table, per graphics or compute function are 31. - // It is decremented by 1 because 1 entry is used for uniforms. - g_caps.limits.maxComputeBindings = bx::uint32_min(30, BGFX_MAX_COMPUTE_BINDINGS); - - for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) - { - uint16_t support = 0; - - support |= wgpu::TextureFormat::Undefined != s_textureFormat[ii].m_fmt - ? BGFX_CAPS_FORMAT_TEXTURE_2D - | BGFX_CAPS_FORMAT_TEXTURE_3D - | BGFX_CAPS_FORMAT_TEXTURE_CUBE - | BGFX_CAPS_FORMAT_TEXTURE_VERTEX - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; - - support |= wgpu::TextureFormat::Undefined != s_textureFormat[ii].m_fmtSrgb - ? BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB - | BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB - | BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB - | BGFX_CAPS_FORMAT_TEXTURE_VERTEX - : BGFX_CAPS_FORMAT_TEXTURE_NONE - ; - - if (!bimg::isCompressed(bimg::TextureFormat::Enum(ii) ) ) - { - support |= 0 - | BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER - // | BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA - ; - } - - g_caps.formats[ii] = support; - } - - g_caps.formats[TextureFormat::A8 ] &= ~(BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER | BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA); - g_caps.formats[TextureFormat::RG32I ] &= ~(BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA); - g_caps.formats[TextureFormat::RG32U ] &= ~(BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA); - g_caps.formats[TextureFormat::RGBA32I] &= ~(BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA); - g_caps.formats[TextureFormat::RGBA32U] &= ~(BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA); - - g_caps.formats[TextureFormat::ETC2 ] = - g_caps.formats[TextureFormat::ETC2A ] = - g_caps.formats[TextureFormat::ETC2A1] = - g_caps.formats[TextureFormat::PTC12 ] = - g_caps.formats[TextureFormat::PTC14 ] = - g_caps.formats[TextureFormat::PTC12A] = - g_caps.formats[TextureFormat::PTC14A] = - g_caps.formats[TextureFormat::R5G6B5] = - g_caps.formats[TextureFormat::RGBA4 ] = - g_caps.formats[TextureFormat::RGB5A1] = BGFX_CAPS_FORMAT_TEXTURE_NONE; - - g_caps.formats[TextureFormat::RGB9E5F] &= ~(BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER | BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA); - - // disable compressed formats - for (uint32_t ii = 0; ii < TextureFormat::Unknown; ++ii) - { - s_textureFormat[ii].m_fmt = wgpu::TextureFormat::Undefined; - } - - for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) - { - if (BGFX_CAPS_FORMAT_TEXTURE_NONE == g_caps.formats[ii]) - { - s_textureFormat[ii].m_fmt = wgpu::TextureFormat::Undefined; - s_textureFormat[ii].m_fmtSrgb = wgpu::TextureFormat::Undefined; - } - } - - for (uint32_t ii = 1, last = 0; ii < BX_COUNTOF(s_msaa); ++ii) - { - // TODO (hugoam) - //const int32_t sampleCount = 1; //1<size, _mem->data, _flags); - } - - void destroyIndexBuffer(IndexBufferHandle _handle) override - { - m_indexBuffers[_handle.idx].destroy(); - } - - void createVertexLayout(VertexLayoutHandle _handle, const VertexLayout& _decl) override - { - VertexLayout& decl = m_vertexDecls[_handle.idx]; - bx::memCopy(&decl, &_decl, sizeof(VertexLayout) ); - dump(decl); - } - - void destroyVertexLayout(VertexLayoutHandle /*_handle*/) override - { - } - - void createVertexBuffer(VertexBufferHandle _handle, const Memory* _mem, VertexLayoutHandle _declHandle, uint16_t _flags) override - { - m_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _declHandle, _flags); - } - - void destroyVertexBuffer(VertexBufferHandle _handle) override - { - m_vertexBuffers[_handle.idx].destroy(); - } - - void createDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _size, uint16_t _flags) override - { - m_indexBuffers[_handle.idx].create(_size, NULL, _flags); - } - - void updateDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _offset, uint32_t _size, const Memory* _mem) override - { - m_indexBuffers[_handle.idx].update(_offset, bx::uint32_min(_size, _mem->size), _mem->data); - } - - void destroyDynamicIndexBuffer(IndexBufferHandle _handle) override - { - m_indexBuffers[_handle.idx].destroy(); - } - - void createDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size, uint16_t _flags) override - { - VertexLayoutHandle decl = BGFX_INVALID_HANDLE; - m_vertexBuffers[_handle.idx].create(_size, NULL, decl, _flags); - } - - void updateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _offset, uint32_t _size, const Memory* _mem) override - { - m_vertexBuffers[_handle.idx].update(_offset, bx::uint32_min(_size, _mem->size), _mem->data); - } - - void destroyDynamicVertexBuffer(VertexBufferHandle _handle) override - { - m_vertexBuffers[_handle.idx].destroy(); - } - - void createShader(ShaderHandle _handle, const Memory* _mem) override - { - m_shaders[_handle.idx].create(_handle, _mem); - } - - void destroyShader(ShaderHandle _handle) override - { - m_shaders[_handle.idx].destroy(); - } - - void createProgram(ProgramHandle _handle, ShaderHandle _vsh, ShaderHandle _fsh) override - { - m_program[_handle.idx].create(&m_shaders[_vsh.idx], isValid(_fsh) ? &m_shaders[_fsh.idx] : NULL); - } - - void destroyProgram(ProgramHandle _handle) override - { - m_program[_handle.idx].destroy(); - } - - void* createTexture(TextureHandle _handle, const Memory* _mem, uint64_t _flags, uint8_t _skip) override - { - m_textures[_handle.idx].create(_handle, _mem, _flags, _skip); - return NULL; - } - - void updateTextureBegin(TextureHandle /*_handle*/, uint8_t /*_side*/, uint8_t /*_mip*/) override - { - } - - void updateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) override - { - m_textures[_handle.idx].update(_side, _mip, _rect, _z, _depth, _pitch, _mem); - } - - void updateTextureEnd() override - { - } - - void readback(ReadbackWgpu& readback, const TextureWgpu& texture, void* _data) - { - m_cmd.kick(false, true); - m_cmd.begin(); - - if (readback.m_mapped) - return; - - BX_CHECK(readback.m_mip> readback.m_mip); - uint32_t srcHeight = bx::uint32_max(1, texture.m_height >> readback.m_mip); - - const uint32_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(texture.m_textureFormat)); - const uint32_t pitch = srcWidth * bpp / 8; - - const uint32_t dstpitch = bx::strideAlign(pitch, 256); - - // TODO move inside ReadbackWgpu::create - if (!readback.m_buffer) - { - wgpu::BufferDescriptor desc; - desc.size = dstpitch * srcHeight; - desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead; - - readback.m_buffer = m_device.CreateBuffer(&desc); - } - - wgpu::TextureCopyView textureCopyView; - textureCopyView.texture = texture.m_ptr; - textureCopyView.origin = { 0, 0, 0 }; - - wgpu::BufferCopyView bufferCopyView; - bufferCopyView.buffer = readback.m_buffer; - bufferCopyView.bytesPerRow = dstpitch; - bufferCopyView.rowsPerImage = srcHeight; - - wgpu::Extent3D extent3D = { srcWidth, srcHeight, 1 }; - m_cmd.m_encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, &extent3D); - - auto finish = [](WGPUBufferMapAsyncStatus status, void const* data, uint64_t dataLength, void* userdata) - { - if(status == WGPUBufferMapAsyncStatus_Success) - static_cast(userdata)->readback(data, dataLength); - }; - - m_cmd.finish(); - - m_cmd.kick(true); - - readback.m_mapped = true; - readback.m_data = _data; - readback.m_size = pitch * srcHeight; - - readback.m_buffer.MapReadAsync(finish, &readback); - } - - void readTexture(TextureHandle _handle, void* _data, uint8_t _mip) override - { - TextureWgpu& texture = m_textures[_handle.idx]; - - readback(texture.m_readback, texture, _data); - } - - void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) override - { - TextureWgpu& texture = m_textures[_handle.idx]; - - uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate); - const Memory* mem = alloc(size); - - bx::StaticMemoryBlockWriter writer(mem->data, mem->size); - uint32_t magic = BGFX_CHUNK_MAGIC_TEX; - bx::write(&writer, magic); - - TextureCreate tc; - tc.m_width = _width; - tc.m_height = _height; - tc.m_depth = 0; - tc.m_numLayers = _numLayers; - tc.m_numMips = _numMips; - tc.m_format = TextureFormat::Enum(texture.m_requestedFormat); - tc.m_cubeMap = false; - tc.m_mem = NULL; - bx::write(&writer, tc); - - texture.destroy(); - texture.create(_handle, mem, texture.m_flags, 0); - - release(mem); - } - - void overrideInternal(TextureHandle _handle, uintptr_t _ptr) override - { - BX_UNUSED(_handle, _ptr); - } - - uintptr_t getInternal(TextureHandle _handle) override - { - BX_UNUSED(_handle); - return 0; - } - - void destroyTexture(TextureHandle _handle) override - { - m_textures[_handle.idx].destroy(); - } - - void createFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const Attachment* _attachment) override - { - m_frameBuffers[_handle.idx].create(_num, _attachment); - } - - void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) override - { - for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) - { - FrameBufferHandle handle = m_windows[ii]; - if (isValid(handle) - && m_frameBuffers[handle.idx].m_nwh == _nwh) - { - destroyFrameBuffer(handle); - } - } - - uint16_t denseIdx = m_numWindows++; - m_windows[denseIdx] = _handle; - - FrameBufferWgpu& fb = m_frameBuffers[_handle.idx]; - fb.create(denseIdx, _nwh, _width, _height, _format, _depthFormat); - fb.m_swapChain->resize(m_frameBuffers[_handle.idx], _width, _height, 0); - } - - void destroyFrameBuffer(FrameBufferHandle _handle) override - { - uint16_t denseIdx = m_frameBuffers[_handle.idx].destroy(); - - if (UINT16_MAX != denseIdx) - { - --m_numWindows; - - if (m_numWindows > 1) - { - FrameBufferHandle handle = m_windows[m_numWindows]; - m_windows[m_numWindows] = {kInvalidHandle}; - - if (m_numWindows != denseIdx) - { - m_windows[denseIdx] = handle; - m_frameBuffers[handle.idx].m_denseIdx = denseIdx; - } - } - } - } - - void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) override - { - if (NULL != m_uniforms[_handle.idx]) - { - BX_FREE(g_allocator, m_uniforms[_handle.idx]); - } - - uint32_t size = bx::alignUp(g_uniformTypeSize[_type]*_num, 16); - void* data = BX_ALLOC(g_allocator, size); - bx::memSet(data, 0, size); - m_uniforms[_handle.idx] = data; - m_uniformReg.add(_handle, _name); - } - - void destroyUniform(UniformHandle _handle) override - { - BX_FREE(g_allocator, m_uniforms[_handle.idx]); - m_uniforms[_handle.idx] = NULL; - m_uniformReg.remove(_handle); - } - - void requestScreenShotPre(const char* _filePath) - { - BX_UNUSED(_filePath); - //m_saveScreenshot = true; - } - - void requestScreenShot(FrameBufferHandle _handle, const char* _filePath) override - { - BX_UNUSED(_handle); BX_UNUSED(_filePath); - } - - void updateViewName(ViewId _id, const char* _name) override - { - bx::strCopy( - &s_viewName[_id][BGFX_CONFIG_MAX_VIEW_NAME_RESERVED] - , BX_COUNTOF(s_viewName[0])-BGFX_CONFIG_MAX_VIEW_NAME_RESERVED - , _name - ); - } - - void updateUniform(uint16_t _loc, const void* _data, uint32_t _size) override - { - bx::memCopy(m_uniforms[_loc], _data, _size); - } - - void invalidateOcclusionQuery(OcclusionQueryHandle _handle) override - { - BX_UNUSED(_handle); - } - - void setMarker(const char* _marker, uint16_t _len) override - { - BX_UNUSED(_len); - - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) ) - { - m_renderEncoder.InsertDebugMarker(_marker); - } - } - - void submitBlit(BlitState& _bs, uint16_t _view); - - void submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) override; - - void blitSetup(TextVideoMemBlitter& _blitter) override - { - BX_UNUSED(_blitter); - } - - void blitRender(TextVideoMemBlitter& _blitter, uint32_t _numIndices) override - { - const uint32_t numVertices = _numIndices*4/6; - if (0 < numVertices) - { - m_indexBuffers [_blitter.m_ib->handle.idx].update( - 0 - , bx::strideAlign(_numIndices*2, 4) - , _blitter.m_ib->data - , true - ); - m_vertexBuffers[_blitter.m_vb->handle.idx].update( - 0 - , numVertices*_blitter.m_layout.m_stride - , _blitter.m_vb->data - , true - ); - - endEncoding(); - - uint32_t width = m_resolution.width; - uint32_t height = m_resolution.height; - - FrameBufferHandle fbh = BGFX_INVALID_HANDLE; - - uint64_t state = 0 - | BGFX_STATE_WRITE_RGB - | BGFX_STATE_WRITE_A - | BGFX_STATE_DEPTH_TEST_ALWAYS - ; - - PipelineStateWgpu* pso = getPipelineState( - state - , 0 - , 0 - , fbh - , _blitter.m_vb->layoutHandle - , false - , _blitter.m_program - , 0 - ); - - RenderPassDescriptor renderPassDescriptor; - wgpu::RenderPassColorAttachmentDescriptor& color = renderPassDescriptor.colorAttachments[0]; - - setFrameBuffer(renderPassDescriptor, fbh); - - color.loadOp = wgpu::LoadOp::Load; - color.storeOp = wgpu::StoreOp::Store; - // NULL != renderPassDescriptor.colorAttachments[0].resolveTexture - // ? wgpu::StoreOp::MultisampleResolve - // : wgpu::StoreOp::Store - //; - - wgpu::RenderPassEncoder rce = m_cmd.m_encoder.BeginRenderPass(&renderPassDescriptor.desc); - m_renderEncoder = rce; - - rce.SetViewport(0.0f, 0.0f, (float)width, (float)height, 0.0f, 1.0f); - - rce.SetPipeline(pso->m_rps); - - ProgramWgpu& program = m_program[_blitter.m_program.idx]; - - ScratchBufferWgpu& scratchBuffer = m_scratchBuffers[0]; - BindStateCacheWgpu& bindStates = m_bindStateCache[0]; - - const uint32_t voffset = scratchBuffer.m_offset; - scratchBuffer.m_offset += program.m_gpuSize; - - float proj[16]; - bx::mtxOrtho(proj, 0.0f, (float)width, (float)height, 0.0f, 0.0f, 1000.0f, 0.0f, false); - - PredefinedUniform& predefined = program.m_predefined[0]; - uint8_t flags = predefined.m_type; - setShaderUniform(flags, predefined.m_loc, proj, 4); - - BX_CHECK(program.m_vsh->m_size > 0, "Not supposed to happen"); - scratchBuffer.m_buffer.SetSubData(voffset, program.m_vsh->m_gpuSize, m_vsScratch); - - const uint32_t fsize = (NULL != program.m_fsh ? program.m_fsh->m_gpuSize : 0); - BX_CHECK(fsize == 0, "Not supposed to happen"); - - TextureWgpu& texture = m_textures[_blitter.m_texture.idx]; - - BindingsWgpu b; - - BindStateWgpu& bindState = allocBindState(program, bindStates, b, scratchBuffer); - - wgpu::BindGroupEntry& textureEntry = b.m_entries[b.numEntries++]; - textureEntry.binding = program.m_textures[0].binding; - textureEntry.textureView = texture.m_ptr.CreateView(); - - wgpu::BindGroupEntry& samplerEntry = b.m_entries[b.numEntries++]; - samplerEntry.binding = program.m_samplers[0].binding; - samplerEntry.sampler = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & state) - ? getSamplerState(state) - : texture.m_sampler; - - bindGroups(program, bindState, b); - - uint32_t numOffset = 1; - uint32_t offsets[1] = { voffset }; - - bindProgram(rce, program, bindState, numOffset, offsets); - - VertexBufferWgpu& vb = m_vertexBuffers[_blitter.m_vb->handle.idx]; - rce.SetVertexBuffer(0, vb.m_ptr); - - rce.SetIndexBuffer(m_indexBuffers[_blitter.m_ib->handle.idx].m_ptr); - rce.DrawIndexed(_numIndices, 1, 0, 0, 0); - } - } - - bool isDeviceRemoved() override - { - return false; - } - - void flip() override - { - for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) - { - FrameBufferWgpu& frameBuffer = ii == 0 ? m_mainFrameBuffer : m_frameBuffers[m_windows[ii].idx]; - if (NULL != frameBuffer.m_swapChain) - //&& frameBuffer.m_swapChain->m_drawable) - { - SwapChainWgpu& swapChain = *frameBuffer.m_swapChain; - swapChain.flip(); - } - } - - m_cmd.m_encoder = nullptr; - } - - void updateResolution(const Resolution& _resolution) - { - m_resolution = _resolution; - return; // TODO (hugoam) - - m_mainFrameBuffer.m_swapChain->m_maxAnisotropy = !!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) - ? 16 - : 1 - ; - - const uint32_t maskFlags = ~(0 - | BGFX_RESET_MAXANISOTROPY - | BGFX_RESET_DEPTH_CLAMP - | BGFX_RESET_SUSPEND - ); - - if (m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height - || (m_resolution.reset&maskFlags) != (_resolution.reset&maskFlags) ) - { - wgpu::TextureFormat prevMetalLayerPixelFormat; // = m_mainFrameBuffer.m_swapChain->m_metalLayer.pixelFormat; - BX_UNUSED(prevMetalLayerPixelFormat); - - m_resolution = _resolution; - m_resolution.reset &= ~BGFX_RESET_INTERNAL_FORCE; - - m_mainFrameBuffer.m_swapChain->resize(m_mainFrameBuffer, _resolution.width, _resolution.height, _resolution.reset); - - for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) - { - m_frameBuffers[ii].postReset(); - } - - updateCapture(); - - m_textVideoMem.resize(false, _resolution.width, _resolution.height); - m_textVideoMem.clear(); - - //if (prevMetalLayerPixelFormat != m_mainFrameBuffer.m_swapChain->m_metalLayer.pixelFormat) - { - //MTL_RELEASE(m_screenshotBlitRenderPipelineState) - //reset(m_renderPipelineDescriptor); - - //m_renderPipelineDescriptor.colorAttachments[0].pixelFormat = m_mainFrameBuffer.m_swapChain->m_metalLayer.pixelFormat; - //m_renderPipelineDescriptor.vertexFunction = m_screenshotBlitProgram.m_vsh->m_function; - //m_renderPipelineDescriptor.fragmentFunction = m_screenshotBlitProgram.m_fsh->m_function; - //m_screenshotBlitRenderPipelineState = m_device.newRenderPipelineStateWithDescriptor(m_renderPipelineDescriptor); - } - } - } - - void invalidateCompute() - { - if (m_computeEncoder) - { - m_computeEncoder.EndPass(); - m_computeEncoder = NULL; - } - } - - void updateCapture() - { - } - - void capture() - { - } - - void captureFinish() - { - } - - BindStateWgpu& allocBindState(const ProgramWgpu& program, BindStateCacheWgpu& bindStates, BindingsWgpu& bindings, ScratchBufferWgpu& scratchBuffer) - { - BindStateWgpu& bindState = bindStates.m_bindStates[bindStates.m_currentBindState]; - bindStates.m_currentBindState++; - - bindState.numOffset = program.m_numUniforms; - - // first two bindings are always uniform buffer (vertex/fragment) - bindings.m_entries[0].binding = 0; - bindings.m_entries[0].offset = 0; - bindings.m_entries[0].size = program.m_vsh->m_gpuSize; - bindings.m_entries[0].buffer = scratchBuffer.m_buffer; - bindings.numEntries++; - - if (NULL != program.m_fsh - && 0 < program.m_fsh->m_gpuSize) - { - bindings.m_entries[1].binding = 48; - bindings.m_entries[1].offset = 0; - bindings.m_entries[1].size = program.m_fsh->m_gpuSize; - bindings.m_entries[1].buffer = scratchBuffer.m_buffer; - bindings.numEntries++; - } - - return bindState; - } - - void bindGroups(const ProgramWgpu& program, BindStateWgpu& bindState, BindingsWgpu& bindings) - { - wgpu::BindGroupDescriptor bindGroupDesc; - bindGroupDesc.layout = program.m_bindGroupLayout; - bindGroupDesc.entryCount = bindings.numEntries; - bindGroupDesc.entries = bindings.m_entries; - - bindState.m_bindGroup = m_device.CreateBindGroup(&bindGroupDesc); - } - - template - void bindProgram(Encoder& encoder, const ProgramWgpu& program, BindStateWgpu& bindState, uint32_t numOffset, uint32_t* offsets) - { - BX_CHECK(bindState.numOffset == numOffset, "We're obviously doing something wrong"); - encoder.SetBindGroup(0, bindState.m_bindGroup, numOffset, offsets); - } - - void allocBindState(const ProgramWgpu& program, BindStateCacheWgpu& bindStates, ScratchBufferWgpu& scratchBuffer, const RenderBind& renderBind) - { - BindingsWgpu b; - - BindStateWgpu& bindState = allocBindState(program, bindStates, b, scratchBuffer); - - for (uint8_t stage = 0; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++stage) - { - const Binding& bind = renderBind.m_bind[stage]; - const BindInfo& bindInfo = program.m_bindInfo[stage]; - - bool isUsed = isValid(program.m_bindInfo[stage].m_uniform); - - BX_CHECK(!isUsed || kInvalidHandle != bind.m_idx, "All expected bindings must be bound with WebGPU"); - - if (kInvalidHandle != bind.m_idx) - { - switch (bind.m_type) - { - case Binding::Image: - { - TextureWgpu& texture = m_textures[bind.m_idx]; - wgpu::BindGroupEntry& entry = b.m_entries[b.numEntries++]; - entry.binding = bindInfo.m_binding; - entry.textureView = texture.getTextureMipLevel(bind.m_mip); - } - break; - - case Binding::Texture: - { - // apparently bgfx allows to set a texture to a stage that a program does not even use - if (isUsed) - { - TextureWgpu& texture = m_textures[bind.m_idx]; - uint32_t flags = bind.m_samplerFlags; - - wgpu::TextureViewDescriptor viewDesc = defaultDescriptor(); - viewDesc.dimension = program.m_textures[bindInfo.m_index].viewDimension; - - wgpu::BindGroupEntry& textureEntry = b.m_entries[b.numEntries++]; - textureEntry.binding = bindInfo.m_binding; - textureEntry.textureView = texture.m_ptr.CreateView(); - //textureEntry.textureView = texture.m_ptr.CreateView(&viewDesc); - - wgpu::BindGroupEntry& samplerEntry = b.m_entries[b.numEntries++]; - samplerEntry.binding = bindInfo.m_binding + 16; - samplerEntry.sampler = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & flags) - ? getSamplerState(flags) - : texture.m_sampler; - } - } - break; - - case Binding::IndexBuffer: - case Binding::VertexBuffer: - { - const BufferWgpu& buffer = Binding::IndexBuffer == bind.m_type - ? m_indexBuffers[bind.m_idx] - : m_vertexBuffers[bind.m_idx] - ; - - wgpu::BindGroupEntry& entry = b.m_entries[b.numEntries++]; - entry.binding = bindInfo.m_binding; - entry.offset = 0; - entry.size = buffer.m_size; - entry.buffer = buffer.m_ptr; - } - break; - } - } - } - - bindGroups(program, bindState, b); - }; - - void setShaderUniform(uint8_t _flags, uint32_t _regIndex, const void* _val, uint32_t _numRegs) - { - if(_flags&BGFX_UNIFORM_FRAGMENTBIT) - { - bx::memCopy(&m_fsScratch[_regIndex], _val, _numRegs * 16); - } - else - { - bx::memCopy(&m_vsScratch[_regIndex], _val, _numRegs * 16); - } - } - - void setShaderUniform4f(uint8_t _flags, uint32_t _loc, const void* _val, uint32_t _numRegs) - { - setShaderUniform(_flags, _loc, _val, _numRegs); - } - - void setShaderUniform4x4f(uint8_t _flags, uint32_t _loc, const void* _val, uint32_t _numRegs) - { - setShaderUniform(_flags, _loc, _val, _numRegs); - } - - void commitShaderConstants(ScratchBufferWgpu& _scratchBuffer, const ProgramWgpu& _program, uint32_t _vertexOffset, uint32_t _fragmentOffset) - { - const uint32_t size = _program.m_vsh->m_size; - if (0 != size) - _scratchBuffer.m_buffer.SetSubData(_vertexOffset, size, m_vsScratch); - - if(NULL != _program.m_fsh) - { - const uint32_t size = _program.m_fsh->m_size; - if(0 != size) - _scratchBuffer.m_buffer.SetSubData(_fragmentOffset, size, m_fsScratch); - } - } - - void commit(UniformBuffer& _uniformBuffer) - { - _uniformBuffer.reset(); - - for (;;) - { - uint32_t opcode = _uniformBuffer.read(); - - if (UniformType::End == opcode) - { - break; - } - - UniformType::Enum type; - uint16_t loc; - uint16_t num; - uint16_t copy; - UniformBuffer::decodeOpcode(opcode, type, loc, num, copy); - - const char* data; - if (copy) - { - data = _uniformBuffer.read(g_uniformTypeSize[type]*num); - } - else - { - UniformHandle handle; - bx::memCopy(&handle, _uniformBuffer.read(sizeof(UniformHandle) ), sizeof(UniformHandle) ); - data = (const char*)m_uniforms[handle.idx]; - } - - switch ( (uint32_t)type) - { - case UniformType::Mat3: - case UniformType::Mat3|BGFX_UNIFORM_FRAGMENTBIT: - { - float* value = (float*)data; - for (uint32_t ii = 0, count = num/3; ii < count; ++ii, loc += 3*16, value += 9) - { - Matrix4 mtx; - mtx.un.val[ 0] = value[0]; - mtx.un.val[ 1] = value[1]; - mtx.un.val[ 2] = value[2]; - mtx.un.val[ 3] = 0.0f; - mtx.un.val[ 4] = value[3]; - mtx.un.val[ 5] = value[4]; - mtx.un.val[ 6] = value[5]; - mtx.un.val[ 7] = 0.0f; - mtx.un.val[ 8] = value[6]; - mtx.un.val[ 9] = value[7]; - mtx.un.val[10] = value[8]; - mtx.un.val[11] = 0.0f; - setShaderUniform(uint8_t(type), loc, &mtx.un.val[0], 3); - } - } - break; - - case UniformType::Sampler: - case UniformType::Sampler | BGFX_UNIFORM_FRAGMENTBIT: - case UniformType::Vec4: - case UniformType::Vec4 | BGFX_UNIFORM_FRAGMENTBIT: - case UniformType::Mat4: - case UniformType::Mat4 | BGFX_UNIFORM_FRAGMENTBIT: - { - setShaderUniform(uint8_t(type), loc, data, num); - } - break; - case UniformType::End: - break; - - default: - BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", _uniformBuffer.getPos(), opcode, type, loc, num, copy); - break; - } - } - } - - void clearQuad(ClearQuad& _clearQuad, const Rect& /*_rect*/, const Clear& _clear, const float _palette[][4]) - { - uint32_t width; - uint32_t height; - - if (isValid(m_fbh) ) - { - const FrameBufferWgpu& fb = m_frameBuffers[m_fbh.idx]; - width = fb.m_width; - height = fb.m_height; - } - else - { - width = m_resolution.width; - height = m_resolution.height; - } - - uint64_t state = 0; - state |= _clear.m_flags & BGFX_CLEAR_COLOR ? BGFX_STATE_WRITE_RGB|BGFX_STATE_WRITE_A : 0; - state |= _clear.m_flags & BGFX_CLEAR_DEPTH ? BGFX_STATE_DEPTH_TEST_ALWAYS|BGFX_STATE_WRITE_Z : 0; - state |= BGFX_STATE_PT_TRISTRIP; - - uint64_t stencil = 0; - stencil |= _clear.m_flags & BGFX_CLEAR_STENCIL ? 0 - | BGFX_STENCIL_TEST_ALWAYS - | BGFX_STENCIL_FUNC_REF(_clear.m_stencil) - | BGFX_STENCIL_FUNC_RMASK(0xff) - | BGFX_STENCIL_OP_FAIL_S_REPLACE - | BGFX_STENCIL_OP_FAIL_Z_REPLACE - | BGFX_STENCIL_OP_PASS_Z_REPLACE - : 0 - ; - - uint32_t numMrt = 1; - FrameBufferHandle fbh = m_fbh; - if (isValid(fbh) && m_frameBuffers[fbh.idx].m_swapChain == NULL) - { - const FrameBufferWgpu& fb = m_frameBuffers[fbh.idx]; - numMrt = bx::uint32_max(1, fb.m_num); - } - - wgpu::RenderPassEncoder rce = m_renderEncoder; - ProgramHandle programHandle = _clearQuad.m_program[numMrt-1]; - - const VertexLayout* decl = &_clearQuad.m_layout; - const PipelineStateWgpu* pso = getPipelineState( - state - , stencil - , 0 - , fbh - , 1 - , &decl - , false - , programHandle - , 0 - ); - rce.SetPipeline(pso->m_rps); - - float mrtClearColor[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS][4]; - float mrtClearDepth[4] = { _clear.m_depth }; - - if (BGFX_CLEAR_COLOR_USE_PALETTE & _clear.m_flags) - { - for (uint32_t ii = 0; ii < numMrt; ++ii) - { - uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_COLOR_PALETTE-1, _clear.m_index[ii]); - bx::memCopy(mrtClearColor[ii], _palette[index], 16); - } - } - else - { - float rgba[4] = - { - _clear.m_index[0]*1.0f/255.0f, - _clear.m_index[1]*1.0f/255.0f, - _clear.m_index[2]*1.0f/255.0f, - _clear.m_index[3]*1.0f/255.0f, - }; - - for (uint32_t ii = 0; ii < numMrt; ++ii) - { - bx::memCopy( mrtClearColor[ii] - , rgba - , 16 - ); - } - } - - ProgramWgpu& program = m_program[programHandle.idx]; - - ScratchBufferWgpu& scratchBuffer = m_scratchBuffers[0]; - BindStateCacheWgpu& bindStates = m_bindStateCache[0]; - - BindingsWgpu b; - BindStateWgpu& bindState = allocBindState(program, bindStates, b, scratchBuffer); - - const uint32_t voffset = scratchBuffer.m_offset; - const uint32_t foffset = scratchBuffer.m_offset + program.m_vsh->m_gpuSize; - scratchBuffer.m_offset += program.m_gpuSize; - - scratchBuffer.m_buffer.SetSubData(voffset, bx::uint32_min(program.m_vsh->m_gpuSize, sizeof(mrtClearDepth)), (uint8_t*)mrtClearDepth); - scratchBuffer.m_buffer.SetSubData(foffset, bx::uint32_min(program.m_fsh->m_gpuSize, sizeof(mrtClearColor)), (uint8_t*)mrtClearColor); - - uint32_t numOffset = 2; - uint32_t offsets[2] = { voffset, foffset }; - - bindGroups(program, bindState, b); - - const VertexBufferWgpu& vb = m_vertexBuffers[_clearQuad.m_vb.idx]; - - bindProgram(rce, program, bindState, numOffset, offsets); - - rce.SetVertexBuffer(0, vb.m_ptr); - rce.Draw(4, 1, 0, 0); - } - - wgpu::TextureViewDescriptor attachmentView(const Attachment& _at, const TextureWgpu& _texture) - { - bool _resolve = bool(_texture.m_ptrMsaa); - BX_UNUSED(_resolve); - - wgpu::TextureViewDescriptor desc; - if (1 < _texture.m_numSides) - { - desc.baseArrayLayer = _at.layer; - } - desc.baseMipLevel = _at.mip; - desc.arrayLayerCount = 1; - desc.mipLevelCount = 1; - - if (_texture.m_type == TextureWgpu::Texture3D) - { - desc.dimension = wgpu::TextureViewDimension::e3D; - } - - return desc; - } - - void setFrameBuffer(RenderPassDescriptor& _renderPassDescriptor, FrameBufferHandle _fbh, bool _msaa = true) - { - if (!isValid(_fbh) - || m_frameBuffers[_fbh.idx].m_swapChain) - { - SwapChainWgpu* swapChain = !isValid(_fbh) - ? m_mainFrameBuffer.m_swapChain - : m_frameBuffers[_fbh.idx].m_swapChain - ; - - _renderPassDescriptor.colorAttachments[0] = defaultDescriptor(); - _renderPassDescriptor.desc.colorAttachmentCount = 1; - - // Force 1 array layers for attachments - wgpu::TextureViewDescriptor desc; - desc.arrayLayerCount = 1; - - if (swapChain->m_backBufferColorMsaa) - { - _renderPassDescriptor.colorAttachments[0].attachment = swapChain->m_backBufferColorMsaa.CreateView(&desc); - _renderPassDescriptor.colorAttachments[0].resolveTarget = swapChain->current(); - } - else - { - _renderPassDescriptor.colorAttachments[0].attachment = swapChain->current(); - } - - _renderPassDescriptor.depthStencilAttachment = defaultDescriptor(); - _renderPassDescriptor.depthStencilAttachment.attachment = swapChain->m_backBufferDepth.CreateView(); - _renderPassDescriptor.desc.depthStencilAttachment = &_renderPassDescriptor.depthStencilAttachment; - } - else - { - FrameBufferWgpu& frameBuffer = m_frameBuffers[_fbh.idx]; - - _renderPassDescriptor.desc.colorAttachmentCount = frameBuffer.m_num; - - for (uint32_t ii = 0; ii < frameBuffer.m_num; ++ii) - { - const TextureWgpu& texture = m_textures[frameBuffer.m_colorHandle[ii].idx]; - - const wgpu::TextureViewDescriptor desc = attachmentView(frameBuffer.m_colorAttachment[ii], texture); - - _renderPassDescriptor.colorAttachments[ii] = defaultDescriptor(); - _renderPassDescriptor.colorAttachments[ii].attachment = texture.m_ptrMsaa - ? texture.m_ptrMsaa.CreateView(&desc) - : texture.m_ptr.CreateView(&desc) - ; - _renderPassDescriptor.colorAttachments[ii].resolveTarget = texture.m_ptrMsaa - ? texture.m_ptr.CreateView(&desc) - : wgpu::TextureView() - ; - } - - if (isValid(frameBuffer.m_depthHandle) ) - { - const TextureWgpu& texture = m_textures[frameBuffer.m_depthHandle.idx]; - const wgpu::TextureViewDescriptor desc = attachmentView(frameBuffer.m_depthAttachment, texture); - - _renderPassDescriptor.depthStencilAttachment = defaultDescriptor(); - _renderPassDescriptor.depthStencilAttachment.attachment = texture.m_ptrMsaa - ? texture.m_ptrMsaa.CreateView(&desc) - : texture.m_ptr.CreateView(&desc) - ; - - _renderPassDescriptor.desc.depthStencilAttachment = &_renderPassDescriptor.depthStencilAttachment; - } - } - - m_fbh = _fbh; - m_rtMsaa = _msaa; - } - - void setDepthStencilState(wgpu::DepthStencilStateDescriptor& desc, uint64_t _state, uint64_t _stencil = 0) - { - const uint32_t fstencil = unpackStencil(0, _stencil); - const uint32_t func = (_state&BGFX_STATE_DEPTH_TEST_MASK) >> BGFX_STATE_DEPTH_TEST_SHIFT; - - desc.depthWriteEnabled = !!(BGFX_STATE_WRITE_Z & _state); - desc.depthCompare = s_cmpFunc[func]; - - uint32_t bstencil = unpackStencil(1, _stencil); - const uint32_t frontAndBack = bstencil != BGFX_STENCIL_NONE && bstencil != fstencil; - bstencil = frontAndBack ? bstencil : fstencil; - - desc.stencilFront = defaultDescriptor(); - desc.stencilBack = defaultDescriptor(); - - if (0 != _stencil) - { - // TODO (hugoam) - const uint32_t readMask = (fstencil&BGFX_STENCIL_FUNC_RMASK_MASK)>>BGFX_STENCIL_FUNC_RMASK_SHIFT; - const uint32_t writeMask = 0xff; - - desc.stencilReadMask = readMask; - desc.stencilWriteMask = writeMask; - - desc.stencilFront.failOp = s_stencilOp[(fstencil&BGFX_STENCIL_OP_FAIL_S_MASK)>>BGFX_STENCIL_OP_FAIL_S_SHIFT]; - desc.stencilFront.depthFailOp = s_stencilOp[(fstencil&BGFX_STENCIL_OP_FAIL_Z_MASK)>>BGFX_STENCIL_OP_FAIL_Z_SHIFT]; - desc.stencilFront.passOp = s_stencilOp[(fstencil&BGFX_STENCIL_OP_PASS_Z_MASK)>>BGFX_STENCIL_OP_PASS_Z_SHIFT]; - desc.stencilFront.compare = s_cmpFunc[(fstencil&BGFX_STENCIL_TEST_MASK)>>BGFX_STENCIL_TEST_SHIFT]; - - desc.stencilBack.failOp = s_stencilOp[(bstencil&BGFX_STENCIL_OP_FAIL_S_MASK)>>BGFX_STENCIL_OP_FAIL_S_SHIFT]; - desc.stencilBack.depthFailOp = s_stencilOp[(bstencil&BGFX_STENCIL_OP_FAIL_Z_MASK)>>BGFX_STENCIL_OP_FAIL_Z_SHIFT]; - desc.stencilBack.passOp = s_stencilOp[(bstencil&BGFX_STENCIL_OP_PASS_Z_MASK)>>BGFX_STENCIL_OP_PASS_Z_SHIFT]; - desc.stencilBack.compare = s_cmpFunc[(bstencil&BGFX_STENCIL_TEST_MASK)>>BGFX_STENCIL_TEST_SHIFT]; - } - } - - RenderPassStateWgpu* getRenderPassState(bgfx::FrameBufferHandle fbh, bool clear, Clear clr) - { - bx::HashMurmur2A murmur; - murmur.begin(); - murmur.add(fbh.idx); - murmur.add(clear); - murmur.add(&clr, sizeof(clr)); - uint32_t hash = murmur.end(); - - RenderPassStateWgpu* rps = m_renderPassStateCache.find(hash); - - if (NULL == rps) - { - rps = BX_NEW(g_allocator, RenderPassStateWgpu); - m_renderPassStateCache.add(hash, rps); - } - - return rps; - } - - PipelineStateWgpu* getPipelineState( - uint64_t _state - , uint64_t _stencil - , uint32_t _rgba - , FrameBufferHandle _fbh - , uint8_t _numStreams - , const VertexLayout** _vertexDecls - , bool _index32 - , ProgramHandle _program - , uint8_t _numInstanceData - ) - { - _state &= 0 - | BGFX_STATE_WRITE_RGB - | BGFX_STATE_WRITE_A - | BGFX_STATE_WRITE_Z - | BGFX_STATE_DEPTH_TEST_MASK - | BGFX_STATE_BLEND_MASK - | BGFX_STATE_BLEND_EQUATION_MASK - | BGFX_STATE_BLEND_INDEPENDENT - | BGFX_STATE_BLEND_ALPHA_TO_COVERAGE - | BGFX_STATE_CULL_MASK - | BGFX_STATE_MSAA - | BGFX_STATE_LINEAA - | BGFX_STATE_CONSERVATIVE_RASTER - | BGFX_STATE_PT_MASK - ; - - const bool independentBlendEnable = !!(BGFX_STATE_BLEND_INDEPENDENT & _state); - const ProgramWgpu& program = m_program[_program.idx]; - - bx::HashMurmur2A murmur; - murmur.begin(); - murmur.add(_state); - murmur.add(_stencil); - murmur.add(independentBlendEnable ? _rgba : 0); - murmur.add(_numInstanceData); - - FrameBufferWgpu& frameBuffer = !isValid(_fbh) ? m_mainFrameBuffer : m_frameBuffers[_fbh.idx]; - murmur.add(frameBuffer.m_pixelFormatHash); - - murmur.add(program.m_vsh->m_hash); - if (NULL != program.m_fsh) - { - murmur.add(program.m_fsh->m_hash); - } - - for (uint8_t ii = 0; ii < _numStreams; ++ii) - { - murmur.add(_vertexDecls[ii]->m_hash); - } - - uint32_t hash = murmur.end(); - - PipelineStateWgpu* pso = m_pipelineStateCache.find(hash); - - if (NULL == pso) - { - pso = BX_NEW(g_allocator, PipelineStateWgpu); - - //pd.alphaToCoverageEnabled = !!(BGFX_STATE_BLEND_ALPHA_TO_COVERAGE & _state); - - RenderPipelineDescriptor& pd = pso->m_rpd; - - uint32_t frameBufferAttachment = 1; - uint32_t sampleCount = 1; - - if (!isValid(_fbh) - || s_renderWgpu->m_frameBuffers[_fbh.idx].m_swapChain) - { - SwapChainWgpu& swapChain = !isValid(_fbh) - ? *s_renderWgpu->m_mainFrameBuffer.m_swapChain - : *s_renderWgpu->m_frameBuffers[_fbh.idx].m_swapChain - ; - sampleCount = swapChain.m_backBufferColorMsaa - ? swapChain.m_sampleCount - : 1 - ; - pd.colorStates[0].format = swapChain.m_colorFormat; - pd.depthStencilState.format = swapChain.m_depthFormat; - pd.desc.depthStencilState = &pd.depthStencilState; - } - else - { - frameBufferAttachment = frameBuffer.m_num; - - for (uint32_t ii = 0; ii < frameBuffer.m_num; ++ii) - { - const TextureWgpu& texture = m_textures[frameBuffer.m_colorHandle[ii].idx]; - sampleCount = texture.m_ptrMsaa - ? texture.m_sampleCount - : 1 - ; - pd.colorStates[ii].format = s_textureFormat[texture.m_textureFormat].m_fmt; - } - - pd.desc.colorStateCount = frameBuffer.m_num; - - if (isValid(frameBuffer.m_depthHandle) ) - { - const TextureWgpu& texture = m_textures[frameBuffer.m_depthHandle.idx]; - pd.depthStencilState.format = s_textureFormat[texture.m_textureFormat].m_fmt; - pd.desc.depthStencilState = &pd.depthStencilState; - } - } - - const uint32_t blend = uint32_t( (_state&BGFX_STATE_BLEND_MASK )>>BGFX_STATE_BLEND_SHIFT); - const uint32_t equation = uint32_t( (_state&BGFX_STATE_BLEND_EQUATION_MASK)>>BGFX_STATE_BLEND_EQUATION_SHIFT); - - const uint32_t srcRGB = (blend )&0xf; - const uint32_t dstRGB = (blend>> 4)&0xf; - const uint32_t srcA = (blend>> 8)&0xf; - const uint32_t dstA = (blend>>12)&0xf; - - const uint32_t equRGB = (equation )&0x7; - const uint32_t equA = (equation>>3)&0x7; - - wgpu::ColorWriteMask writeMask = wgpu::ColorWriteMask::None; - writeMask |= (_state&BGFX_STATE_WRITE_R) ? wgpu::ColorWriteMask::Red : wgpu::ColorWriteMask::None; - writeMask |= (_state&BGFX_STATE_WRITE_G) ? wgpu::ColorWriteMask::Green : wgpu::ColorWriteMask::None; - writeMask |= (_state&BGFX_STATE_WRITE_B) ? wgpu::ColorWriteMask::Blue : wgpu::ColorWriteMask::None; - writeMask |= (_state&BGFX_STATE_WRITE_A) ? wgpu::ColorWriteMask::Alpha : wgpu::ColorWriteMask::None; - - for (uint32_t ii = 0; ii < (independentBlendEnable ? 1 : frameBufferAttachment); ++ii) - { - wgpu::ColorStateDescriptor& drt = pd.colorStates[ii]; // = pd.colorAttachments[ii]; - - if(!(BGFX_STATE_BLEND_MASK & _state)) - { - drt.colorBlend = defaultDescriptor(); - drt.alphaBlend = defaultDescriptor(); - } - else - { - drt.colorBlend.srcFactor = s_blendFactor[srcRGB][0]; - drt.colorBlend.dstFactor = s_blendFactor[dstRGB][0]; - drt.colorBlend.operation = s_blendEquation[equRGB]; - - drt.alphaBlend.srcFactor = s_blendFactor[srcA][1]; - drt.alphaBlend.dstFactor = s_blendFactor[dstA][1]; - drt.alphaBlend.operation = s_blendEquation[equA]; - } - - drt.writeMask = writeMask; - } - - if (independentBlendEnable) - { - for (uint32_t ii = 1, rgba = _rgba; ii < frameBufferAttachment; ++ii, rgba >>= 11) - { - wgpu::ColorStateDescriptor drt = pd.colorStates[ii]; // = pd.colorAttachments[ii]; - - //drt.blendingEnabled = 0 != (rgba&0x7ff); - - const uint32_t src = (rgba )&0xf; - const uint32_t dst = (rgba>>4)&0xf; - const uint32_t equationIndex = (rgba>>8)&0x7; - - drt.colorBlend.srcFactor = s_blendFactor[src][0]; - drt.colorBlend.dstFactor = s_blendFactor[dst][0]; - drt.colorBlend.operation = s_blendEquation[equationIndex]; - - drt.alphaBlend.srcFactor = s_blendFactor[src][1]; - drt.alphaBlend.dstFactor = s_blendFactor[dst][1]; - drt.alphaBlend.operation = s_blendEquation[equationIndex]; - - drt.writeMask = writeMask; - } - } - - pd.desc.vertexStage.module = program.m_vsh->m_module; - pd.fragmentStage.module = program.m_fsh != NULL ? program.m_fsh->m_module : wgpu::ShaderModule(); - - setDepthStencilState(pd.depthStencilState, _state, _stencil); - - const uint64_t cull = _state & BGFX_STATE_CULL_MASK; - const uint8_t cullIndex = uint8_t(cull >> BGFX_STATE_CULL_SHIFT); - pd.rasterizationState.cullMode = s_cullMode[cullIndex]; - - pd.rasterizationState.frontFace = (_state & BGFX_STATE_FRONT_CCW) ? wgpu::FrontFace::CCW : wgpu::FrontFace::CW; - - // pd.desc = m_renderPipelineDescriptor; - pd.desc.sampleCount = sampleCount; - - wgpu::PipelineLayoutDescriptor layout = defaultDescriptor(); - layout.bindGroupLayouts = &program.m_bindGroupLayout; - layout.bindGroupLayoutCount = 1; - - pd.desc.layout = m_device.CreatePipelineLayout(&layout); - // TODO (hugoam) this should be cached too ? - - //uint32_t ref = (_state&BGFX_STATE_ALPHA_REF_MASK) >> BGFX_STATE_ALPHA_REF_SHIFT; - //viewState.m_alphaRef = ref / 255.0f; - - const uint64_t primType = _state & BGFX_STATE_PT_MASK; - uint8_t primIndex = uint8_t(primType >> BGFX_STATE_PT_SHIFT); - - PrimInfo prim = s_primInfo[primIndex]; - pd.desc.primitiveTopology = prim.m_type; - - VertexStateDescriptor input; - input.desc.vertexBufferCount = 0; - - wgpu::VertexBufferLayoutDescriptor* inputBinding = input.vertexBuffers; - wgpu::VertexAttributeDescriptor* inputAttrib = input.attributes; - - auto fillVertexDecl = [&](const ShaderWgpu* _vsh, const VertexLayout& _decl) - { - input.desc.vertexBufferCount += 1; - - inputBinding->arrayStride = _decl.m_stride; - inputBinding->stepMode = wgpu::InputStepMode::Vertex; - inputBinding->attributes = inputAttrib; - - uint32_t numAttribs = 0; - - for(uint32_t attr = 0; attr < Attrib::Count; ++attr) - { - if(UINT16_MAX != _decl.m_attributes[attr]) - { - if(UINT8_MAX == _vsh->m_attrRemap[attr]) - continue; - - inputAttrib->shaderLocation = _vsh->m_attrRemap[attr]; - - if(0 == _decl.m_attributes[attr]) - { - inputAttrib->format = wgpu::VertexFormat::Float3; - inputAttrib->offset = 0; - } - else - { - uint8_t num; - AttribType::Enum type; - bool normalized; - bool asInt; - _decl.decode(Attrib::Enum(attr), num, type, normalized, asInt); - inputAttrib->format = s_attribType[type][num-1][normalized]; - inputAttrib->offset = _decl.m_offset[attr]; - } - - ++inputAttrib; - ++numAttribs; - } - } - - inputBinding->attributeCount = numAttribs; - inputBinding++; - - return numAttribs; - }; - - //bool attrSet[Attrib::Count] = {}; - - uint16_t unsettedAttr[Attrib::Count]; - bx::memCopy(unsettedAttr, program.m_vsh->m_attrMask, sizeof(uint16_t) * Attrib::Count); - - uint8_t stream = 0; - for (; stream < _numStreams; ++stream) - { - VertexLayout layout; - bx::memCopy(&layout, _vertexDecls[stream], sizeof(VertexLayout)); - const uint16_t* attrMask = program.m_vsh->m_attrMask; - - for (uint32_t ii = 0; ii < Attrib::Count; ++ii) - { - Attrib::Enum iiattr = Attrib::Enum(ii); - uint16_t mask = attrMask[ii]; - uint16_t attr = (layout.m_attributes[ii] & mask); - if (attr == 0) - { - layout.m_attributes[ii] = UINT16_MAX; - } - if (unsettedAttr[ii] && attr != UINT16_MAX) - { - unsettedAttr[ii] = 0; - } - } - - fillVertexDecl(program.m_vsh, layout); - } - - for (uint32_t ii = 0; ii < Attrib::Count; ++ii) - { - Attrib::Enum iiattr = Attrib::Enum(ii); - if (0 < unsettedAttr[ii]) - { - //uint32_t numAttribs = input.vertexBuffers[stream].attributeCount; - //uint32_t numAttribs = inputBinding->attributeCount; - //wgpu::VertexBufferLayoutDescriptor* inputAttrib = const_cast(_vertexInputState.pVertexAttributeDescriptions + numAttribs); - inputAttrib->shaderLocation = program.m_vsh->m_attrRemap[ii]; - //inputAttrib->binding = 0; - inputAttrib->format = wgpu::VertexFormat::Float3; // VK_FORMAT_R32G32B32_SFLOAT; - inputAttrib->offset = 0; - input.vertexBuffers[stream-1].attributeCount++; - ++inputAttrib; - } - } - - // TODO (hugoam) WebGPU will crash whenever we are not supplying the correct number of attributes (which depends on the stride passed to bgfx::allocInstanceDataBuffer) - // so we need to know the number of live instance attributes in the shader and if they aren't all supplied: - // - fail the pipeline state creation - // - bind dummy attributes - if (0 < _numInstanceData) - { - uint32_t numBindings = input.desc.vertexBufferCount; // == stream+1 // .vertexBindingDescriptionCount; - uint32_t firstAttrib = input.vertexBuffers[stream-1].attributeCount; - uint32_t numAttribs = firstAttrib; - - inputBinding->arrayStride = _numInstanceData * 16; - inputBinding->stepMode = wgpu::InputStepMode::Instance; - - for (uint32_t inst = 0; inst < _numInstanceData; ++inst) - { - inputAttrib->shaderLocation = numAttribs; - inputAttrib->format = wgpu::VertexFormat::Float4; - inputAttrib->offset = inst * 16; - - ++numAttribs; - ++inputAttrib; - } - - input.desc.vertexBufferCount = numBindings + 1; - input.vertexBuffers[stream].attributeCount = numAttribs - firstAttrib; - input.vertexBuffers[stream].attributes = &input.attributes[firstAttrib]; - } - - - input.desc.indexFormat = _index32 ? wgpu::IndexFormat::Uint32 : wgpu::IndexFormat::Uint16; - - pd.desc.vertexState = &input.desc; - - BX_TRACE("Creating WebGPU render pipeline state for program %s", program.m_vsh->name()); - pso->m_rps = m_device.CreateRenderPipeline(&pd.desc); - - m_pipelineStateCache.add(hash, pso); - } - - return pso; - } - - PipelineStateWgpu* getPipelineState( - uint64_t _state - , uint64_t _stencil - , uint32_t _rgba - , FrameBufferHandle _fbh - , VertexLayoutHandle _declHandle - , bool _index32 - , ProgramHandle _program - , uint8_t _numInstanceData - ) - { - const VertexLayout* decl = &m_vertexDecls[_declHandle.idx]; - return getPipelineState( - _state - , _stencil - , _rgba - , _fbh - , 1 - , &decl - , _index32 - , _program - , _numInstanceData - ); - } - - PipelineStateWgpu* getComputePipelineState(ProgramHandle _program) - { - ProgramWgpu& program = m_program[_program.idx]; - - if (NULL == program.m_computePS) - { - PipelineStateWgpu* pso = BX_NEW(g_allocator, PipelineStateWgpu); - program.m_computePS = pso; - - wgpu::PipelineLayoutDescriptor layout = defaultDescriptor(); - layout.bindGroupLayouts = &program.m_bindGroupLayout; - layout.bindGroupLayoutCount = 1; - - pso->m_layout = m_device.CreatePipelineLayout(&layout); - - wgpu::ComputePipelineDescriptor desc; - desc.layout = pso->m_layout; - desc.computeStage = { nullptr, program.m_vsh->m_module, "main" }; - - pso->m_cps = m_device.CreateComputePipeline(&desc); - } - - return program.m_computePS; - } - - - wgpu::Sampler getSamplerState(uint32_t _flags) - { - _flags &= BGFX_SAMPLER_BITS_MASK; - SamplerStateWgpu* sampler = m_samplerStateCache.find(_flags); - - if (NULL == sampler) - { - sampler = BX_NEW(g_allocator, SamplerStateWgpu); - - wgpu::SamplerDescriptor desc; - desc.addressModeU = s_textureAddress[(_flags&BGFX_SAMPLER_U_MASK)>>BGFX_SAMPLER_U_SHIFT]; - desc.addressModeV = s_textureAddress[(_flags&BGFX_SAMPLER_V_MASK)>>BGFX_SAMPLER_V_SHIFT]; - desc.addressModeW = s_textureAddress[(_flags&BGFX_SAMPLER_W_MASK)>>BGFX_SAMPLER_W_SHIFT]; - desc.minFilter = s_textureFilterMinMag[(_flags&BGFX_SAMPLER_MIN_MASK)>>BGFX_SAMPLER_MIN_SHIFT]; - desc.magFilter = s_textureFilterMinMag[(_flags&BGFX_SAMPLER_MAG_MASK)>>BGFX_SAMPLER_MAG_SHIFT]; - desc.mipmapFilter = s_textureFilterMip[(_flags&BGFX_SAMPLER_MIP_MASK)>>BGFX_SAMPLER_MIP_SHIFT]; - desc.lodMinClamp = 0; - desc.lodMaxClamp = FLT_MAX; - - const uint32_t cmpFunc = (_flags&BGFX_SAMPLER_COMPARE_MASK)>>BGFX_SAMPLER_COMPARE_SHIFT; - desc.compare = 0 == cmpFunc - ? wgpu::CompareFunction::Undefined - : s_cmpFunc[cmpFunc] - ; - - sampler->m_sampler = s_renderWgpu->m_device.CreateSampler(&desc); - m_samplerStateCache.add(_flags, sampler); - } - - return sampler->m_sampler; - } - - wgpu::CommandEncoder& getBlitCommandEncoder() - { - if (!m_cmd.m_encoder) - m_cmd.begin(); - - if (m_renderEncoder || m_computeEncoder) - endEncoding(); - - return m_cmd.m_encoder; - } - - wgpu::RenderPassEncoder renderPass(bgfx::Frame* _render, bgfx::FrameBufferHandle fbh, bool clear, Clear clr, const char* name = NULL) - { - RenderPassStateWgpu* rps = s_renderWgpu->getRenderPassState(fbh, clear, clr); - - RenderPassDescriptor& renderPassDescriptor = rps->m_rpd; - renderPassDescriptor.desc.label = name; - - setFrameBuffer(renderPassDescriptor, fbh); - - if(clear) - { - for(uint32_t ii = 0; ii < g_caps.limits.maxFBAttachments; ++ii) - { - wgpu::RenderPassColorAttachmentDescriptor& color = renderPassDescriptor.colorAttachments[ii]; - - if(0 != (BGFX_CLEAR_COLOR & clr.m_flags)) - { - if(0 != (BGFX_CLEAR_COLOR_USE_PALETTE & clr.m_flags)) - { - uint8_t index = (uint8_t)bx::uint32_min(BGFX_CONFIG_MAX_COLOR_PALETTE - 1, clr.m_index[ii]); - const float* rgba = _render->m_colorPalette[index]; - const float rr = rgba[0]; - const float gg = rgba[1]; - const float bb = rgba[2]; - const float aa = rgba[3]; - color.clearColor = { rr, gg, bb, aa }; - } - else - { - float rr = clr.m_index[0] * 1.0f / 255.0f; - float gg = clr.m_index[1] * 1.0f / 255.0f; - float bb = clr.m_index[2] * 1.0f / 255.0f; - float aa = clr.m_index[3] * 1.0f / 255.0f; - color.clearColor = { rr, gg, bb, aa }; - } - - color.loadOp = wgpu::LoadOp::Clear; - } - else - { - color.loadOp = wgpu::LoadOp::Load; - } - - //desc.storeOp = desc.attachment.sampleCount > 1 ? wgpu::StoreOp::MultisampleResolve : wgpu::StoreOp::Store; - color.storeOp = wgpu::StoreOp::Store; - } - - wgpu::RenderPassDepthStencilAttachmentDescriptor& depthStencil = renderPassDescriptor.depthStencilAttachment; - - if(depthStencil.attachment) - { - depthStencil.clearDepth = clr.m_depth; - depthStencil.depthLoadOp = 0 != (BGFX_CLEAR_DEPTH & clr.m_flags) - ? wgpu::LoadOp::Clear - : wgpu::LoadOp::Load - ; - depthStencil.depthStoreOp = m_mainFrameBuffer.m_swapChain->m_backBufferColorMsaa - ? wgpu::StoreOp(0) //wgpu::StoreOp::DontCare - : wgpu::StoreOp::Store - ; - - depthStencil.clearStencil = clr.m_stencil; - depthStencil.stencilLoadOp = 0 != (BGFX_CLEAR_STENCIL & clr.m_flags) - ? wgpu::LoadOp::Clear - : wgpu::LoadOp::Load - ; - depthStencil.stencilStoreOp = m_mainFrameBuffer.m_swapChain->m_backBufferColorMsaa - ? wgpu::StoreOp(0) //wgpu::StoreOp::DontCare - : wgpu::StoreOp::Store - ; - } - } - else - { - for(uint32_t ii = 0; ii < g_caps.limits.maxFBAttachments; ++ii) - { - wgpu::RenderPassColorAttachmentDescriptor& color = renderPassDescriptor.colorAttachments[ii]; - if(color.attachment) - { - color.loadOp = wgpu::LoadOp::Load; - } - } - - wgpu::RenderPassDepthStencilAttachmentDescriptor& depthStencil = renderPassDescriptor.depthStencilAttachment; - - if(depthStencil.attachment) - { - depthStencil.depthLoadOp = wgpu::LoadOp::Load; - depthStencil.depthStoreOp = wgpu::StoreOp::Store; - - depthStencil.stencilLoadOp = wgpu::LoadOp::Load; - depthStencil.stencilStoreOp = wgpu::StoreOp::Store; - } - } - - wgpu::RenderPassEncoder rce = m_cmd.m_encoder.BeginRenderPass(&renderPassDescriptor.desc); - m_renderEncoder = rce; - return rce; - } - - void endEncoding() - { - if (m_renderEncoder) - { - m_renderEncoder.EndPass(); - m_renderEncoder = nullptr; - } - - if (m_computeEncoder) - { - m_computeEncoder.EndPass(); - m_computeEncoder = nullptr; - } - } - - void* m_renderDocDll; - -#if !BX_PLATFORM_EMSCRIPTEN - dawn_native::Instance m_instance; -#endif - wgpu::Device m_device; - wgpu::Queue m_queue; - TimerQueryWgpu m_gpuTimer; - CommandQueueWgpu m_cmd; - - ScratchBufferWgpu m_scratchBuffers[WEBGPU_MAX_FRAMES_IN_FLIGHT]; - - BindStateCacheWgpu m_bindStateCache[WEBGPU_MAX_FRAMES_IN_FLIGHT]; - - uint8_t m_frameIndex; - - uint16_t m_numWindows; - FrameBufferHandle m_windows[BGFX_CONFIG_MAX_FRAME_BUFFERS]; - - IndexBufferWgpu m_indexBuffers[BGFX_CONFIG_MAX_INDEX_BUFFERS]; - VertexBufferWgpu m_vertexBuffers[BGFX_CONFIG_MAX_VERTEX_BUFFERS]; - ShaderWgpu m_shaders[BGFX_CONFIG_MAX_SHADERS]; - ProgramWgpu m_program[BGFX_CONFIG_MAX_PROGRAMS]; - TextureWgpu m_textures[BGFX_CONFIG_MAX_TEXTURES]; - ReadbackWgpu m_readbacks[BGFX_CONFIG_MAX_TEXTURES]; - FrameBufferWgpu m_mainFrameBuffer; - FrameBufferWgpu m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS]; - VertexLayout m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_LAYOUTS]; - UniformRegistry m_uniformReg; - void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; - - //StateCacheT m_bindStateCache; - StateCacheT m_renderPassStateCache; - StateCacheT m_pipelineStateCache; - StateCacheT m_samplerStateCache; - - TextVideoMem m_textVideoMem; - - uint8_t m_fsScratch[64 << 10]; - uint8_t m_vsScratch[64 << 10]; - - FrameBufferHandle m_fbh; - bool m_rtMsaa; - - Resolution m_resolution; - void* m_capture; - uint32_t m_captureSize; - - wgpu::RenderPassEncoder m_renderEncoder; - wgpu::ComputePassEncoder m_computeEncoder; - }; - - RendererContextI* rendererCreate(const Init& _init) - { - s_renderWgpu = BX_NEW(g_allocator, RendererContextWgpu); - if (!s_renderWgpu->init(_init) ) - { - BX_DELETE(g_allocator, s_renderWgpu); - s_renderWgpu = NULL; - } - return s_renderWgpu; - } - - void rendererDestroy() - { - s_renderWgpu->shutdown(); - BX_DELETE(g_allocator, s_renderWgpu); - s_renderWgpu = NULL; - } - - void writeString(bx::WriterI* _writer, const char* _str) - { - bx::write(_writer, _str, (int32_t)bx::strLen(_str) ); - } - - void ShaderWgpu::create(ShaderHandle _handle, const Memory* _mem) - { - m_handle = _handle; - - BX_TRACE("Creating shader %s", getName(_handle)); - - bx::MemoryReader reader(_mem->data, _mem->size); - - uint32_t magic; - bx::read(&reader, magic); - - wgpu::ShaderStage shaderStage; - - if (isShaderType(magic, 'C')) - { - shaderStage = wgpu::ShaderStage::Compute; - } - else if (isShaderType(magic, 'F')) - { - shaderStage = wgpu::ShaderStage::Fragment; - } - else if (isShaderType(magic, 'G')) - { - //shaderStage = wgpu::ShaderStage::Geometry; - } - else if (isShaderType(magic, 'V')) - { - shaderStage = wgpu::ShaderStage::Vertex; - } - - m_stage = shaderStage; - - uint32_t hashIn; - bx::read(&reader, hashIn); - - uint32_t hashOut; - - if (isShaderVerLess(magic, 6) ) - { - hashOut = hashIn; - } - else - { - bx::read(&reader, hashOut); - } - - uint16_t count; - bx::read(&reader, count); - - m_numPredefined = 0; - m_numUniforms = count; - - BX_TRACE("%s Shader consts %d" - , getShaderTypeName(magic) - , count - ); - - const bool fragment = isShaderType(magic, 'F'); - uint8_t fragmentBit = fragment ? BGFX_UNIFORM_FRAGMENTBIT : 0; - - BX_CHECK(!isShaderVerLess(magic, 7), "WebGPU backend supports only shader binary version >= 7"); - - if (0 < count) - { - for (uint32_t ii = 0; ii < count; ++ii) - { - uint8_t nameSize = 0; - bx::read(&reader, nameSize); - - char name[256]; - bx::read(&reader, &name, nameSize); - name[nameSize] = '\0'; - - uint8_t type = 0; - bx::read(&reader, type); - - uint8_t num; - bx::read(&reader, num); - - uint16_t regIndex; - bx::read(&reader, regIndex); - - uint16_t regCount; - bx::read(&reader, regCount); - - uint8_t texComponent; - bx::read(&reader, texComponent); - - uint8_t texDimension; - bx::read(&reader, texDimension); - - const char* kind = "invalid"; - - PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name); - if (PredefinedUniform::Count != predefined) - { - kind = "predefined"; - m_predefined[m_numPredefined].m_loc = regIndex; - m_predefined[m_numPredefined].m_count = regCount; - m_predefined[m_numPredefined].m_type = uint8_t(predefined|fragmentBit); - m_numPredefined++; - } - else if (UniformType::End == (~BGFX_UNIFORM_MASK & type)) - { - // regCount is used for descriptor type - const bool buffer = regCount == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - const bool readonly = (type & BGFX_UNIFORM_READONLYBIT) != 0; - - const uint8_t stage = regIndex - (buffer ? 16 : 32) - (fragment ? 48 : 0); - - m_bindInfo[stage].m_index = m_numBuffers; - m_bindInfo[stage].m_binding = regIndex; - m_bindInfo[stage].m_uniform = { 0 }; - - m_buffers[m_numBuffers] = wgpu::BindGroupLayoutBinding(); - m_buffers[m_numBuffers].binding = regIndex; - m_buffers[m_numBuffers].visibility = shaderStage; - - if (buffer) - { - m_buffers[m_numBuffers].type = readonly - ? wgpu::BindingType::ReadonlyStorageBuffer - : wgpu::BindingType::StorageBuffer; - } - else - { - m_buffers[m_numBuffers].type = readonly - ? wgpu::BindingType::ReadonlyStorageTexture - : wgpu::BindingType::WriteonlyStorageTexture; - } - - m_numBuffers++; - - kind = "storage"; - } - else if (UniformType::Sampler == (~BGFX_UNIFORM_MASK & type)) - { - const UniformRegInfo* info = s_renderWgpu->m_uniformReg.find(name); - BX_CHECK(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name); - - const uint8_t stage = regIndex - 16 - (fragment ? 48 : 0); - - m_bindInfo[stage].m_index = m_numSamplers; - m_bindInfo[stage].m_binding = regIndex; - m_bindInfo[stage].m_uniform = info->m_handle; - - m_textures[m_numSamplers] = wgpu::BindGroupLayoutBinding(); - m_textures[m_numSamplers].binding = regIndex; - m_textures[m_numSamplers].visibility = shaderStage; - m_textures[m_numSamplers].type = wgpu::BindingType::SampledTexture; - m_textures[m_numSamplers].viewDimension = wgpu::TextureViewDimension(texDimension); - m_textures[m_numSamplers].textureComponentType = wgpu::TextureComponentType(texComponent); - - const bool comparisonSampler = (type & BGFX_UNIFORM_COMPAREBIT) != 0; - - m_samplers[m_numSamplers] = wgpu::BindGroupLayoutBinding(); - m_samplers[m_numSamplers].binding = regIndex + 16; - m_samplers[m_numSamplers].visibility = shaderStage; - m_samplers[m_numSamplers].type = comparisonSampler - ? wgpu::BindingType::ComparisonSampler - : wgpu::BindingType::Sampler; - - m_numSamplers++; - - kind = "sampler"; - } - else - { - const UniformRegInfo* info = s_renderWgpu->m_uniformReg.find(name); - BX_CHECK(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name); - - if(NULL == m_constantBuffer) - { - m_constantBuffer = UniformBuffer::create(1024); - } - - kind = "user"; - m_constantBuffer->writeUniformHandle((UniformType::Enum)(type | fragmentBit), regIndex, info->m_handle, regCount); - } - - BX_TRACE("\t%s: %s (%s), r.index %3d, r.count %2d" - , kind - , name - , getUniformTypeName(UniformType::Enum(type&~BGFX_UNIFORM_MASK) ) - , regIndex - , regCount - ); - BX_UNUSED(kind); - } - - if (NULL != m_constantBuffer) - { - m_constantBuffer->finish(); - } - } - - uint32_t shaderSize; - bx::read(&reader, shaderSize); - - BX_TRACE("Shader body is at %lld size %u remaining %lld", reader.getPos(), shaderSize, reader.remaining()); - - const uint32_t* code = (const uint32_t*)reader.getDataPtr(); - bx::skip(&reader, shaderSize+1); - - m_code = (uint32_t*)BX_ALLOC(g_allocator, shaderSize); - m_codeSize = shaderSize; - - bx::memCopy(m_code, code, shaderSize); - // TODO (hugoam) delete this - - BX_TRACE("First word %08" PRIx32, code[0]); - - uint8_t numAttrs = 0; - bx::read(&reader, numAttrs); - - m_numAttrs = numAttrs; - - bx::memSet(m_attrMask, 0, sizeof(m_attrMask)); - bx::memSet(m_attrRemap, UINT8_MAX, sizeof(m_attrRemap)); - - for(uint8_t ii = 0; ii < numAttrs; ++ii) - { - uint16_t id; - bx::read(&reader, id); - - auto toString = [](Attrib::Enum attr) - { - if (attr == Attrib::Position) return "Position"; - else if (attr == Attrib::Normal) return "Normal"; - else if (attr == Attrib::Tangent) return "Tangent"; - else if (attr == Attrib::Bitangent) return "Bitangent"; - else if (attr == Attrib::Color0) return "Color0"; - else if (attr == Attrib::Color1) return "Color1"; - else if (attr == Attrib::Color2) return "Color2"; - else if (attr == Attrib::Color3) return "Color3"; - else if (attr == Attrib::Indices) return "Indices"; - else if (attr == Attrib::Weight) return "Weight"; - else if (attr == Attrib::TexCoord0) return "TexCoord0"; - else if (attr == Attrib::TexCoord1) return "TexCoord1"; - else if (attr == Attrib::TexCoord2) return "TexCoord2"; - else if (attr == Attrib::TexCoord3) return "TexCoord3"; - else if (attr == Attrib::TexCoord4) return "TexCoord4"; - else if (attr == Attrib::TexCoord5) return "TexCoord5"; - else if (attr == Attrib::TexCoord6) return "TexCoord6"; - else if (attr == Attrib::TexCoord7) return "TexCoord7"; - return "Invalid"; - }; - - Attrib::Enum attr = idToAttrib(id); - - if(Attrib::Count != attr) - { - m_attrMask[attr] = UINT16_MAX; - m_attrRemap[attr] = ii; - BX_TRACE("\tattrib: %s (%i) at index %i", toString(attr), attr, ii); - } - } - - wgpu::ShaderModuleDescriptor desc; - desc.label = getName(_handle); - desc.code = m_code; - desc.codeSize = shaderSize/4; - - m_module = s_renderWgpu->m_device.CreateShaderModule(&desc); - - BGFX_FATAL(m_module - , bgfx::Fatal::InvalidShader - , "Failed to create %s shader." - , getShaderTypeName(magic) - ); - - bx::HashMurmur2A murmur; - murmur.begin(); - murmur.add(hashIn); - murmur.add(hashOut); - murmur.add(code, shaderSize); - murmur.add(numAttrs); - murmur.add(m_attrMask, numAttrs); - m_hash = murmur.end(); - - auto roundUp = [](auto value, auto multiple) - { - return ((value + multiple - 1) / multiple) * multiple; - }; - - bx::read(&reader, m_size); - - const uint32_t align = kMinUniformBufferOffsetAlignment; - m_gpuSize = bx::strideAlign(m_size, align); - - BX_TRACE("shader size %d (used=%d) (prev=%d)", (int)m_size, (int)m_gpuSize, (int)bx::strideAlign(roundUp(m_size, 4), align)); - } - - void ProgramWgpu::create(const ShaderWgpu* _vsh, const ShaderWgpu* _fsh) - { - BX_CHECK(_vsh->m_module, "Vertex shader doesn't exist."); - m_vsh = _vsh; - m_fsh = _fsh; - m_gpuSize = _vsh->m_gpuSize + (_fsh ? _fsh->m_gpuSize : 0); - - //BX_CHECK(NULL != _vsh->m_code, "Vertex shader doesn't exist."); - m_vsh = _vsh; - bx::memCopy(&m_predefined[0], _vsh->m_predefined, _vsh->m_numPredefined * sizeof(PredefinedUniform)); - m_numPredefined = _vsh->m_numPredefined; - - if(NULL != _fsh) - { - //BX_CHECK(NULL != _fsh->m_code, "Fragment shader doesn't exist."); - m_fsh = _fsh; - bx::memCopy(&m_predefined[m_numPredefined], _fsh->m_predefined, _fsh->m_numPredefined * sizeof(PredefinedUniform)); - m_numPredefined += _fsh->m_numPredefined; - } - - wgpu::BindGroupLayoutEntry bindings[2 + BGFX_CONFIG_MAX_TEXTURE_SAMPLERS * 3]; - - m_numUniforms = 0 + (_vsh->m_size > 0 ? 1 : 0) + (NULL != _fsh && _fsh->m_size > 0 ? 1 : 0); - - uint8_t numBindings = 0; - - // bind uniform buffer at slot 0 - bindings[numBindings].binding = 0; - bindings[numBindings].visibility = _vsh->m_stage; - bindings[numBindings].type = wgpu::BindingType::UniformBuffer; - bindings[numBindings].hasDynamicOffset = true; - numBindings++; - - if (m_numUniforms > 1) - { - bindings[numBindings].binding = 48; - bindings[numBindings].visibility = wgpu::ShaderStage::Fragment; - bindings[numBindings].type = wgpu::BindingType::UniformBuffer; - bindings[numBindings].hasDynamicOffset = true; - numBindings++; - } - - uint8_t numSamplers = 0; - - for (uint32_t ii = 0; ii < _vsh->m_numSamplers; ++ii) - { - m_textures[ii] = _vsh->m_textures[ii]; - m_samplers[ii] = _vsh->m_samplers[ii]; - bindings[numBindings++] = _vsh->m_textures[ii]; - bindings[numBindings++] = _vsh->m_samplers[ii]; - } - - numSamplers += _vsh->m_numSamplers; - - if (NULL != _fsh) - { - for (uint32_t ii = 0; ii < _fsh->m_numSamplers; ++ii) - { - m_textures[numSamplers + ii] = _fsh->m_textures[ii]; - m_samplers[numSamplers + ii] = _fsh->m_samplers[ii]; - bindings[numBindings++] = _fsh->m_textures[ii]; - bindings[numBindings++] = _fsh->m_samplers[ii]; - } - - numSamplers += _fsh->m_numSamplers; - } - - for (uint8_t stage = 0; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++stage) - { - if (isValid(m_vsh->m_bindInfo[stage].m_uniform)) - { - m_bindInfo[stage] = m_vsh->m_bindInfo[stage]; - } - else if (NULL != m_fsh && isValid(m_fsh->m_bindInfo[stage].m_uniform)) - { - m_bindInfo[stage] = m_fsh->m_bindInfo[stage]; - m_bindInfo[stage].m_index += _vsh->m_numSamplers; - } - } - - m_numSamplers = numSamplers; - - for (uint32_t ii = 0; ii < _vsh->m_numBuffers; ++ii) - { - m_buffers[ii] = _vsh->m_buffers[ii]; - bindings[numBindings++] = _vsh->m_buffers[ii]; - } - - m_numBuffers = _vsh->m_numBuffers; - - BX_CHECK(m_numUniforms + m_numSamplers * 2 + m_numBuffers == numBindings, ""); - - wgpu::BindGroupLayoutDescriptor bindGroupDesc; - bindGroupDesc.entryCount = numBindings; - bindGroupDesc.entries = bindings; - m_bindGroupLayout = s_renderWgpu->m_device.CreateBindGroupLayout(&bindGroupDesc); - - bx::HashMurmur2A murmur; - murmur.begin(); - murmur.add(m_numUniforms); - murmur.add(m_textures, sizeof(wgpu::BindGroupLayoutEntry) * numSamplers); - murmur.add(m_samplers, sizeof(wgpu::BindGroupLayoutEntry) * numSamplers); - murmur.add(m_buffers, sizeof(wgpu::BindGroupLayoutEntry) * m_numBuffers); - m_bindGroupLayoutHash = murmur.end(); - } - - void ProgramWgpu::destroy() - { - m_vsh = NULL; - m_fsh = NULL; - if ( NULL != m_computePS ) - { - BX_DELETE(g_allocator, m_computePS); - m_computePS = NULL; - } - } - - void BufferWgpu::create(uint32_t _size, void* _data, uint16_t _flags, uint16_t _stride, bool _vertex) - { - BX_UNUSED(_stride); - - m_size = _size; - m_flags = _flags; - m_vertex = _vertex; - - const uint32_t paddedSize = bx::strideAlign(_size, 4); - - bool storage = m_flags & BGFX_BUFFER_COMPUTE_READ_WRITE; - bool indirect = m_flags & BGFX_BUFFER_DRAW_INDIRECT; - - wgpu::BufferDescriptor desc; - desc.size = paddedSize; - desc.usage = _vertex ? wgpu::BufferUsage::Vertex : wgpu::BufferUsage::Index; - desc.usage |= (storage || indirect) ? wgpu::BufferUsage::Storage : wgpu::BufferUsage(0); - desc.usage |= indirect ? wgpu::BufferUsage::Indirect : wgpu::BufferUsage(0); - desc.usage |= wgpu::BufferUsage::CopyDst; - - m_ptr = s_renderWgpu->m_device.CreateBuffer(&desc); - - if(NULL != _data) - { - if(_size % 4 != 0) - { - uint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, paddedSize); - bx::memCopy(temp, _data, _size); - m_ptr.SetSubData(0, paddedSize, temp); - BX_FREE(g_allocator, temp); - } - else - { - m_ptr.SetSubData(0, _size, (const uint8_t*)_data); - } - } - } - - void BufferWgpu::update(uint32_t _offset, uint32_t _size, void* _data, bool _discard) - { - wgpu::CommandEncoder& bce = s_renderWgpu->getBlitCommandEncoder(); - - if (!m_vertex && !_discard) - { - if ( m_dynamic == NULL ) - { - m_dynamic = (uint8_t*)BX_ALLOC(g_allocator, m_size); - } - - bx::memCopy(m_dynamic + _offset, _data, _size); - uint32_t start = _offset & 4; - uint32_t end = bx::strideAlign(_offset + _size, 4); - - wgpu::BufferDescriptor desc; - desc.size = end - start; - desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc; - - wgpu::Buffer staging = s_renderWgpu->m_device.CreateBuffer(&desc); // m_dynamic, , 0); - staging.SetSubData(0, _size, reinterpret_cast(_data)); - - // TODO pad to 4 bytes - bce.CopyBufferToBuffer(staging, 0, m_ptr, start, end - start); - s_renderWgpu->m_cmd.release(staging); - } - else - { - wgpu::BufferDescriptor desc; - desc.size = _size; - desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc; - - wgpu::Buffer staging = s_renderWgpu->m_device.CreateBuffer(&desc); - staging.SetSubData(0, _size, reinterpret_cast(_data)); - - bce.CopyBufferToBuffer(staging, 0, m_ptr, _offset, _size); - s_renderWgpu->m_cmd.release(staging); - } - } - - void VertexBufferWgpu::create(uint32_t _size, void* _data, VertexLayoutHandle _layoutHandle, uint16_t _flags) - { - m_layoutHandle = _layoutHandle; - uint16_t stride = isValid(_layoutHandle) - ? s_renderWgpu->m_vertexDecls[_layoutHandle.idx].m_stride - : 0 - ; - - BufferWgpu::create(_size, _data, _flags, stride, true); - } - - void TextureWgpu::create(TextureHandle _handle, const Memory* _mem, uint64_t _flags, uint8_t _skip) - { - m_handle = _handle; - - m_sampler = s_renderWgpu->getSamplerState(uint32_t(_flags) ); - - bimg::ImageContainer imageContainer; - - if (bimg::imageParse(imageContainer, _mem->data, _mem->size) ) - { - const bimg::ImageBlockInfo& blockInfo = getBlockInfo(bimg::TextureFormat::Enum(imageContainer.m_format) ); - const uint8_t startLod = bx::min(_skip, imageContainer.m_numMips-1); - - bimg::TextureInfo ti; - bimg::imageGetSize( - &ti - , uint16_t(imageContainer.m_width >>startLod) - , uint16_t(imageContainer.m_height>>startLod) - , uint16_t(imageContainer.m_depth >>startLod) - , imageContainer.m_cubeMap - , 1 < imageContainer.m_numMips - , imageContainer.m_numLayers - , imageContainer.m_format - ); - ti.numMips = bx::min(imageContainer.m_numMips-startLod, ti.numMips); - - m_flags = _flags; - m_width = ti.width; - m_height = ti.height; - m_depth = ti.depth; - m_numLayers = ti.numLayers; - m_numMips = ti.numMips; - m_numSides = ti.numLayers * (imageContainer.m_cubeMap ? 6 : 1); - m_requestedFormat = TextureFormat::Enum(imageContainer.m_format); - m_textureFormat = getViableTextureFormat(imageContainer); - - if (m_requestedFormat == bgfx::TextureFormat::D16) - m_textureFormat = bgfx::TextureFormat::D32F; - - const bool compressed = bimg::isCompressed(bimg::TextureFormat::Enum(imageContainer.m_format)); - - if (compressed) - m_textureFormat = bgfx::TextureFormat::BGRA8; - - const bool convert = m_textureFormat != m_requestedFormat; - const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) ); - - wgpu::TextureDescriptor desc = defaultDescriptor(); - //desc.label = getName(_handle); - - if (1 < ti.numLayers) - { - if (imageContainer.m_cubeMap) - { - m_type = TextureCube; - desc.dimension = wgpu::TextureDimension::e2D; - } - else - { - m_type = Texture2D; - desc.dimension = wgpu::TextureDimension::e2D; - } - } - else if (imageContainer.m_cubeMap) - { - m_type = TextureCube; - desc.dimension = wgpu::TextureDimension::e2D; - } - else if (1 < imageContainer.m_depth) - { - m_type = Texture3D; - desc.dimension = wgpu::TextureDimension::e3D; - } - else - { - m_type = Texture2D; - desc.dimension = wgpu::TextureDimension::e2D; - } - - const uint16_t numSides = ti.numLayers * (imageContainer.m_cubeMap ? 6 : 1); - const uint32_t numSrd = numSides * ti.numMips; - - const bool writeOnly = 0 != (_flags&BGFX_TEXTURE_RT_WRITE_ONLY); - const bool computeWrite = 0 != (_flags&BGFX_TEXTURE_COMPUTE_WRITE); - const bool renderTarget = 0 != (_flags&BGFX_TEXTURE_RT_MASK); - const bool srgb = 0 != (_flags&BGFX_TEXTURE_SRGB); - - BX_TRACE("Texture %3d: %s (requested: %s), layers %d, %dx%d%s RT[%c], WO[%c], CW[%c], sRGB[%c]" - , this - s_renderWgpu->m_textures - , getName( (TextureFormat::Enum)m_textureFormat) - , getName( (TextureFormat::Enum)m_requestedFormat) - , ti.numLayers - , ti.width - , ti.height - , imageContainer.m_cubeMap ? "x6" : "" - , renderTarget ? 'x' : ' ' - , writeOnly ? 'x' : ' ' - , computeWrite ? 'x' : ' ' - , srgb ? 'x' : ' ' - ); - - const uint32_t msaaQuality = bx::uint32_satsub( (_flags&BGFX_TEXTURE_RT_MSAA_MASK)>>BGFX_TEXTURE_RT_MSAA_SHIFT, 1); - const int32_t sampleCount = s_msaa[msaaQuality]; - - - wgpu::TextureFormat format = wgpu::TextureFormat::Undefined; - if (srgb) - { - format = s_textureFormat[m_textureFormat].m_fmtSrgb; - BX_WARN(format != wgpu::TextureFormat::Undefined - , "sRGB not supported for texture format %d" - , m_textureFormat - ); - } - - if (format == wgpu::TextureFormat::Undefined) - { - // not swizzled and not sRGB, or sRGB unsupported - format = s_textureFormat[m_textureFormat].m_fmt; - } - - desc.format = format; - desc.size.width = m_width; - desc.size.height = m_height; - desc.size.depth = bx::uint32_max(1,imageContainer.m_depth); - desc.mipLevelCount = m_numMips; - desc.sampleCount = 1; - desc.arrayLayerCount = m_numSides; - - desc.usage = wgpu::TextureUsage::Sampled; - desc.usage |= wgpu::TextureUsage::CopyDst; - desc.usage |= wgpu::TextureUsage::CopySrc; - - if (computeWrite) - { - desc.usage |= wgpu::TextureUsage::Storage; - } - - if (renderTarget) - { - desc.usage |= wgpu::TextureUsage::OutputAttachment; - } - - m_ptr = s_renderWgpu->m_device.CreateTexture(&desc); - - if (sampleCount > 1) - { - desc.sampleCount = sampleCount; - - m_ptrMsaa = s_renderWgpu->m_device.CreateTexture(&desc); - } - - // decode images - struct ImageInfo - { - uint8_t* data; - uint32_t width; - uint32_t height; - uint32_t depth; - uint32_t pitch; - uint32_t slice; - uint32_t size; - uint8_t mipLevel; - uint8_t layer; - }; - - ImageInfo* imageInfos = (ImageInfo*)BX_ALLOC(g_allocator, sizeof(ImageInfo) * numSrd); - bx::memSet(imageInfos, 0, sizeof(ImageInfo) * numSrd); - uint32_t alignment = 1; // tightly aligned buffer - - uint32_t kk = 0; - - for (uint8_t side = 0; side < numSides; ++side) - { - for (uint8_t lod = 0; lod < ti.numMips; ++lod) - { - bimg::ImageMip mip; - if (bimg::imageGetRawData(imageContainer, side, lod + startLod, _mem->data, _mem->size, mip)) - { - if (convert) - { - const uint32_t pitch = bx::strideAlign(bx::max(mip.m_width, 4) * bpp / 8, alignment); - const uint32_t slice = bx::strideAlign(bx::max(mip.m_height, 4) * pitch, alignment); - const uint32_t size = slice * mip.m_depth; - - uint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, size); - bimg::imageDecodeToBgra8( - g_allocator - , temp - , mip.m_data - , mip.m_width - , mip.m_height - , pitch - , mip.m_format - ); - - imageInfos[kk].data = temp; - imageInfos[kk].width = mip.m_width; - imageInfos[kk].height = mip.m_height; - imageInfos[kk].depth = mip.m_depth; - imageInfos[kk].pitch = pitch; - imageInfos[kk].slice = slice; - imageInfos[kk].size = size; - imageInfos[kk].mipLevel = lod; - imageInfos[kk].layer = side; - } - else if (compressed) - { - const uint32_t pitch = bx::strideAlign((mip.m_width / blockInfo.blockWidth) * mip.m_blockSize, alignment); - const uint32_t slice = bx::strideAlign((mip.m_height / blockInfo.blockHeight) * pitch, alignment); - const uint32_t size = slice * mip.m_depth; - - uint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, size); - bimg::imageCopy( - temp - , mip.m_height / blockInfo.blockHeight - , (mip.m_width / blockInfo.blockWidth) * mip.m_blockSize - , mip.m_depth - , mip.m_data - , pitch - ); - - imageInfos[kk].data = temp; - imageInfos[kk].width = mip.m_width; - imageInfos[kk].height = mip.m_height; - imageInfos[kk].depth = mip.m_depth; - imageInfos[kk].pitch = pitch; - imageInfos[kk].slice = slice; - imageInfos[kk].size = size; - imageInfos[kk].mipLevel = lod; - imageInfos[kk].layer = side; - } - else - { - const uint32_t pitch = bx::strideAlign(mip.m_width * mip.m_bpp / 8, alignment); - const uint32_t slice = bx::strideAlign(mip.m_height * pitch, alignment); - const uint32_t size = slice * mip.m_depth; - - uint8_t* temp = (uint8_t*)BX_ALLOC(g_allocator, size); - bimg::imageCopy(temp - , mip.m_height - , mip.m_width * mip.m_bpp / 8 - , mip.m_depth - , mip.m_data - , pitch - ); - - imageInfos[kk].data = temp; - imageInfos[kk].width = mip.m_width; - imageInfos[kk].height = mip.m_height; - imageInfos[kk].depth = mip.m_depth; - imageInfos[kk].pitch = pitch; - imageInfos[kk].slice = slice; - imageInfos[kk].size = size; - imageInfos[kk].mipLevel = lod; - imageInfos[kk].layer = side; - } - } - ++kk; - } - } - - uint32_t totalMemSize = 0; - for (uint32_t ii = 0; ii < numSrd; ++ii) - { - const uint32_t dstpitch = bx::strideAlign(imageInfos[ii].pitch, 256); - totalMemSize += dstpitch * imageInfos[ii].height; - //totalMemSize += imageInfos[ii].size; - } - - wgpu::Buffer stagingBuffer; - if (totalMemSize > 0) - { - wgpu::BufferDescriptor staginBufferDesc; - staginBufferDesc.size = totalMemSize; - staginBufferDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc; - - stagingBuffer = s_renderWgpu->m_device.CreateBuffer(&staginBufferDesc); - - uint64_t offset = 0; - - for (uint32_t ii = 0; ii < numSrd; ++ii) - { - const uint32_t dstpitch = bx::strideAlign(imageInfos[ii].pitch, 256); - - const uint8_t* src = (uint8_t*)imageInfos[ii].data; - //uint64_t offset = 0; - - for (uint32_t yy = 0; yy < imageInfos[ii].height; ++yy, src += imageInfos[ii].pitch, offset += dstpitch) - { - stagingBuffer.SetSubData(offset, imageInfos[ii].pitch, src); - } - - //stagingBuffer.SetSubData(offset, imageInfos[ii].size, imageInfos[ii].data); - //offset += imageInfos[ii].size; - } - } - - wgpu::BufferCopyView* bufferCopyView = (wgpu::BufferCopyView*)BX_ALLOC(g_allocator, sizeof(wgpu::BufferCopyView) * numSrd); - wgpu::TextureCopyView* textureCopyView = (wgpu::TextureCopyView*)BX_ALLOC(g_allocator, sizeof(wgpu::TextureCopyView) * numSrd); - wgpu::Extent3D* textureCopySize = (wgpu::Extent3D*)BX_ALLOC(g_allocator, sizeof(wgpu::Extent3D) * numSrd); - - uint64_t offset = 0; - - for (uint32_t ii = 0; ii < numSrd; ++ii) - { - const uint32_t dstpitch = bx::strideAlign(imageInfos[ii].pitch, 256); - - uint32_t idealWidth = bx::max(1, m_width >> imageInfos[ii].mipLevel); - uint32_t idealHeight = bx::max(1, m_height >> imageInfos[ii].mipLevel); - new (&bufferCopyView[ii]) wgpu::BufferCopyView(); - new (&textureCopyView[ii]) wgpu::TextureCopyView(); - new (&textureCopySize[ii]) wgpu::Extent3D(); - bufferCopyView[ii].buffer = stagingBuffer; - bufferCopyView[ii].offset = offset; - bufferCopyView[ii].bytesPerRow = dstpitch; // assume that image data are tightly aligned - bufferCopyView[ii].rowsPerImage = 0; // assume that image data are tightly aligned - textureCopyView[ii].texture = m_ptr; - //textureCopyView[ii].imageSubresource.aspectMask = m_vkTextureAspect; - textureCopyView[ii].mipLevel = imageInfos[ii].mipLevel; - textureCopyView[ii].arrayLayer = imageInfos[ii].layer; - //textureCopyView[ii].layerCount = 1; - textureCopyView[ii].origin = { 0, 0, 0 }; - textureCopySize[ii] = { idealWidth, idealHeight, imageInfos[ii].depth }; - - offset += dstpitch * imageInfos[ii].height; - //offset += imageInfos[ii].size; - } - - - if (stagingBuffer) - { - wgpu::CommandEncoder encoder = s_renderWgpu->getBlitCommandEncoder(); - //wgpu::CommandEncoder encoder = s_renderWgpu->m_cmd.m_encoder; - for (uint32_t ii = 0; ii < numSrd; ++ii) - { - encoder.CopyBufferToTexture(&bufferCopyView[ii], &textureCopyView[ii], &textureCopySize[ii]); - } - } - else - { - //VkCommandBuffer commandBuffer = s_renderVK->beginNewCommand(); - //setImageMemoryBarrier( - // commandBuffer - // , (m_flags & BGFX_TEXTURE_COMPUTE_WRITE - // ? VK_IMAGE_LAYOUT_GENERAL - // : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL - // ) - //); - //s_renderVK->submitCommandAndWait(commandBuffer); - } - - //vkFreeMemory(device, stagingDeviceMem, allocatorCb); - //vkDestroy(stagingBuffer); - - BX_FREE(g_allocator, bufferCopyView); - BX_FREE(g_allocator, textureCopyView); - BX_FREE(g_allocator, textureCopySize); - for (uint32_t ii = 0; ii < numSrd; ++ii) - { - BX_FREE(g_allocator, imageInfos[ii].data); - } - BX_FREE(g_allocator, imageInfos); - } - } - - void TextureWgpu::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) - { - BX_UNUSED(_side); BX_UNUSED(_mip); BX_UNUSED(_depth); BX_UNUSED(_z); - - const uint32_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_textureFormat) ); - const uint32_t rectpitch = _rect.m_width*bpp/8; - const uint32_t srcpitch = UINT16_MAX == _pitch ? rectpitch : _pitch; - const uint32_t slice = ( (m_type == Texture3D) ? 0 : _side + _z * (m_type == TextureCube ? 6 : 1) ); - const uint16_t zz = (m_type == Texture3D) ? _z : 0 ; - - const bool convert = m_textureFormat != m_requestedFormat; - - uint8_t* data = _mem->data; - uint8_t* temp = NULL; - - if (convert) - { - temp = (uint8_t*)BX_ALLOC(g_allocator, rectpitch*_rect.m_height); - bimg::imageDecodeToBgra8( - g_allocator - , temp - , data - , _rect.m_width - , _rect.m_height - , srcpitch - , bimg::TextureFormat::Enum(m_requestedFormat) - ); - data = temp; - } - - //const uint32_t dstpitch = bx::strideAlign(rectpitch, 64); - const uint32_t dstpitch = bx::strideAlign(rectpitch, 256); - - wgpu::BufferDescriptor desc; - desc.size = dstpitch * _rect.m_height; - desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc; - - wgpu::Buffer staging = s_renderWgpu->m_device.CreateBuffer(&desc); - - const uint8_t* src = (uint8_t*)data; - uint64_t offset = 0; - - for (uint32_t yy = 0; yy < _rect.m_height; ++yy, src += srcpitch, offset += dstpitch) - { - const uint32_t size = bx::strideAlign(rectpitch, 4); - staging.SetSubData(offset, size, src); - } - - wgpu::BufferCopyView srcView; - srcView.buffer = staging; - srcView.offset = 0; - srcView.bytesPerRow = dstpitch; - srcView.rowsPerImage = 0; - - wgpu::TextureCopyView destView; - destView.texture = m_ptr; - destView.mipLevel = _mip; - destView.arrayLayer = _side; - destView.origin = { _rect.m_x, _rect.m_y, zz }; - //destView.origin = { _rect.m_x, _rect.m_y, _z }; - - - wgpu::Extent3D destExtent = { _rect.m_width, _rect.m_height, _depth }; - - //region.imageSubresource.aspectMask = m_vkTextureAspect; - - wgpu::CommandEncoder encoder = s_renderWgpu->getBlitCommandEncoder(); - //wgpu::CommandEncoder encoder = s_renderWgpu->m_cmd.m_encoder; - encoder.CopyBufferToTexture(&srcView, &destView, &destExtent); - - //wgpu::CommandBuffer copy = encoder.Finish(); - //wgpu::Queue queue = s_renderWgpu->m_queue; - //queue.Submit(1, ©); - - //staging.Destroy(); - - if (NULL != temp) - { - BX_FREE(g_allocator, temp); - } - } - - void BindStateWgpu::clear() - { - m_bindGroup = nullptr; - } - - void ScratchBufferWgpu::create(uint32_t _size) - { - m_offset = 0; - m_size = _size; - - wgpu::BufferDescriptor desc; - desc.size = _size; // UNIFORM_BUFFER_SIZE - // TODO (webgpu) use map and wgpu::BufferUsage::MapWrite ? - desc.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst; //wgpu::BufferUsage::TransferDst; - m_buffer = s_renderWgpu->m_device.CreateBuffer(&desc); - } - - void ScratchBufferWgpu::destroy() - { - reset(); - - m_buffer.Release(); - } - - void ScratchBufferWgpu::reset() - { - m_offset = 0; - } - - void BindStateCacheWgpu::create() //(uint32_t _maxBindGroups) - { - //m_maxBindStates = 1024; // _maxBindStates; - m_currentBindState = 0; - } - - void BindStateCacheWgpu::destroy() - { - reset(); - } - - void BindStateCacheWgpu::reset() - { - for (size_t i = 0; i < m_currentBindState; ++i) - { - m_bindStates[i] = {}; - } - - m_currentBindState = 0; - } - - wgpu::TextureView TextureWgpu::getTextureMipLevel(int _mip) - { - if (_mip >= 0 - && _mip < m_numMips - && m_ptr) - { - if (!m_ptrMips[_mip]) - { - wgpu::TextureViewDescriptor desc; - desc.baseMipLevel = _mip; - desc.mipLevelCount = 1; - - desc.format = s_textureFormat[m_textureFormat].m_fmt; - - if (TextureCube == m_type) - { - //desc.dimension = MTLTextureType2DArray; - desc.baseArrayLayer = 0; - desc.arrayLayerCount = m_numLayers * 6; - } - else - { - desc.baseArrayLayer = 0; - desc.arrayLayerCount = m_numLayers; - } - - m_ptrMips[_mip] = m_ptr.CreateView(&desc); - } - - return m_ptrMips[_mip]; - } - - return wgpu::TextureView(); - } - - void SwapChainWgpu::init(wgpu::Device _device, void* _nwh, uint32_t _width, uint32_t _height) - { - BX_UNUSED(_nwh); - - wgpu::SwapChainDescriptor desc; - desc.usage = wgpu::TextureUsage::OutputAttachment; - desc.width = _width; - desc.height = _height; - -#if !BX_PLATFORM_EMSCRIPTEN - m_impl = createSwapChain(_device, _nwh); - - desc.presentMode = wgpu::PresentMode::Immediate; - desc.format = wgpu::TextureFormat::RGBA8Unorm; - desc.implementation = reinterpret_cast(&m_impl); - m_swapChain = _device.CreateSwapChain(nullptr, &desc); -#else - wgpu::SurfaceDescriptorFromHTMLCanvasId canvasDesc{}; - canvasDesc.id = "canvas"; - - wgpu::SurfaceDescriptor surfDesc{}; - surfDesc.nextInChain = &canvasDesc; - wgpu::Surface surface = wgpu::Instance().CreateSurface(&surfDesc); - - desc.presentMode = wgpu::PresentMode::Immediate; - desc.format = wgpu::TextureFormat::BGRA8Unorm; - m_swapChain = _device.CreateSwapChain(surface, &desc); -#endif - - m_colorFormat = desc.format; - m_depthFormat = wgpu::TextureFormat::Depth24PlusStencil8; - } - - void SwapChainWgpu::resize(FrameBufferWgpu& _frameBuffer, uint32_t _width, uint32_t _height, uint32_t _flags) - { - BX_TRACE("SwapChainWgpu::resize"); - - const int32_t sampleCount = s_msaa[(_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; - - wgpu::TextureFormat format = (_flags & BGFX_RESET_SRGB_BACKBUFFER) -#ifdef DAWN_ENABLE_BACKEND_VULKAN - ? wgpu::TextureFormat::BGRA8UnormSrgb - : wgpu::TextureFormat::BGRA8Unorm -#else - ? wgpu::TextureFormat::RGBA8UnormSrgb - : wgpu::TextureFormat::RGBA8Unorm -#endif - ; - -#if !BX_PLATFORM_EMSCRIPTEN - m_swapChain.Configure(format, wgpu::TextureUsage::OutputAttachment, _width, _height); -#endif - - m_colorFormat = format; - m_depthFormat = wgpu::TextureFormat::Depth24PlusStencil8; - - bx::HashMurmur2A murmur; - murmur.begin(); - murmur.add(1); - murmur.add((uint32_t)m_colorFormat); - murmur.add((uint32_t)m_depthFormat); - murmur.add((uint32_t)sampleCount); - _frameBuffer.m_pixelFormatHash = murmur.end(); - - wgpu::TextureDescriptor desc; - - desc.dimension = wgpu::TextureDimension::e2D; - - desc.size.width = _width; - desc.size.height = _height; - desc.size.depth = 1; - desc.mipLevelCount = 1; - desc.sampleCount = sampleCount; - desc.arrayLayerCount = 1; - desc.usage = wgpu::TextureUsage::OutputAttachment; - - if (m_backBufferDepth) - { - m_backBufferDepth.Destroy(); - } - - desc.format = wgpu::TextureFormat::Depth24PlusStencil8; - - m_backBufferDepth = s_renderWgpu->m_device.CreateTexture(&desc); - - if (sampleCount > 1) - { - if (m_backBufferColorMsaa) - { - m_backBufferColorMsaa.Destroy(); - } - - desc.format = m_colorFormat; - desc.sampleCount = sampleCount; - - m_backBufferColorMsaa = s_renderWgpu->m_device.CreateTexture(&desc); - } - } - - void SwapChainWgpu::flip() - { - m_drawable = m_swapChain.GetCurrentTextureView(); - } - - wgpu::TextureView SwapChainWgpu::current() - { - if (!m_drawable) - m_drawable = m_swapChain.GetCurrentTextureView(); - return m_drawable; - } - - void FrameBufferWgpu::create(uint8_t _num, const Attachment* _attachment) - { - m_swapChain = NULL; - m_denseIdx = UINT16_MAX; - m_num = 0; - m_width = 0; - m_height = 0; - - for (uint32_t ii = 0; ii < _num; ++ii) - { - const Attachment& at = _attachment[ii]; - TextureHandle handle = at.handle; - - if (isValid(handle) ) - { - const TextureWgpu& texture = s_renderWgpu->m_textures[handle.idx]; - - if (0 == m_width) - { - m_width = texture.m_width; - m_height = texture.m_height; - } - - if (bimg::isDepth(bimg::TextureFormat::Enum(texture.m_textureFormat) ) ) - { - m_depthHandle = handle; - m_depthAttachment = at; - } - else - { - m_colorHandle[m_num] = handle; - m_colorAttachment[m_num] = at; - m_num++; - } - } - } - - bx::HashMurmur2A murmur; - murmur.begin(); - murmur.add(m_num); - - for (uint32_t ii = 0; ii < m_num; ++ii) - { - const TextureWgpu& texture = s_renderWgpu->m_textures[m_colorHandle[ii].idx]; - murmur.add(uint32_t(s_textureFormat[texture.m_textureFormat].m_fmt) ); - } - - if (!isValid(m_depthHandle) ) - { - murmur.add(uint32_t(wgpu::TextureFormat::Undefined) ); - } - else - { - const TextureWgpu& depthTexture = s_renderWgpu->m_textures[m_depthHandle.idx]; - murmur.add(uint32_t(s_textureFormat[depthTexture.m_textureFormat].m_fmt) ); - } - - murmur.add(1); // SampleCount - - m_pixelFormatHash = murmur.end(); - } - - bool FrameBufferWgpu::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) - { - BX_UNUSED(_format, _depthFormat); - m_swapChain = BX_NEW(g_allocator, SwapChainWgpu); - m_num = 0; - m_width = _width; - m_height = _height; - m_nwh = _nwh; - m_denseIdx = _denseIdx; - - m_swapChain->init(s_renderWgpu->m_device, _nwh, _width, _height); - m_swapChain->resize(*this, _width, _height, 0); - - return m_swapChain->m_swapChain != nullptr; - } - - void FrameBufferWgpu::postReset() - { - } - - uint16_t FrameBufferWgpu::destroy() - { - if (NULL != m_swapChain) - { - BX_DELETE(g_allocator, m_swapChain); - m_swapChain = NULL; - } - - m_num = 0; - m_nwh = NULL; - m_depthHandle.idx = kInvalidHandle; - - uint16_t denseIdx = m_denseIdx; - m_denseIdx = UINT16_MAX; - - return denseIdx; - } - - void CommandQueueWgpu::init(wgpu::Queue _queue) - { - m_queue = _queue; -#if BGFX_CONFIG_MULTITHREADED - //m_framesSemaphore.post(WEBGPU_MAX_FRAMES_IN_FLIGHT); -#endif - } - - void CommandQueueWgpu::shutdown() - { - finish(true); - } - - void CommandQueueWgpu::begin() - { - m_encoder = s_renderWgpu->m_device.CreateCommandEncoder(); - } - - inline void commandBufferFinishedCallback(void* _data) - { -#if BGFX_CONFIG_MULTITHREADED - CommandQueueWgpu* queue = (CommandQueueWgpu*)_data; - if (queue) - { - //queue->m_framesSemaphore.post(); - } -#else - BX_UNUSED(_data); -#endif - } - - void CommandQueueWgpu::kick(bool _endFrame, bool _waitForFinish) - { - if (m_encoder) - { - if (_endFrame) - { - m_releaseWriteIndex = (m_releaseWriteIndex + 1) % WEBGPU_MAX_FRAMES_IN_FLIGHT; - //m_encoder.addCompletedHandler(commandBufferFinishedCallback, this); - } - - wgpu::CommandBuffer commands = m_encoder.Finish(); - m_queue.Submit(1, &commands); - - if (_waitForFinish) - { -#if BGFX_CONFIG_MULTITHREADED - //m_framesSemaphore.post(); -#endif - } - - m_encoder = nullptr; - } - } - - void CommandQueueWgpu::finish(bool _finishAll) - { - if (_finishAll) - { - uint32_t count = m_encoder - ? 2 - : 3 - ; - - for (uint32_t ii = 0; ii < count; ++ii) - { - consume(); - } - -#if BGFX_CONFIG_MULTITHREADED - //m_framesSemaphore.post(count); -#endif - } - else - { - consume(); - } - } - - void CommandQueueWgpu::release(wgpu::Buffer _buffer) - { - m_release[m_releaseWriteIndex].push_back(_buffer); - } - - void CommandQueueWgpu::consume() - { -#if BGFX_CONFIG_MULTITHREADED - //m_framesSemaphore.wait(); -#endif - - m_releaseReadIndex = (m_releaseReadIndex + 1) % WEBGPU_MAX_FRAMES_IN_FLIGHT; - - for (wgpu::Buffer& buffer : m_release[m_releaseReadIndex]) - { - buffer.Destroy(); - } - - m_release[m_releaseReadIndex].clear(); - } - - void TimerQueryWgpu::init() - { - m_frequency = bx::getHPFrequency(); - } - - void TimerQueryWgpu::shutdown() - { - } - - uint32_t TimerQueryWgpu::begin(uint32_t _resultIdx) - { - BX_UNUSED(_resultIdx); - return 0; - } - - void TimerQueryWgpu::end(uint32_t _idx) - { - BX_UNUSED(_idx); - } - -#if 0 - static void setTimestamp(void* _data) - { - *( (int64_t*)_data) = bx::getHPCounter(); - } -#endif - - void TimerQueryWgpu::addHandlers(wgpu::CommandBuffer& _commandBuffer) - { - BX_UNUSED(_commandBuffer); - - while (0 == m_control.reserve(1) ) - { - m_control.consume(1); - } - - //uint32_t offset = m_control.m_current; - //_commandBuffer.addScheduledHandler(setTimestamp, &m_result[offset].m_begin); - //_commandBuffer.addCompletedHandler(setTimestamp, &m_result[offset].m_end); - m_control.commit(1); - } - - bool TimerQueryWgpu::get() - { - if (0 != m_control.available() ) - { - uint32_t offset = m_control.m_read; - m_begin = m_result[offset].m_begin; - m_end = m_result[offset].m_end; - m_elapsed = m_end - m_begin; - - m_control.consume(1); - - return true; - } - - return false; - } - - void RendererContextWgpu::submitBlit(BlitState& _bs, uint16_t _view) - { - if (!_bs.hasItem(_view) ) - { - return; - } - - endEncoding(); - - wgpu::CommandEncoder& bce = getBlitCommandEncoder(); - - while (_bs.hasItem(_view) ) - { - const BlitItem& blit = _bs.advance(); - - const TextureWgpu& src = m_textures[blit.m_src.idx]; - const TextureWgpu& dst = m_textures[blit.m_dst.idx]; - - uint32_t srcWidth = bx::uint32_min(src.m_width, blit.m_srcX + blit.m_width) - blit.m_srcX; - uint32_t srcHeight = bx::uint32_min(src.m_height, blit.m_srcY + blit.m_height) - blit.m_srcY; - uint32_t srcDepth = bx::uint32_min(src.m_depth, blit.m_srcZ + blit.m_depth) - blit.m_srcZ; - uint32_t dstWidth = bx::uint32_min(dst.m_width, blit.m_dstX + blit.m_width) - blit.m_dstX; - uint32_t dstHeight = bx::uint32_min(dst.m_height, blit.m_dstY + blit.m_height) - blit.m_dstY; - uint32_t dstDepth = bx::uint32_min(dst.m_depth, blit.m_dstZ + blit.m_depth) - blit.m_dstZ; - uint32_t width = bx::uint32_min(srcWidth, dstWidth); - uint32_t height = bx::uint32_min(srcHeight, dstHeight); - uint32_t depth = bx::uint32_min(srcDepth, dstDepth); - bool readBack = !!(dst.m_flags & BGFX_TEXTURE_READ_BACK); - - wgpu::TextureCopyView srcView; - srcView.texture = src.m_ptr; - srcView.origin = { blit.m_srcX, blit.m_srcY, 0 }; - srcView.mipLevel = blit.m_srcMip; - srcView.arrayLayer = blit.m_srcZ; - - wgpu::TextureCopyView dstView; - dstView.texture = dst.m_ptr; - dstView.origin = { blit.m_dstX, blit.m_dstY, 0 }; - dstView.mipLevel = blit.m_dstMip; - dstView.arrayLayer = blit.m_dstZ; - - if (depth == 0) - { - wgpu::Extent3D copyExtent = { width, height, 1 }; - bce.CopyTextureToTexture(&srcView, &dstView, ©Extent); - } - else - { - wgpu::Extent3D copyExtent = { width, height, depth }; - bce.CopyTextureToTexture(&srcView, &dstView, ©Extent); - } - - if (readBack) - { - //bce..synchronizeTexture(dst.m_ptr, 0, blit.m_dstMip); - } - } - - //if (bce) - //{ - // bce.endEncoding(); - // bce = 0; - //} - } - - void RendererContextWgpu::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) - { - if(_render->m_capture) - { - renderDocTriggerCapture(); - } - - m_cmd.finish(false); - - if (!m_cmd.m_encoder) - { - m_cmd.begin(); - } - - BGFX_WEBGPU_PROFILER_BEGIN_LITERAL("rendererSubmit", kColorFrame); - - int64_t timeBegin = bx::getHPCounter(); - int64_t captureElapsed = 0; - - //m_gpuTimer.addHandlers(m_encoder); - - updateResolution(_render->m_resolution); - - m_frameIndex = 0; // (m_frameIndex + 1) % WEBGPU_MAX_FRAMES_IN_FLIGHT; - - ScratchBufferWgpu& scratchBuffer = m_scratchBuffers[m_frameIndex]; - scratchBuffer.reset(); - - BindStateCacheWgpu& bindStates = m_bindStateCache[m_frameIndex]; - bindStates.reset(); - - if (0 < _render->m_iboffset) - { - BGFX_PROFILER_SCOPE("bgfx/Update transient index buffer", kColorResource); - TransientIndexBuffer* ib = _render->m_transientIb; - m_indexBuffers[ib->handle.idx].update(0, bx::strideAlign(_render->m_iboffset,4), ib->data, true); - } - - if (0 < _render->m_vboffset) - { - BGFX_PROFILER_SCOPE("bgfx/Update transient vertex buffer", kColorResource); - TransientVertexBuffer* vb = _render->m_transientVb; - m_vertexBuffers[vb->handle.idx].update(0, bx::strideAlign(_render->m_vboffset,4), vb->data, true); - } - - _render->sort(); - - RenderDraw currentState; - currentState.clear(); - currentState.m_stateFlags = BGFX_STATE_NONE; - currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); - - RenderBind currentBind; - currentBind.clear(); - - static ViewState viewState; - viewState.reset(_render); - uint32_t blendFactor = 0; - - //bool wireframe = !!(_render->m_debug&BGFX_DEBUG_WIREFRAME); - - ProgramHandle currentProgram = BGFX_INVALID_HANDLE; - uint32_t currentBindHash = 0; - uint32_t currentBindLayoutHash = 0; - BindStateWgpu* previousBindState = nullptr; - SortKey key; - uint16_t view = UINT16_MAX; - FrameBufferHandle fbh = { BGFX_CONFIG_MAX_FRAME_BUFFERS }; - - BlitState bs(_render); - - const uint64_t primType = 0; - uint8_t primIndex = uint8_t(primType >> BGFX_STATE_PT_SHIFT); - PrimInfo prim = s_primInfo[primIndex]; - const uint32_t maxComputeBindings = g_caps.limits.maxComputeBindings; - - // TODO store this - static wgpu::RenderPassEncoder rce; - - PipelineStateWgpu* currentPso = NULL; - - bool wasCompute = false; - bool viewHasScissor = false; - Rect viewScissorRect; - viewScissorRect.clear(); - - uint32_t statsNumPrimsSubmitted[BX_COUNTOF(s_primInfo)] = {}; - uint32_t statsNumPrimsRendered[BX_COUNTOF(s_primInfo)] = {}; - uint32_t statsNumInstances[BX_COUNTOF(s_primInfo)] = {}; - uint32_t statsNumDrawIndirect[BX_COUNTOF(s_primInfo)] = {}; - uint32_t statsNumIndices = 0; - uint32_t statsKeyType[2] = {}; - - Profiler profiler( - _render - , m_gpuTimer - , s_viewName - ); - - if (0 == (_render->m_debug & BGFX_DEBUG_IFH)) - { - viewState.m_rect = _render->m_view[0].m_rect; - int32_t numItems = _render->m_numRenderItems; - - for (int32_t item = 0; item < numItems;) - { - const uint64_t encodedKey = _render->m_sortKeys[item]; - const bool isCompute = key.decode(encodedKey, _render->m_viewRemap); - statsKeyType[isCompute]++; - - const bool viewChanged = 0 - || key.m_view != view - || item == numItems - ; - - const uint32_t itemIdx = _render->m_sortValues[item]; - const RenderItem& renderItem = _render->m_renderItem[itemIdx]; - const RenderBind& renderBind = _render->m_renderItemBind[itemIdx]; - ++item; - - if (viewChanged - || (!isCompute && wasCompute)) - { - view = key.m_view; - currentProgram = BGFX_INVALID_HANDLE; - - if (item > 1) - { - profiler.end(); - } - - BGFX_WEBGPU_PROFILER_END(); - setViewType(view, " "); - BGFX_WEBGPU_PROFILER_BEGIN(view, kColorView); - - profiler.begin(view); - - viewState.m_rect = _render->m_view[view].m_rect; - - submitBlit(bs, view); - - if (!isCompute) - { - const Rect& scissorRect = _render->m_view[view].m_scissor; - viewHasScissor = !scissorRect.isZero(); - viewScissorRect = viewHasScissor ? scissorRect : viewState.m_rect; - Clear& clr = _render->m_view[view].m_clear; - - Rect viewRect = viewState.m_rect; - bool clearWithRenderPass = false; - - if (!m_renderEncoder - || fbh.idx != _render->m_view[view].m_fbh.idx) - { - endEncoding(); - - fbh = _render->m_view[view].m_fbh; - - uint32_t width = m_resolution.width; - uint32_t height = m_resolution.height; - - if (isValid(fbh)) - { - FrameBufferWgpu& frameBuffer = m_frameBuffers[fbh.idx]; - width = frameBuffer.m_width; - height = frameBuffer.m_height; - } - - clearWithRenderPass = true - && 0 == viewRect.m_x - && 0 == viewRect.m_y - && width == viewRect.m_width - && height == viewRect.m_height - ; - - rce = renderPass(_render, fbh, clearWithRenderPass, clr, s_viewName[view]); - } - else if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION)) - { - rce.PopDebugGroup(); - } - - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION)) - { - rce.PushDebugGroup(s_viewName[view]); - } - - //rce.setTriangleFillMode(wireframe ? MTLTriangleFillModeLines : MTLTriangleFillModeFill); - - // TODO (webgpu) check other renderers - const Rect& rect = viewState.m_rect; - rce.SetViewport(rect.m_x, rect.m_y, rect.m_width, rect.m_height, 0.0f, 1.0f); - - // can't disable: set to view rect - rce.SetScissorRect(rect.m_x, rect.m_y, rect.m_width, rect.m_height); - - - if (BGFX_CLEAR_NONE != (clr.m_flags & BGFX_CLEAR_MASK) - && !clearWithRenderPass) - { - clearQuad(_clearQuad, viewState.m_rect, clr, _render->m_colorPalette); - } - } - } - - if (isCompute) - { - if (!wasCompute) - { - wasCompute = true; - - endEncoding(); - rce = NULL; - - setViewType(view, "C"); - BGFX_WEBGPU_PROFILER_END(); - BGFX_WEBGPU_PROFILER_BEGIN(view, kColorCompute); - - m_computeEncoder = m_cmd.m_encoder.BeginComputePass(); - } - else if (viewChanged) - { - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION)) - { - m_computeEncoder.PopDebugGroup(); - } - - endEncoding(); - m_computeEncoder = m_cmd.m_encoder.BeginComputePass(); - } - - if (viewChanged) - { - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION)) - { - s_viewName[view][3] = L'C'; - m_computeEncoder.PushDebugGroup(s_viewName[view]); - s_viewName[view][3] = L' '; - } - } - - const RenderCompute& compute = renderItem.compute; - - bool programChanged = false; - bool constantsChanged = compute.m_uniformBegin < compute.m_uniformEnd; - rendererUpdateUniforms(this, _render->m_uniformBuffer[compute.m_uniformIdx], compute.m_uniformBegin, compute.m_uniformEnd); - - if (key.m_program.idx != currentProgram.idx) - { - currentProgram = key.m_program; - - currentPso = getComputePipelineState(currentProgram); - - if (NULL == currentPso) - { - currentProgram = BGFX_INVALID_HANDLE; - continue; - } - - m_computeEncoder.SetPipeline(currentPso->m_cps); - programChanged = - constantsChanged = true; - } - - if (!isValid(currentProgram) - || NULL == currentPso) - BX_WARN(false, "Invalid program / No PSO"); - - const ProgramWgpu& program = m_program[currentProgram.idx]; - - if (constantsChanged) - { - UniformBuffer* vcb = program.m_vsh->m_constantBuffer; - if (NULL != vcb) - { - commit(*vcb); - } - } - - viewState.setPredefined<4>(this, view, program, _render, compute); - - uint32_t numOffset = 1; - uint32_t offsets[2] = { scratchBuffer.m_offset, 0 }; - if (program.m_vsh->m_size > 0) - { - scratchBuffer.m_buffer.SetSubData(scratchBuffer.m_offset, program.m_vsh->m_gpuSize, m_vsScratch); - scratchBuffer.m_offset += program.m_vsh->m_gpuSize; - } - - BindingsWgpu b; - BindStateWgpu& bindState = allocBindState(program, bindStates, b, scratchBuffer); - - bindGroups(program, bindState, b); - - bindProgram(m_computeEncoder, program, bindState, numOffset, offsets); - - if (isValid(compute.m_indirectBuffer)) - { - const VertexBufferWgpu& vb = m_vertexBuffers[compute.m_indirectBuffer.idx]; - - uint32_t numDrawIndirect = UINT16_MAX == compute.m_numIndirect - ? vb.m_size/BGFX_CONFIG_DRAW_INDIRECT_STRIDE - : compute.m_numIndirect - ; - - uint32_t args = compute.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE; - for (uint32_t ii = 0; ii < numDrawIndirect; ++ii) - { - m_computeEncoder.DispatchIndirect( - vb.m_ptr - , args - ); - args += BGFX_CONFIG_DRAW_INDIRECT_STRIDE; - } - } - else - { - m_computeEncoder.Dispatch(compute.m_numX, compute.m_numY, compute.m_numZ); - } - - continue; - } - - - bool resetState = viewChanged || wasCompute; - - if (wasCompute) - { - wasCompute = false; - currentProgram = BGFX_INVALID_HANDLE; - - setViewType(view, " "); - BGFX_WEBGPU_PROFILER_END(); - BGFX_WEBGPU_PROFILER_BEGIN(view, kColorDraw); - } - - const RenderDraw& draw = renderItem.draw; - - // TODO (hugoam) - //const bool depthWrite = !!(BGFX_STATE_WRITE_Z & draw.m_stateFlags); - const uint64_t newFlags = draw.m_stateFlags; - uint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags; - currentState.m_stateFlags = newFlags; - - const uint64_t newStencil = draw.m_stencil; - uint64_t changedStencil = (currentState.m_stencil ^ draw.m_stencil) & BGFX_STENCIL_FUNC_REF_MASK; - currentState.m_stencil = newStencil; - - if (resetState) - { - wasCompute = false; - - currentState.clear(); - currentState.m_scissor = !draw.m_scissor; - changedFlags = BGFX_STATE_MASK; - changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK); - currentState.m_stateFlags = newFlags; - currentState.m_stencil = newStencil; - - currentBind.clear(); - - currentProgram = BGFX_INVALID_HANDLE; - const uint64_t pt = newFlags & BGFX_STATE_PT_MASK; - primIndex = uint8_t(pt >> BGFX_STATE_PT_SHIFT); - } - - if (prim.m_type != s_primInfo[primIndex].m_type) - { - prim = s_primInfo[primIndex]; - } - - uint16_t scissor = draw.m_scissor; - if (currentState.m_scissor != scissor) - { - currentState.m_scissor = scissor; - - if (UINT16_MAX == scissor) - { - if (viewHasScissor) - { - const auto& r = viewScissorRect; - rce.SetScissorRect(r.m_x, r.m_y, r.m_width, r.m_height); - } - else - { // can't disable: set to view rect - const auto& r = viewState.m_rect; - rce.SetScissorRect(r.m_x, r.m_y, r.m_width, r.m_height); - } - } - else - { - Rect scissorRect; - scissorRect.setIntersect(viewScissorRect, _render->m_frameCache.m_rectCache.m_cache[scissor]); - - const auto& r = scissorRect; - rce.SetScissorRect(r.m_x, r.m_y, r.m_width, r.m_height); - } - - } - - if (0 != changedStencil) - { - const uint32_t fstencil = unpackStencil(0, draw.m_stencil); - const uint32_t ref = (fstencil & BGFX_STENCIL_FUNC_REF_MASK) >> BGFX_STENCIL_FUNC_REF_SHIFT; - rce.SetStencilReference(ref); - } - - if ((0 | BGFX_STATE_PT_MASK) & changedFlags) - { - const uint64_t pt = newFlags & BGFX_STATE_PT_MASK; - primIndex = uint8_t(pt >> BGFX_STATE_PT_SHIFT); - if (prim.m_type != s_primInfo[primIndex].m_type) - { - prim = s_primInfo[primIndex]; - } - } - - if (blendFactor != draw.m_rgba - && !(newFlags & BGFX_STATE_BLEND_INDEPENDENT)) - { - const uint32_t rgba = draw.m_rgba; - float rr = ((rgba >> 24)) / 255.0f; - float gg = ((rgba >> 16) & 0xff) / 255.0f; - float bb = ((rgba >> 8) & 0xff) / 255.0f; - float aa = ((rgba) & 0xff) / 255.0f; - wgpu::Color color = { rr, gg, bb, aa }; - rce.SetBlendColor(&color); - - blendFactor = draw.m_rgba; - } - - bool programChanged = false; - bool constantsChanged = draw.m_uniformBegin < draw.m_uniformEnd; - rendererUpdateUniforms(this, _render->m_uniformBuffer[draw.m_uniformIdx], draw.m_uniformBegin, draw.m_uniformEnd); - - bool vertexStreamChanged = hasVertexStreamChanged(currentState, draw); - - if (key.m_program.idx != currentProgram.idx - || vertexStreamChanged - || (0 - | BGFX_STATE_BLEND_MASK - | BGFX_STATE_BLEND_EQUATION_MASK - | BGFX_STATE_WRITE_RGB - | BGFX_STATE_WRITE_A - | BGFX_STATE_BLEND_INDEPENDENT - | BGFX_STATE_MSAA - | BGFX_STATE_BLEND_ALPHA_TO_COVERAGE - ) & changedFlags - || ((blendFactor != draw.m_rgba) && !!(newFlags & BGFX_STATE_BLEND_INDEPENDENT))) - { - currentProgram = key.m_program; - - currentState.m_streamMask = draw.m_streamMask; - currentState.m_instanceDataBuffer.idx = draw.m_instanceDataBuffer.idx; - currentState.m_instanceDataOffset = draw.m_instanceDataOffset; - currentState.m_instanceDataStride = draw.m_instanceDataStride; - - const VertexLayout* decls[BGFX_CONFIG_MAX_VERTEX_STREAMS]; - - uint32_t numVertices = draw.m_numVertices; - uint8_t numStreams = 0; - for (uint32_t idx = 0, streamMask = draw.m_streamMask - ; 0 != streamMask - ; streamMask >>= 1, idx += 1, ++numStreams - ) - { - const uint32_t ntz = bx::uint32_cnttz(streamMask); - streamMask >>= ntz; - idx += ntz; - - currentState.m_stream[idx].m_layoutHandle = draw.m_stream[idx].m_layoutHandle; - currentState.m_stream[idx].m_handle = draw.m_stream[idx].m_handle; - currentState.m_stream[idx].m_startVertex = draw.m_stream[idx].m_startVertex; - - const uint16_t handle = draw.m_stream[idx].m_handle.idx; - const VertexBufferWgpu& vb = m_vertexBuffers[handle]; - const uint16_t decl = isValid(draw.m_stream[idx].m_layoutHandle) - ? draw.m_stream[idx].m_layoutHandle.idx - : vb.m_layoutHandle.idx; - const VertexLayout& vertexDecl = m_vertexDecls[decl]; - const uint32_t stride = vertexDecl.m_stride; - - decls[numStreams] = &vertexDecl; - - numVertices = bx::uint32_min(UINT32_MAX == draw.m_numVertices - ? vb.m_size / stride - : draw.m_numVertices - , numVertices - ); - const uint32_t offset = draw.m_stream[idx].m_startVertex * stride; - - rce.SetVertexBuffer(idx, vb.m_ptr, offset); - } - - bool index32 = false; - - if (isValid(draw.m_indexBuffer)) - { - const IndexBufferWgpu& ib = m_indexBuffers[draw.m_indexBuffer.idx]; - index32 = 0 != (ib.m_flags & BGFX_BUFFER_INDEX32); - } - - currentState.m_numVertices = numVertices; - - if (!isValid(currentProgram)) - { - continue; - } - else - { - currentPso = NULL; - - if (0 < numStreams) - { - currentPso = getPipelineState( - newFlags - , newStencil - , draw.m_rgba - , fbh - , numStreams - , decls - , index32 - , currentProgram - , uint8_t(draw.m_instanceDataStride / 16) - ); - } - - if (NULL == currentPso) - { - currentProgram = BGFX_INVALID_HANDLE; - continue; - } - - rce.SetPipeline(currentPso->m_rps); - } - - if (isValid(draw.m_instanceDataBuffer)) - { - const VertexBufferWgpu& inst = m_vertexBuffers[draw.m_instanceDataBuffer.idx]; - rce.SetVertexBuffer(numStreams/*+1*/, inst.m_ptr, draw.m_instanceDataOffset); - } - - programChanged = - constantsChanged = true; - } - - if (isValid(currentProgram)) - { - const ProgramWgpu& program = m_program[currentProgram.idx]; - - if (constantsChanged) - { - UniformBuffer* vcb = program.m_vsh->m_constantBuffer; - if (NULL != vcb) - { - commit(*vcb); - } - } - - if (constantsChanged) - { - UniformBuffer* fcb = program.m_fsh->m_constantBuffer; - if (NULL != fcb) - { - commit(*fcb); - } - } - - viewState.setPredefined<4>(this, view, program, _render, draw); - - bool hasPredefined = 0 < program.m_numPredefined; - - uint32_t numOffset = 0; - uint32_t offsets[2] = { 0, 0 }; - if (constantsChanged - || hasPredefined) - { - //viewState.setPredefined<4>(this, view, program, _render, draw, programChanged || viewChanged); - //commitShaderConstants(scratchBuffer, program, voffset, foffset); - - const uint32_t vsize = program.m_fsh->m_gpuSize; - const uint32_t fsize = (NULL != program.m_fsh ? program.m_fsh->m_gpuSize : 0); - - if (program.m_vsh->m_size > 0) - { - offsets[numOffset++] = scratchBuffer.m_offset; - scratchBuffer.m_buffer.SetSubData(scratchBuffer.m_offset, vsize, m_vsScratch); - } - if (fsize > 0) - { - offsets[numOffset++] = scratchBuffer.m_offset + vsize; - scratchBuffer.m_buffer.SetSubData(scratchBuffer.m_offset + vsize, fsize, m_fsScratch); - } - - scratchBuffer.m_offset += program.m_gpuSize; - } - - uint32_t bindHash = bx::hash(renderBind.m_bind, sizeof(renderBind.m_bind)); - if (currentBindHash != bindHash - || currentBindLayoutHash != program.m_bindGroupLayoutHash) - { - currentBindHash = bindHash; - currentBindLayoutHash = program.m_bindGroupLayoutHash; - previousBindState = &bindStates.m_bindStates[bindStates.m_currentBindState]; - - allocBindState(program, bindStates, scratchBuffer, renderBind); - } - - BindStateWgpu& bindState = bindStates.m_bindStates[bindStates.m_currentBindState-1]; - - bindProgram(rce, program, bindState, numOffset, offsets); - } - - if (0 != currentState.m_streamMask) - { - uint32_t numVertices = draw.m_numVertices; - if (UINT32_MAX == numVertices) - { - const VertexBufferWgpu& vb = m_vertexBuffers[currentState.m_stream[0].m_handle.idx]; - uint16_t decl = !isValid(vb.m_layoutHandle) ? draw.m_stream[0].m_layoutHandle.idx : vb.m_layoutHandle.idx; - const VertexLayout& vertexDecl = m_vertexDecls[decl]; - numVertices = vb.m_size/vertexDecl.m_stride; - } - - uint32_t numIndices = 0; - uint32_t numPrimsSubmitted = 0; - uint32_t numInstances = 0; - uint32_t numPrimsRendered = 0; - uint32_t numDrawIndirect = 0; - - if (isValid(draw.m_indirectBuffer) ) - { - const VertexBufferWgpu& vb = m_vertexBuffers[draw.m_indirectBuffer.idx]; - - if (isValid(draw.m_indexBuffer) ) - { - const IndexBufferWgpu& ib = m_indexBuffers[draw.m_indexBuffer.idx]; - - numDrawIndirect = UINT16_MAX == draw.m_numIndirect - ? vb.m_size/BGFX_CONFIG_DRAW_INDIRECT_STRIDE - : draw.m_numIndirect - ; - - for (uint32_t ii = 0; ii < numDrawIndirect; ++ii) - { - rce.SetIndexBuffer(ib.m_ptr, 0); - rce.DrawIndexedIndirect(vb.m_ptr, (draw.m_startIndirect + ii)* BGFX_CONFIG_DRAW_INDIRECT_STRIDE); - } - } - else - { - numDrawIndirect = UINT16_MAX == draw.m_numIndirect - ? vb.m_size/BGFX_CONFIG_DRAW_INDIRECT_STRIDE - : draw.m_numIndirect - ; - for (uint32_t ii = 0; ii < numDrawIndirect; ++ii) - { - rce.DrawIndirect(vb.m_ptr, (draw.m_startIndirect + ii)* BGFX_CONFIG_DRAW_INDIRECT_STRIDE); - } - } - } - else - { - if (isValid(draw.m_indexBuffer) ) - { - const IndexBufferWgpu& ib = m_indexBuffers[draw.m_indexBuffer.idx]; - - const uint32_t indexSize = 0 == (ib.m_flags & BGFX_BUFFER_INDEX32) ? 2 : 4; - - if (UINT32_MAX == draw.m_numIndices) - { - numIndices = ib.m_size/indexSize; - numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub; - numInstances = draw.m_numInstances; - numPrimsRendered = numPrimsSubmitted*draw.m_numInstances; - - rce.SetIndexBuffer(ib.m_ptr, 0); - rce.DrawIndexed(numIndices, draw.m_numInstances, 0, 0, 0); - } - else if (prim.m_min <= draw.m_numIndices) - { - numIndices = draw.m_numIndices; - numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub; - numInstances = draw.m_numInstances; - numPrimsRendered = numPrimsSubmitted*draw.m_numInstances; - - rce.SetIndexBuffer(ib.m_ptr, 0); - rce.DrawIndexed(numIndices, numInstances, draw.m_startIndex, 0, 0); - } - } - else - { - numPrimsSubmitted = numVertices/prim.m_div - prim.m_sub; - numInstances = draw.m_numInstances; - numPrimsRendered = numPrimsSubmitted*draw.m_numInstances; - - rce.Draw(numVertices, draw.m_numInstances, 0, 0); - } - } - - statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted; - statsNumPrimsRendered[primIndex] += numPrimsRendered; - statsNumInstances[primIndex] += numInstances; - statsNumDrawIndirect[primIndex] += numDrawIndirect; - statsNumIndices += numIndices; - } - } - - if (wasCompute) - { - invalidateCompute(); - - setViewType(view, "C"); - BGFX_WEBGPU_PROFILER_END(); - BGFX_WEBGPU_PROFILER_BEGIN(view, kColorCompute); - } - - submitBlit(bs, BGFX_CONFIG_MAX_VIEWS); - - if (0 < _render->m_numRenderItems) - { - captureElapsed = -bx::getHPCounter(); - capture(); - rce = m_renderEncoder; - captureElapsed += bx::getHPCounter(); - - profiler.end(); - } - } - - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) ) - { - if (0 < _render->m_numRenderItems) - { - rce.PopDebugGroup(); - } - } - - BGFX_WEBGPU_PROFILER_END(); - - int64_t timeEnd = bx::getHPCounter(); - int64_t frameTime = timeEnd - timeBegin; - - static int64_t min = frameTime; - static int64_t max = frameTime; - min = bx::min(min, frameTime); - max = bx::max(max, frameTime); - - static uint32_t maxGpuLatency = 0; - static double maxGpuElapsed = 0.0f; - double elapsedGpuMs = 0.0; - - do - { - double toGpuMs = 1000.0 / double(m_gpuTimer.m_frequency); - elapsedGpuMs = m_gpuTimer.m_elapsed * toGpuMs; - maxGpuElapsed = elapsedGpuMs > maxGpuElapsed ? elapsedGpuMs : maxGpuElapsed; - } - while (m_gpuTimer.get() ); - - maxGpuLatency = bx::uint32_imax(maxGpuLatency, m_gpuTimer.m_control.available()-1); - - const int64_t timerFreq = bx::getHPFrequency(); - - Stats& perfStats = _render->m_perfStats; - perfStats.cpuTimeBegin = timeBegin; - perfStats.cpuTimeEnd = timeEnd; - perfStats.cpuTimerFreq = timerFreq; - perfStats.gpuTimeBegin = m_gpuTimer.m_begin; - perfStats.gpuTimeEnd = m_gpuTimer.m_end; - perfStats.gpuTimerFreq = m_gpuTimer.m_frequency; - perfStats.numDraw = statsKeyType[0]; - perfStats.numCompute = statsKeyType[1]; - perfStats.numBlit = _render->m_numBlitItems; - perfStats.maxGpuLatency = maxGpuLatency; - bx::memCopy(perfStats.numPrims, statsNumPrimsRendered, sizeof(perfStats.numPrims) ); - perfStats.gpuMemoryMax = -INT64_MAX; - perfStats.gpuMemoryUsed = -INT64_MAX; - - //rce.setTriangleFillMode(MTLTriangleFillModeFill); - if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) ) - { - rce = renderPass(_render, BGFX_INVALID_HANDLE, false, Clear()); - - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION)) - { - rce.PushDebugGroup("debugstats"); - } - - TextVideoMem& tvm = m_textVideoMem; - - static int64_t next = timeEnd; - - if (timeEnd >= next) - { - next = timeEnd + timerFreq; - - double freq = double(timerFreq); - double toMs = 1000.0/freq; - - tvm.clear(); - uint16_t pos = 0; - tvm.printf(0, pos++, BGFX_CONFIG_DEBUG ? 0x8c : 0x8f - , " %s / " BX_COMPILER_NAME " / " BX_CPU_NAME " / " BX_ARCH_NAME " / " BX_PLATFORM_NAME " " - , getRendererName() - ); - - pos = 10; - tvm.printf(10, pos++, 0x8b, " Frame: %7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS " - , double(frameTime)*toMs - , double(min)*toMs - , double(max)*toMs - , freq/frameTime - ); - - const uint32_t msaa = (m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; - tvm.printf(10, pos++, 0x8b, " Reset flags: [%c] vsync, [%c] MSAAx%d, [%c] MaxAnisotropy " - , !!(m_resolution.reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' - , 0 != msaa ? '\xfe' : ' ' - , 1<m_numRenderItems - , statsKeyType[0] - , statsKeyType[1] - , elapsedCpuMs - , elapsedCpuMs > maxGpuElapsed ? '>' : '<' - , maxGpuElapsed - , maxGpuLatency - ); - maxGpuLatency = 0; - maxGpuElapsed = 0.0; - - for (uint32_t ii = 0; ii < Topology::Count; ++ii) - { - tvm.printf(10, pos++, 0x8b, " %10s: %7d (#inst: %5d), submitted: %7d" - , getName(Topology::Enum(ii) ) - , statsNumPrimsRendered[ii] - , statsNumInstances[ii] - , statsNumPrimsSubmitted[ii] - ); - } - - tvm.printf(10, pos++, 0x8b, " Indices: %7d ", statsNumIndices); -// tvm.printf(10, pos++, 0x8b, " Uniform size: %7d, Max: %7d ", _render->m_uniformEnd, _render->m_uniformMax); - tvm.printf(10, pos++, 0x8b, " DVB size: %7d ", _render->m_vboffset); - tvm.printf(10, pos++, 0x8b, " DIB size: %7d ", _render->m_iboffset); - - pos++; - double captureMs = double(captureElapsed)*toMs; - tvm.printf(10, pos++, 0x8b, " Capture: %3.4f [ms]", captureMs); - - uint8_t attr[2] = { 0x8c, 0x8a }; - uint8_t attrIndex = _render->m_waitSubmit < _render->m_waitRender; - - tvm.printf(10, pos++, attr[attrIndex &1], " Submit wait: %3.4f [ms]", _render->m_waitSubmit*toMs); - tvm.printf(10, pos++, attr[(attrIndex+1)&1], " Render wait: %3.4f [ms]", _render->m_waitRender*toMs); - - min = frameTime; - max = frameTime; - } - - blit(this, _textVideoMemBlitter, tvm); - rce = m_renderEncoder; - - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION)) - { - rce.PopDebugGroup(); - } - } - else if (_render->m_debug & BGFX_DEBUG_TEXT) - { - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION)) - { - rce.PushDebugGroup("debugtext"); - } - - blit(this, _textVideoMemBlitter, _render->m_textVideoMem); - rce = m_renderEncoder; - - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION)) - { - rce.PopDebugGroup(); - } - } - - endEncoding(); - - m_cmd.kick(true); - -#if !BX_PLATFORM_EMSCRIPTEN - for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) - { - FrameBufferWgpu& frameBuffer = ii == 0 ? m_mainFrameBuffer : m_frameBuffers[m_windows[ii].idx]; - if (NULL != frameBuffer.m_swapChain - && frameBuffer.m_swapChain->m_drawable) - { - SwapChainWgpu& swapChain = *frameBuffer.m_swapChain; - swapChain.m_swapChain.Present(); - } - } -#endif - } - -} /* namespace webgpu */ } // namespace bgfx - -#else - -namespace bgfx { namespace webgpu - { - RendererContextI* rendererCreate(const Init& _init) - { - BX_UNUSED(_init); - return NULL; - } - - void rendererDestroy() - { - } - } /* namespace webgpu */ } // namespace bgfx - -#endif // BGFX_CONFIG_RENDERER_WEBGPU