Add Webgpu backend (#2132)

* WebGPU first draft (shaderc bin version 8)

* WebGPU scripts
This commit is contained in:
Hugo Amnov
2020-05-08 17:53:53 +02:00
committed by GitHub
parent ee96333452
commit b62302631e
36 changed files with 14929 additions and 24 deletions

View File

@@ -0,0 +1,144 @@
// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DAWN_ENUM_CLASS_BITMASKS_H_
#define DAWN_ENUM_CLASS_BITMASKS_H_
#include <type_traits>
namespace wgpu {
template <typename T>
struct IsDawnBitmask {
static constexpr bool enable = false;
};
template <typename T, typename Enable = void>
struct LowerBitmask {
static constexpr bool enable = false;
};
template <typename T>
struct LowerBitmask<T, typename std::enable_if<IsDawnBitmask<T>::enable>::type> {
static constexpr bool enable = true;
using type = T;
constexpr static T Lower(T t) {
return t;
}
};
template <typename T>
struct BoolConvertible {
using Integral = typename std::underlying_type<T>::type;
constexpr BoolConvertible(Integral value) : value(value) {
}
constexpr operator bool() const {
return value != 0;
}
constexpr operator T() const {
return static_cast<T>(value);
}
Integral value;
};
template <typename T>
struct LowerBitmask<BoolConvertible<T>> {
static constexpr bool enable = true;
using type = T;
static constexpr type Lower(BoolConvertible<T> t) {
return t;
}
};
template <typename T1,
typename T2,
typename = typename std::enable_if<LowerBitmask<T1>::enable &&
LowerBitmask<T2>::enable>::type>
constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator|(T1 left, T2 right) {
using T = typename LowerBitmask<T1>::type;
using Integral = typename std::underlying_type<T>::type;
return static_cast<Integral>(LowerBitmask<T1>::Lower(left)) |
static_cast<Integral>(LowerBitmask<T2>::Lower(right));
}
template <typename T1,
typename T2,
typename = typename std::enable_if<LowerBitmask<T1>::enable &&
LowerBitmask<T2>::enable>::type>
constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator&(T1 left, T2 right) {
using T = typename LowerBitmask<T1>::type;
using Integral = typename std::underlying_type<T>::type;
return static_cast<Integral>(LowerBitmask<T1>::Lower(left)) &
static_cast<Integral>(LowerBitmask<T2>::Lower(right));
}
template <typename T1,
typename T2,
typename = typename std::enable_if<LowerBitmask<T1>::enable &&
LowerBitmask<T2>::enable>::type>
constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator^(T1 left, T2 right) {
using T = typename LowerBitmask<T1>::type;
using Integral = typename std::underlying_type<T>::type;
return static_cast<Integral>(LowerBitmask<T1>::Lower(left)) ^
static_cast<Integral>(LowerBitmask<T2>::Lower(right));
}
template <typename T1>
constexpr BoolConvertible<typename LowerBitmask<T1>::type> operator~(T1 t) {
using T = typename LowerBitmask<T1>::type;
using Integral = typename std::underlying_type<T>::type;
return ~static_cast<Integral>(LowerBitmask<T1>::Lower(t));
}
template <typename T,
typename T2,
typename = typename std::enable_if<IsDawnBitmask<T>::enable &&
LowerBitmask<T2>::enable>::type>
constexpr T& operator&=(T& l, T2 right) {
T r = LowerBitmask<T2>::Lower(right);
l = l & r;
return l;
}
template <typename T,
typename T2,
typename = typename std::enable_if<IsDawnBitmask<T>::enable &&
LowerBitmask<T2>::enable>::type>
constexpr T& operator|=(T& l, T2 right) {
T r = LowerBitmask<T2>::Lower(right);
l = l | r;
return l;
}
template <typename T,
typename T2,
typename = typename std::enable_if<IsDawnBitmask<T>::enable &&
LowerBitmask<T2>::enable>::type>
constexpr T& operator^=(T& l, T2 right) {
T r = LowerBitmask<T2>::Lower(right);
l = l ^ r;
return l;
}
template <typename T>
constexpr bool HasZeroOrOneBits(T value) {
using Integral = typename std::underlying_type<T>::type;
return (static_cast<Integral>(value) & (static_cast<Integral>(value) - 1)) == 0;
}
} // namespace wgpu
#endif // DAWN_ENUM_CLASS_BITMASKS_H_

1207
3rdparty/webgpu/include/webgpu/webgpu.h vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1762
3rdparty/webgpu/webgpu_cpp.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1371,6 +1371,11 @@ public static partial class bgfx
/// </summary>
Vulkan,
/// <summary>
/// WebGPU
/// </summary>
WebGPU,
Count
}

View File

@@ -435,6 +435,7 @@ enum bgfx_renderer_type_t
BGFX_RENDERER_TYPE_OPENGLES, /// OpenGL ES 2.0+
BGFX_RENDERER_TYPE_OPENGL, /// OpenGL 2.1+
BGFX_RENDERER_TYPE_VULKAN, /// Vulkan
BGFX_RENDERER_TYPE_WEBGPU, /// WebGPU
BGFX_RENDERER_TYPE_COUNT
}

View File

@@ -483,7 +483,11 @@ public:
gbufferAt[1].init(m_gbufferTex[1]);
}
m_gbufferTex[2] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::D24S8, BGFX_TEXTURE_RT | tsFlags);
bgfx::TextureFormat::Enum depthFormat = bgfx::getRendererType() == bgfx::RendererType::WebGPU
? bgfx::TextureFormat::D32F // WebGPU only supports sampling those for now
: bgfx::TextureFormat::D24S8;
m_gbufferTex[2] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, depthFormat, BGFX_TEXTURE_RT | tsFlags);
gbufferAt[2].init(m_gbufferTex[2]);
m_gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(gbufferAt), gbufferAt, true);

View File

@@ -312,9 +312,13 @@ public:
;
// Make gbuffer and related textures
bgfx::TextureFormat::Enum depthFormat = bgfx::getRendererType() == bgfx::RendererType::WebGPU
? bgfx::TextureFormat::D32F
: bgfx::TextureFormat::D24;
m_gbufferTex[GBUFFER_RT_NORMAL] = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, false, 1, bgfx::TextureFormat::BGRA8, tsFlags);
m_gbufferTex[GBUFFER_RT_COLOR] = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, false, 1, bgfx::TextureFormat::BGRA8, tsFlags);
m_gbufferTex[GBUFFER_RT_DEPTH] = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, false, 1, bgfx::TextureFormat::D24, tsFlags);
m_gbufferTex[GBUFFER_RT_DEPTH] = bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, false, 1, depthFormat, tsFlags);
m_gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(m_gbufferTex), m_gbufferTex, true);
// Make light buffer

View File

@@ -114,6 +114,7 @@ static bgfx::ShaderHandle loadShader(bx::FileReaderI* _reader, const char* _name
case bgfx::RendererType::OpenGL: shaderPath = "shaders/glsl/"; break;
case bgfx::RendererType::OpenGLES: shaderPath = "shaders/essl/"; break;
case bgfx::RendererType::Vulkan: shaderPath = "shaders/spirv/"; break;
case bgfx::RendererType::WebGPU: shaderPath = "shaders/spirv/"; break;
case bgfx::RendererType::Count:
BX_CHECK(false, "You should not be here!");

View File

@@ -61,6 +61,7 @@ namespace bgfx
OpenGLES, //!< OpenGL ES 2.0+
OpenGL, //!< OpenGL 2.1+
Vulkan, //!< Vulkan
WebGPU, //!< WebGPU
Count
};

View File

@@ -90,6 +90,7 @@ typedef enum bgfx_renderer_type
BGFX_RENDERER_TYPE_OPENGLES, /** ( 7) OpenGL ES 2.0+ */
BGFX_RENDERER_TYPE_OPENGL, /** ( 8) OpenGL 2.1+ */
BGFX_RENDERER_TYPE_VULKAN, /** ( 9) Vulkan */
BGFX_RENDERER_TYPE_WEBGPU, /** (10) WebGPU */
BGFX_RENDERER_TYPE_COUNT

View File

@@ -53,6 +53,7 @@
)
#define BGFX_PLATFORM_SUPPORTS_SPIRV (0 \
|| BX_PLATFORM_ANDROID \
|| BX_PLATFORM_EMSCRIPTEN \
|| BX_PLATFORM_LINUX \
|| BX_PLATFORM_WINDOWS \
|| BX_PLATFORM_OSX \
@@ -113,6 +114,7 @@
BGFX_EMBEDDED_SHADER_ESSL (bgfx::RendererType::OpenGLES, _name) \
BGFX_EMBEDDED_SHADER_GLSL (bgfx::RendererType::OpenGL, _name) \
BGFX_EMBEDDED_SHADER_SPIRV(bgfx::RendererType::Vulkan, _name) \
BGFX_EMBEDDED_SHADER_SPIRV(bgfx::RendererType::WebGPU, _name) \
{ bgfx::RendererType::Noop, (const uint8_t*)"VSH\x5\x0\x0\x0\x0\x0\x0", 10 }, \
{ bgfx::RendererType::Count, NULL, 0 } \
} \

View File

@@ -458,6 +458,7 @@ enum.RendererType { comment = "Renderer types:" }
.OpenGLES --- OpenGL ES 2.0+
.OpenGL --- OpenGL 2.1+
.Vulkan --- Vulkan
.WebGPU --- WebGPU
()
--- Access mode enum.

View File

@@ -163,6 +163,43 @@ function bgfxProjectBase(_kind, _defines)
path.join(BGFX_DIR, "src/renderer_nvn.h"),
})
if _OPTIONS["webgpu"] then
defines {
"BGFX_CONFIG_RENDERER_WEBGPU=1",
}
configuration { "asmjs" }
defines {
"BGFX_CONFIG_RENDERER_OPENGL=0",
"BGFX_CONFIG_RENDERER_OPENGLES=0",
}
configuration { "not asmjs" }
--local generator = "out/Default"
local generator = "out/VS2019"
includedirs {
path.join(DAWN_DIR, "src"),
path.join(DAWN_DIR, "src/include"),
path.join(DAWN_DIR, "third_party/vulkan-headers/include"),
path.join(DAWN_DIR, generator, "gen/src"),
path.join(DAWN_DIR, generator, "gen/src/include"),
}
configuration { "vs*" }
defines {
"NTDDI_VERSION=NTDDI_WIN10_RS2",
-- We can't say `=_WIN32_WINNT_WIN10` here because some files do
-- `#if WINVER < 0x0600` without including windows.h before,
-- and then _WIN32_WINNT_WIN10 isn't yet known to be 0x0A00.
"_WIN32_WINNT=0x0A00",
"WINVER=0x0A00",
}
configuration {}
end
if _OPTIONS["with-amalgamated"] then
excludes {
path.join(BGFX_DIR, "src/bgfx.cpp"),
@@ -234,3 +271,59 @@ function bgfxProject(_name, _kind, _defines)
copyLib()
end
if _OPTIONS["webgpu"] then
function usesWebGPU()
configuration { "asmjs" }
linkoptions {
"-s USE_WEBGPU=1",
}
configuration { "not asmjs" }
--local generator = "out/Default"
local generator = "out/VS2019"
includedirs {
path.join(DAWN_DIR, "src"),
path.join(DAWN_DIR, "src/include"),
path.join(DAWN_DIR, generator, "gen/src"),
path.join(DAWN_DIR, generator, "gen/src/include"),
}
libdirs {
path.join(DAWN_DIR, generator),
path.join(DAWN_DIR, generator, "lib/Debug"),
}
files {
path.join(DAWN_DIR, generator, "gen/src/dawn/webgpu_cpp.cpp"),
}
links {
-- shared
"dawn_proc_shared",
"dawn_native_shared",
"shaderc_spvc_shared",
-- static
--"dawn_common",
--"dawn_proc",
--"dawn_native",
--"dawn_platform",
------"shaderc",
--"shaderc_spvc",
--"SPIRV-tools",
--"SPIRV-tools-opt",
--"spirv-cross-cored",
--"spirv-cross-hlsld",
--"spirv-cross-glsld",
--"spirv-cross-msld",
--"spirv-cross-reflectd",
}
removeflags {
"FatalWarnings",
}
configuration {}
end
end

View File

@@ -3,6 +3,11 @@
-- License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
--
newoption {
trigger = "webgpu",
description = "Enable webgpu experimental renderer.",
}
newoption {
trigger = "with-amalgamated",
description = "Enable amalgamated build.",
@@ -162,6 +167,12 @@ if not os.isdir(BX_DIR) or not os.isdir(BIMG_DIR) then
os.exit()
end
if _OPTIONS["webgpu"] then
DAWN_DIR = os.getenv("DAWN_DIR")
_OPTIONS["with-windows"] = "10.0"
end
dofile (path.join(BX_DIR, "scripts/toolchain.lua"))
if not toolchain(BGFX_BUILD_DIR, BGFX_THIRD_PARTY_DIR) then
return -- no action specified
@@ -214,6 +225,10 @@ function exampleProjectDefaults()
"bx",
}
if _OPTIONS["webgpu"] then
usesWebGPU()
end
if _OPTIONS["with-sdl"] then
defines { "ENTRY_CONFIG_USE_SDL=1" }
links { "SDL2" }

View File

@@ -597,6 +597,7 @@ project "shaderc"
path.join(BIMG_DIR, "include"),
path.join(BGFX_DIR, "include"),
path.join(BGFX_DIR, "3rdparty/webgpu/include"),
path.join(BGFX_DIR, "3rdparty/dxsdk/include"),
FCPP_DIR,

View File

@@ -679,6 +679,8 @@ namespace bgfx
ShaderHandle vsh = createEmbeddedShader(s_embeddedShaders, g_caps.rendererType, "vs_debugfont");
ShaderHandle fsh = createEmbeddedShader(s_embeddedShaders, g_caps.rendererType, "fs_debugfont");
BX_CHECK(isValid(vsh) && isValid(fsh), "Failed to create embedded blit shaders");
m_program = createProgram(vsh, fsh, true);
m_vb = s_ctx->createTransientVertexBuffer(numBatchVertices*m_layout.m_stride, &m_layout);
@@ -849,12 +851,14 @@ namespace bgfx
.end();
ShaderHandle vsh = createEmbeddedShader(s_embeddedShaders, g_caps.rendererType, "vs_clear");
BX_CHECK(isValid(vsh), "Failed to create clear quad embedded vertex shader \"vs_clear\"");
for (uint32_t ii = 0, num = g_caps.limits.maxFBAttachments; ii < num; ++ii)
{
char name[32];
bx::snprintf(name, BX_COUNTOF(name), "fs_clear%d", ii);
ShaderHandle fsh = createEmbeddedShader(s_embeddedShaders, g_caps.rendererType, name);
BX_CHECK(isValid(fsh), "Failed to create clear quad embedded fragment shader \"%s\"", name);
m_program[ii] = createProgram(vsh, fsh);
BX_CHECK(isValid(m_program[ii]), "Failed to create clear quad program.");
@@ -1707,6 +1711,11 @@ namespace bgfx
return s_ctx->m_uniformRef[_handle.idx].m_name.getPtr();
}
const char* getName(ShaderHandle _handle)
{
return s_ctx->m_shaderRef[_handle.idx].m_name.getPtr();
}
static const char* s_topologyName[] =
{
"Triangles",
@@ -2476,6 +2485,7 @@ namespace bgfx
BGFX_RENDERER_CONTEXT(nvn);
BGFX_RENDERER_CONTEXT(gl);
BGFX_RENDERER_CONTEXT(vk);
BGFX_RENDERER_CONTEXT(webgpu);
#undef BGFX_RENDERER_CONTEXT
@@ -2489,20 +2499,21 @@ namespace bgfx
static RendererCreator s_rendererCreator[] =
{
{ noop::rendererCreate, noop::rendererDestroy, BGFX_RENDERER_NOOP_NAME, true }, // Noop
{ d3d9::rendererCreate, d3d9::rendererDestroy, BGFX_RENDERER_DIRECT3D9_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D9 }, // Direct3D9
{ d3d11::rendererCreate, d3d11::rendererDestroy, BGFX_RENDERER_DIRECT3D11_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D11 }, // Direct3D11
{ d3d12::rendererCreate, d3d12::rendererDestroy, BGFX_RENDERER_DIRECT3D12_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D12 }, // Direct3D12
{ gnm::rendererCreate, gnm::rendererDestroy, BGFX_RENDERER_GNM_NAME, !!BGFX_CONFIG_RENDERER_GNM }, // GNM
{ noop::rendererCreate, noop::rendererDestroy, BGFX_RENDERER_NOOP_NAME, true }, // Noop
{ d3d9::rendererCreate, d3d9::rendererDestroy, BGFX_RENDERER_DIRECT3D9_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D9 }, // Direct3D9
{ d3d11::rendererCreate, d3d11::rendererDestroy, BGFX_RENDERER_DIRECT3D11_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D11 }, // Direct3D11
{ d3d12::rendererCreate, d3d12::rendererDestroy, BGFX_RENDERER_DIRECT3D12_NAME, !!BGFX_CONFIG_RENDERER_DIRECT3D12 }, // Direct3D12
{ gnm::rendererCreate, gnm::rendererDestroy, BGFX_RENDERER_GNM_NAME, !!BGFX_CONFIG_RENDERER_GNM }, // GNM
#if BX_PLATFORM_OSX || BX_PLATFORM_IOS
{ mtl::rendererCreate, mtl::rendererDestroy, BGFX_RENDERER_METAL_NAME, !!BGFX_CONFIG_RENDERER_METAL }, // Metal
{ mtl::rendererCreate, mtl::rendererDestroy, BGFX_RENDERER_METAL_NAME, !!BGFX_CONFIG_RENDERER_METAL }, // Metal
#else
{ noop::rendererCreate, noop::rendererDestroy, BGFX_RENDERER_NOOP_NAME, false }, // Noop
{ noop::rendererCreate, noop::rendererDestroy, BGFX_RENDERER_NOOP_NAME, false }, // Noop
#endif // BX_PLATFORM_OSX || BX_PLATFORM_IOS
{ nvn::rendererCreate, nvn::rendererDestroy, BGFX_RENDERER_NVN_NAME, !!BGFX_CONFIG_RENDERER_NVN }, // NVN
{ gl::rendererCreate, gl::rendererDestroy, BGFX_RENDERER_OPENGL_NAME, !!BGFX_CONFIG_RENDERER_OPENGLES }, // OpenGLES
{ gl::rendererCreate, gl::rendererDestroy, BGFX_RENDERER_OPENGL_NAME, !!BGFX_CONFIG_RENDERER_OPENGL }, // OpenGL
{ vk::rendererCreate, vk::rendererDestroy, BGFX_RENDERER_VULKAN_NAME, !!BGFX_CONFIG_RENDERER_VULKAN }, // Vulkan
{ nvn::rendererCreate, nvn::rendererDestroy, BGFX_RENDERER_NVN_NAME, !!BGFX_CONFIG_RENDERER_NVN }, // NVN
{ gl::rendererCreate, gl::rendererDestroy, BGFX_RENDERER_OPENGL_NAME, !!BGFX_CONFIG_RENDERER_OPENGLES }, // OpenGLES
{ gl::rendererCreate, gl::rendererDestroy, BGFX_RENDERER_OPENGL_NAME, !!BGFX_CONFIG_RENDERER_OPENGL }, // OpenGL
{ vk::rendererCreate, vk::rendererDestroy, BGFX_RENDERER_VULKAN_NAME, !!BGFX_CONFIG_RENDERER_VULKAN }, // Vulkan
{ webgpu::rendererCreate, webgpu::rendererDestroy, BGFX_RENDERER_WEBGPU_NAME, !!BGFX_CONFIG_RENDERER_WEBGPU }, // WebGPU
};
BX_STATIC_ASSERT(BX_COUNTOF(s_rendererCreator) == RendererType::Count);

View File

@@ -225,6 +225,7 @@ namespace stl = std;
#define BGFX_RENDERER_METAL_NAME "Metal"
#define BGFX_RENDERER_NVN_NAME "NVN"
#define BGFX_RENDERER_VULKAN_NAME "Vulkan"
#define BGFX_RENDERER_WEBGPU_NAME "WebGPU"
#define BGFX_RENDERER_NOOP_NAME "Noop"
#if BGFX_CONFIG_RENDERER_OPENGL
@@ -491,6 +492,7 @@ namespace bgfx
TextureFormat::Enum getViableTextureFormat(const bimg::ImageContainer& _imageContainer);
const char* getName(TextureFormat::Enum _fmt);
const char* getName(UniformHandle _handle);
const char* getName(ShaderHandle _handle);
const char* getName(Topology::Enum _topology);
template<typename Ty>
@@ -1326,7 +1328,9 @@ constexpr uint64_t kSortKeyComputeProgramMask = uint64_t(BGFX_CONFIG_MAX_PROGRA
#define BGFX_UNIFORM_FRAGMENTBIT UINT8_C(0x10)
#define BGFX_UNIFORM_SAMPLERBIT UINT8_C(0x20)
#define BGFX_UNIFORM_MASK (BGFX_UNIFORM_FRAGMENTBIT|BGFX_UNIFORM_SAMPLERBIT)
#define BGFX_UNIFORM_READONLYBIT UINT8_C(0x40)
#define BGFX_UNIFORM_COMPAREBIT UINT8_C(0x80)
#define BGFX_UNIFORM_MASK (BGFX_UNIFORM_FRAGMENTBIT|BGFX_UNIFORM_SAMPLERBIT|BGFX_UNIFORM_READONLYBIT|BGFX_UNIFORM_COMPAREBIT)
class UniformBuffer
{
@@ -3872,6 +3876,12 @@ constexpr uint64_t kSortKeyComputeProgramMask = uint64_t(BGFX_CONFIG_MAX_PROGRA
uint16_t regCount;
bx::read(&reader, regCount, &err);
if (!isShaderVerLess(magic, 8))
{
uint16_t texInfo;
bx::read(&reader, texInfo);
}
PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name);
if (PredefinedUniform::Count == predefined && UniformType::End != UniformType::Enum(type))
{

View File

@@ -137,6 +137,10 @@
# ifndef BGFX_CONFIG_RENDERER_VULKAN
# define BGFX_CONFIG_RENDERER_VULKAN 0
# endif // BGFX_CONFIG_RENDERER_VULKAN
# ifndef BGFX_CONFIG_RENDERER_WEBGPU
# define BGFX_CONFIG_RENDERER_WEBGPU 0
# endif // BGFX_CONFIG_RENDERER_VULKAN
#endif // !defined...
#if BGFX_CONFIG_RENDERER_OPENGL && BGFX_CONFIG_RENDERER_OPENGL < 21

View File

@@ -3938,6 +3938,12 @@ namespace bgfx { namespace d3d11
uint16_t regCount = 0;
bx::read(&reader, regCount);
if (!isShaderVerLess(magic, 8) )
{
uint16_t texInfo = 0;
bx::read(&reader, texInfo);
}
const char* kind = "invalid";
PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name);

View File

@@ -4535,6 +4535,12 @@ namespace bgfx { namespace d3d12
uint16_t regCount = 0;
bx::read(&reader, regCount);
if (!isShaderVerLess(magic, 8) )
{
uint16_t texInfo = 0;
bx::read(&reader, texInfo);
}
const char* kind = "invalid";
PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name);

View File

@@ -2449,6 +2449,12 @@ namespace bgfx { namespace d3d9
uint16_t regCount = 0;
bx::read(&reader, regCount);
if (!isShaderVerLess(magic, 8) )
{
uint16_t texInfo = 0;
bx::read(&reader, texInfo);
}
const char* kind = "invalid";
PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name);

View File

@@ -5905,6 +5905,12 @@ namespace bgfx { namespace gl
uint16_t regCount;
bx::read(&reader, regCount);
if (!isShaderVerLess(magic, 8) )
{
uint16_t texInfo = 0;
bx::read(&reader, texInfo);
}
}
uint32_t shaderSize;

View File

@@ -2459,6 +2459,12 @@ namespace bgfx { namespace mtl
uint16_t regCount;
bx::read(&reader, regCount);
if (!isShaderVerLess(magic, 8) )
{
uint16_t texInfo = 0;
bx::read(&reader, texInfo);
}
}
if (isShaderType(magic, 'C'))

View File

@@ -4816,6 +4816,11 @@ VK_DESTROY
uint16_t regCount;
bx::read(&reader, regCount);
if (!isShaderVerLess(magic, 8) )
{
uint16_t texInfo = 0;
bx::read(&reader, texInfo);
}
const char* kind = "invalid";
PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name);

4898
src/renderer_webgpu.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

568
src/renderer_webgpu.h Normal file
View File

@@ -0,0 +1,568 @@
/*
* Copyright 2011-2019 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#ifndef BGFX_RENDERER_WEBGPU_H_HEADER_GUARD
#define BGFX_RENDERER_WEBGPU_H_HEADER_GUARD
#include "bgfx_p.h"
#if BGFX_CONFIG_RENDERER_WEBGPU
#if !BX_PLATFORM_EMSCRIPTEN
#include <dawn/webgpu_cpp.h>
#include <dawn/dawn_wsi.h>
#else
#include <webgpu/webgpu_cpp.h>
#endif
#define BGFX_WEBGPU_PROFILER_BEGIN(_view, _abgr) \
BX_MACRO_BLOCK_BEGIN \
BGFX_PROFILER_BEGIN(s_viewName[view], _abgr); \
BX_MACRO_BLOCK_END
#define BGFX_WEBGPU_PROFILER_BEGIN_LITERAL(_name, _abgr) \
BX_MACRO_BLOCK_BEGIN \
BGFX_PROFILER_BEGIN_LITERAL("" # _name, _abgr); \
BX_MACRO_BLOCK_END
#define BGFX_WEBGPU_PROFILER_END() \
BX_MACRO_BLOCK_BEGIN \
BGFX_PROFILER_END(); \
BX_MACRO_BLOCK_END
#define WEBGPU_MAX_FRAMES_IN_FLIGHT 3
#define WEBGPU_NUM_UNIFORM_BUFFERS 8
namespace bgfx {
namespace webgpu
{
template <typename Ty>
class StateCacheT
{
public:
void add(uint64_t _id, Ty _item)
{
invalidate(_id);
m_hashMap.insert(stl::make_pair(_id, _item));
}
Ty find(uint64_t _id)
{
typename HashMap::iterator it = m_hashMap.find(_id);
if(it != m_hashMap.end())
{
return it->second;
}
return NULL;
}
void invalidate(uint64_t _id)
{
typename HashMap::iterator it = m_hashMap.find(_id);
if(it != m_hashMap.end())
{
release(it->second);
m_hashMap.erase(it);
}
}
void invalidate()
{
for(typename HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it)
{
release(it->second);
}
m_hashMap.clear();
}
uint32_t getCount() const
{
return uint32_t(m_hashMap.size());
}
private:
typedef stl::unordered_map<uint64_t, Ty> HashMap;
HashMap m_hashMap;
};
struct BufferWgpu
{
void create(uint32_t _size, void* _data, uint16_t _flags, uint16_t _stride = 0, bool _vertex = false);
void update(uint32_t _offset, uint32_t _size, void* _data, bool _discard = false);
void destroy()
{
m_ptr.Destroy();
if(NULL != m_dynamic)
{
BX_DELETE(g_allocator, m_dynamic);
m_dynamic = NULL;
}
}
uint32_t m_size;
uint16_t m_flags = BGFX_BUFFER_NONE;
bool m_vertex;
String m_label;
wgpu::Buffer m_ptr;
uint8_t* m_dynamic = NULL;
};
typedef BufferWgpu IndexBufferWgpu;
struct VertexBufferWgpu : public BufferWgpu
{
void create(uint32_t _size, void* _data, VertexLayoutHandle _declHandle, uint16_t _flags);
VertexLayoutHandle m_layoutHandle;
};
struct BindInfo
{
uint32_t m_index = UINT32_MAX;
uint32_t m_binding = UINT32_MAX;
UniformHandle m_uniform = BGFX_INVALID_HANDLE;
};
struct ShaderWgpu
{
void create(ShaderHandle _handle, const Memory* _mem);
void destroy()
{
if (NULL != m_constantBuffer)
{
UniformBuffer::destroy(m_constantBuffer);
m_constantBuffer = NULL;
}
m_module = nullptr;
}
const char* name() const { return getName(m_handle); }
ShaderHandle m_handle;
String m_label;
wgpu::ShaderStage m_stage;
wgpu::ShaderModule m_module;
uint32_t* m_code = nullptr;
size_t m_codeSize = 0;
UniformBuffer* m_constantBuffer = nullptr;
PredefinedUniform m_predefined[PredefinedUniform::Count];
uint16_t m_attrMask[Attrib::Count];
uint8_t m_attrRemap[Attrib::Count];
uint32_t m_hash = 0;
uint16_t m_numUniforms = 0;
uint16_t m_size = 0;
uint16_t m_gpuSize = 0;
uint8_t m_numPredefined = 0;
uint8_t m_numAttrs = 0;
BindInfo m_bindInfo[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
wgpu::BindGroupLayoutEntry m_samplers[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
wgpu::BindGroupLayoutEntry m_textures[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint8_t m_numSamplers = 0;
wgpu::BindGroupLayoutEntry m_buffers[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint32_t m_numBuffers = 0;
};
struct PipelineStateWgpu;
struct ProgramWgpu
{
void create(const ShaderWgpu* _vsh, const ShaderWgpu* _fsh);
void destroy();
const ShaderWgpu* m_vsh = NULL;
const ShaderWgpu* m_fsh = NULL;
PredefinedUniform m_predefined[PredefinedUniform::Count * 2];
uint8_t m_numPredefined;
PipelineStateWgpu* m_computePS = NULL;
wgpu::BindGroupLayout m_bindGroupLayout;
uint16_t m_gpuSize = 0;
uint32_t m_numUniforms;
uint32_t m_bindGroupLayoutHash;
BindInfo m_bindInfo[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
wgpu::BindGroupLayoutEntry m_samplers[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
wgpu::BindGroupLayoutEntry m_textures[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint32_t m_numSamplers = 0;
wgpu::BindGroupLayoutEntry m_buffers[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint32_t m_numBuffers = 0;
};
constexpr size_t kMaxVertexInputs = 16;
constexpr size_t kMaxVertexAttributes = 16;
constexpr size_t kMaxColorAttachments = BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS;
constexpr uint32_t kMinBufferOffsetAlignment = 256;
struct RenderPassDescriptor
{
RenderPassDescriptor();
wgpu::RenderPassDescriptor desc;
wgpu::RenderPassColorAttachmentDescriptor colorAttachments[kMaxColorAttachments];
wgpu::RenderPassDepthStencilAttachmentDescriptor depthStencilAttachment;
};
struct VertexStateDescriptor
{
VertexStateDescriptor();
wgpu::VertexStateDescriptor desc;
wgpu::VertexBufferLayoutDescriptor vertexBuffers[kMaxVertexInputs];
wgpu::VertexAttributeDescriptor attributes[kMaxVertexAttributes];
};
struct RenderPipelineDescriptor
{
RenderPipelineDescriptor();
wgpu::RenderPipelineDescriptor desc;
//wgpu::ProgrammableStageDescriptor vertexStage;
wgpu::ProgrammableStageDescriptor fragmentStage;
wgpu::VertexStateDescriptor inputState;
wgpu::RasterizationStateDescriptor rasterizationState;
wgpu::DepthStencilStateDescriptor depthStencilState;
wgpu::ColorStateDescriptor colorStates[kMaxColorAttachments];
};
struct BindingsWgpu
{
uint32_t numEntries = 0;
wgpu::BindGroupEntry m_entries[2 + BGFX_CONFIG_MAX_TEXTURE_SAMPLERS*3];
};
struct BindStateWgpu
{
void clear();
uint32_t numOffset;
wgpu::BindGroup m_bindGroup;
};
struct RenderPassStateWgpu
{
RenderPassDescriptor m_rpd;
};
struct PipelineStateWgpu
{
RenderPipelineDescriptor m_rpd;
wgpu::PipelineLayout m_layout;
wgpu::RenderPipeline m_rps;
wgpu::ComputePipeline m_cps;
};
void release(RenderPassStateWgpu* _ptr)
{
BX_DELETE(g_allocator, _ptr);
}
void release(PipelineStateWgpu* _ptr)
{
BX_DELETE(g_allocator, _ptr);
}
class StagingBufferWgpu
{
public:
void create(uint32_t _size, bool mapped);
void map();
void unmap();
void destroy();
void mapped(void* _data, uint64_t _size);
wgpu::Buffer m_buffer;
void* m_data = nullptr;
uint64_t m_size = 0;
};
class ScratchBufferWgpu
{
public:
void create(uint32_t _size); // , uint32_t _maxBindGroups);
void destroy();
void begin();
uint32_t write(void* data, uint64_t _size, uint64_t _offset);
uint32_t write(void* data, uint64_t _size);
void submit();
void release();
StagingBufferWgpu* m_staging = nullptr;
wgpu::Buffer m_stagingAlloc;
wgpu::Buffer m_buffer;
uint32_t m_offset;
uint32_t m_size;
};
class BindStateCacheWgpu
{
public:
void create(); // , uint32_t _maxBindGroups);
void destroy();
void reset();
BindStateWgpu m_bindStates[1024] = {};
uint32_t m_currentBindState;
//uint32_t m_maxBindStates;
};
struct ReadbackWgpu
{
void create(TextureHandle _texture) { m_texture = _texture; }
void destroy()
{
m_buffer.Destroy();
}
void readback(void const* data, uint64_t size)
{
bx::memCopy(m_data, data, m_size < size ? m_size : size);
m_buffer.Unmap();
m_mapped = false;
}
TextureHandle m_texture;
wgpu::Buffer m_buffer;
uint32_t m_mip = 0;
bool m_mapped = false;
void* m_data = NULL;
size_t m_size = 0;
};
struct TextureWgpu
{
enum Enum
{
Texture2D,
Texture3D,
TextureCube,
};
void create(TextureHandle _handle, const Memory* _mem, uint64_t _flags, uint8_t _skip);
void destroy()
{
m_ptr.Destroy();
}
void update(
uint8_t _side
, uint8_t _mip
, const Rect& _rect
, uint16_t _z
, uint16_t _depth
, uint16_t _pitch
, const Memory* _mem
);
TextureHandle m_handle;
String m_label;
wgpu::TextureView m_view;
wgpu::TextureView getTextureMipLevel(int _mip);
wgpu::Texture m_ptr;
wgpu::Texture m_ptrMsaa;
wgpu::TextureView m_ptrMips[14] = {};
wgpu::Sampler m_sampler;
uint64_t m_flags = 0;
uint32_t m_width = 0;
uint32_t m_height = 0;
uint32_t m_depth = 0;
uint8_t m_type;
TextureFormat::Enum m_requestedFormat;
TextureFormat::Enum m_textureFormat;
uint8_t m_numMips = 0;
uint8_t m_numLayers;
uint32_t m_numSides;
uint8_t m_sampleCount;
ReadbackWgpu m_readback;
};
struct SamplerStateWgpu
{
wgpu::Sampler m_sampler;
};
void release(SamplerStateWgpu* _ptr)
{
BX_DELETE(g_allocator, _ptr);
}
struct FrameBufferWgpu;
struct SwapChainWgpu
{
void init(wgpu::Device _device, void* _nwh, uint32_t _width, uint32_t _height);
void resize(FrameBufferWgpu& _frameBuffer, uint32_t _width, uint32_t _height, uint32_t _flags);
void flip();
wgpu::TextureView current();
#if !BX_PLATFORM_EMSCRIPTEN
DawnSwapChainImplementation m_impl;
#endif
wgpu::SwapChain m_swapChain;
wgpu::TextureView m_drawable;
wgpu::Texture m_backBufferColorMsaa;
wgpu::Texture m_backBufferDepth;
wgpu::TextureFormat m_colorFormat;
wgpu::TextureFormat m_depthFormat;
uint32_t m_maxAnisotropy = 0;
uint8_t m_sampleCount;
};
struct FrameBufferWgpu
{
void create(uint8_t _num, const Attachment* _attachment);
bool create(
uint16_t _denseIdx
, void* _nwh
, uint32_t _width
, uint32_t _height
, TextureFormat::Enum _format
, TextureFormat::Enum _depthFormat
);
void postReset();
uint16_t destroy();
SwapChainWgpu* m_swapChain = NULL;
void* m_nwh = NULL;
uint32_t m_width;
uint32_t m_height;
uint16_t m_denseIdx = UINT16_MAX;
uint32_t m_pixelFormatHash = 0;
TextureHandle m_colorHandle[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS - 1];
TextureHandle m_depthHandle = { kInvalidHandle };
Attachment m_colorAttachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS - 1];
Attachment m_depthAttachment;
uint8_t m_num = 0; // number of color handles
};
struct CommandQueueWgpu
{
void init(wgpu::Queue _queue);
void shutdown();
void begin();
void kick(bool _endFrame, bool _waitForFinish = false);
void finish(bool _finishAll = false);
void release(wgpu::Buffer _buffer);
void consume();
#if BGFX_CONFIG_MULTITHREADED
//bx::Semaphore m_framesSemaphore;
#endif
wgpu::Queue m_queue;
wgpu::CommandEncoder m_encoder;
int m_releaseWriteIndex = 0;
int m_releaseReadIndex = 0;
typedef stl::vector<wgpu::Buffer> ResourceArray;
ResourceArray m_release[WEBGPU_MAX_FRAMES_IN_FLIGHT];
};
struct TimerQueryWgpu
{
TimerQueryWgpu()
: m_control(4)
{
}
void init();
void shutdown();
uint32_t begin(uint32_t _resultIdx);
void end(uint32_t _idx);
void addHandlers(wgpu::CommandBuffer& _commandBuffer);
bool get();
struct Result
{
void reset()
{
m_begin = 0;
m_end = 0;
m_pending = 0;
}
uint64_t m_begin;
uint64_t m_end;
uint32_t m_pending;
};
uint64_t m_begin;
uint64_t m_end;
uint64_t m_elapsed;
uint64_t m_frequency;
Result m_result[4 * 2];
bx::RingBufferControl m_control;
};
struct OcclusionQueryWgpu
{
OcclusionQueryWgpu()
: m_control(BX_COUNTOF(m_query))
{
}
void postReset();
void preReset();
void begin(wgpu::RenderPassEncoder& _rce, Frame* _render, OcclusionQueryHandle _handle);
void end(wgpu::RenderPassEncoder& _rce);
void resolve(Frame* _render, bool _wait = false);
void invalidate(OcclusionQueryHandle _handle);
struct Query
{
OcclusionQueryHandle m_handle;
};
wgpu::Buffer m_buffer;
Query m_query[BGFX_CONFIG_MAX_OCCLUSION_QUERIES];
bx::RingBufferControl m_control;
};
} /* namespace metal */
} // namespace bgfx
#endif // BGFX_CONFIG_RENDERER_WEBGPU
#endif // BGFX_RENDERER_WEBGPU_H_HEADER_GUARD

View File

@@ -120,6 +120,12 @@ namespace bgfx
uint16_t regCount;
bx::read(_reader, regCount, _err);
if (!isShaderVerLess(magic, 8) )
{
uint16_t texInfo;
bx::read(_reader, texInfo, _err);
}
}
uint32_t shaderSize;

View File

@@ -53,6 +53,7 @@ namespace bgfx
&s_attribTypeSizeGl, // OpenGLES
&s_attribTypeSizeGl, // OpenGL
&s_attribTypeSizeD3D1x, // Vulkan
&s_attribTypeSizeD3D1x, // WebGPU
&s_attribTypeSizeD3D9, // Count
};
BX_STATIC_ASSERT(BX_COUNTOF(s_attribTypeSize) == RendererType::Count+1);

View File

@@ -13,7 +13,7 @@ extern "C"
#include <fpp.h>
} // extern "C"
#define BGFX_SHADER_BIN_VERSION 6
#define BGFX_SHADER_BIN_VERSION 8
#define BGFX_CHUNK_MAGIC_CSH BX_MAKEFOURCC('C', 'S', 'H', BGFX_SHADER_BIN_VERSION)
#define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', BGFX_SHADER_BIN_VERSION)
#define BGFX_CHUNK_MAGIC_VSH BX_MAKEFOURCC('V', 'S', 'H', BGFX_SHADER_BIN_VERSION)

View File

@@ -109,7 +109,9 @@ namespace bgfx
#define BGFX_UNIFORM_FRAGMENTBIT UINT8_C(0x10)
#define BGFX_UNIFORM_SAMPLERBIT UINT8_C(0x20)
#define BGFX_UNIFORM_MASK (BGFX_UNIFORM_FRAGMENTBIT|BGFX_UNIFORM_SAMPLERBIT)
#define BGFX_UNIFORM_READONLYBIT UINT8_C(0x40)
#define BGFX_UNIFORM_COMPAREBIT UINT8_C(0x80)
#define BGFX_UNIFORM_MASK (BGFX_UNIFORM_FRAGMENTBIT|BGFX_UNIFORM_SAMPLERBIT|BGFX_UNIFORM_READONLYBIT|BGFX_UNIFORM_COMPAREBIT)
const char* getUniformTypeName(UniformType::Enum _enum);
UniformType::Enum nameToUniformTypeEnum(const char* _name);
@@ -121,6 +123,8 @@ namespace bgfx
uint8_t num;
uint16_t regIndex;
uint16_t regCount;
uint8_t texComponent;
uint8_t texDimension;
};
struct Options

View File

@@ -339,6 +339,8 @@ namespace bgfx { namespace glsl
bx::write(_writer, un.num);
bx::write(_writer, un.regIndex);
bx::write(_writer, un.regCount);
bx::write(_writer, un.texComponent);
bx::write(_writer, un.texDimension);
BX_TRACE("%s, %s, %d, %d, %d"
, un.name.c_str()

View File

@@ -736,6 +736,8 @@ namespace bgfx { namespace hlsl
bx::write(_writer, un.num);
bx::write(_writer, un.regIndex);
bx::write(_writer, un.regCount);
bx::write(_writer, un.texComponent);
bx::write(_writer, un.texDimension);
BX_TRACE("%s, %s, %d, %d, %d"
, un.name.c_str()

View File

@@ -602,6 +602,8 @@ namespace bgfx { namespace metal
bx::write(_writer, un.num);
bx::write(_writer, un.regIndex);
bx::write(_writer, un.regCount);
bx::write(_writer, un.texComponent);
bx::write(_writer, un.texDimension);
BX_TRACE("%s, %s, %d, %d, %d"
, un.name.c_str()

View File

@@ -14,6 +14,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow") // warning: declaration of 'u
#include <ResourceLimits.h>
#include <SPIRV/SPVRemapper.h>
#include <SPIRV/GlslangToSpv.h>
#include <webgpu/webgpu_cpp.h>
#define SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
#include <spirv_msl.hpp>
#include <spirv_reflect.hpp>
@@ -175,6 +176,42 @@ namespace bgfx { namespace spirv
return true;
}
wgpu::TextureComponentType SpirvCrossBaseTypeToFormatType(spirv_cross::SPIRType::BaseType spirvBaseType)
{
switch (spirvBaseType)
{
case spirv_cross::SPIRType::Float:
return wgpu::TextureComponentType::Float;
case spirv_cross::SPIRType::Int:
return wgpu::TextureComponentType::Sint;
case spirv_cross::SPIRType::UInt:
return wgpu::TextureComponentType::Uint;
default:
return wgpu::TextureComponentType::Float;
}
}
wgpu::TextureViewDimension SpirvDimToTextureViewDimension(spv::Dim dim, bool arrayed)
{
switch (dim)
{
case spv::Dim::Dim1D:
return wgpu::TextureViewDimension::e1D;
case spv::Dim::Dim2D:
return arrayed
? wgpu::TextureViewDimension::e2DArray
: wgpu::TextureViewDimension::e2D;
case spv::Dim::Dim3D:
return wgpu::TextureViewDimension::e3D;
case spv::Dim::DimCube:
return arrayed
? wgpu::TextureViewDimension::CubeArray
: wgpu::TextureViewDimension::Cube;
default:
return wgpu::TextureViewDimension::Undefined;
}
}
struct SpvReflection
{
struct TypeId
@@ -619,6 +656,8 @@ namespace bgfx { namespace spirv
bx::write(_writer, un.num);
bx::write(_writer, un.regIndex);
bx::write(_writer, un.regCount);
bx::write(_writer, un.texComponent);
bx::write(_writer, un.texDimension);
BX_TRACE("%s, %s, %d, %d, %d"
, un.name.c_str()
@@ -938,15 +977,32 @@ namespace bgfx { namespace spirv
if (name.size() > 7
&& 0 == bx::strCmp(name.c_str() + name.length() - 7, "Texture") )
{
auto uniform_name = name.substr(0, name.length() - 7);
std::string uniform_name = name.substr(0, name.length() - 7);
uint32_t binding_index = refl.get_decoration(resource.id, spv::Decoration::DecorationBinding);
auto imageType = refl.get_type(resource.base_type_id).image;
auto componentType = refl.get_type(imageType.type).basetype;
bool isCompareSampler = false;
for (auto& sampler : resourcesrefl.separate_samplers)
{
if (binding_index + 16 == refl.get_decoration(sampler.id, spv::Decoration::DecorationBinding))
{
std::string samplerName = refl.get_name(sampler.id);
isCompareSampler = refl.variable_is_depth_or_compare(sampler.id) || samplerName.find("Comparison") != std::string::npos;
break;
}
}
Uniform un;
un.name = uniform_name;
un.type = UniformType::Enum(BGFX_UNIFORM_SAMPLERBIT | UniformType::Sampler);
if (isCompareSampler)
un.type = UniformType::Enum(BGFX_UNIFORM_SAMPLERBIT | BGFX_UNIFORM_COMPAREBIT | UniformType::Sampler);
else
un.type = UniformType::Enum(BGFX_UNIFORM_SAMPLERBIT | UniformType::Sampler);
const uint32_t binding = refl.get_decoration(resource.id, spv::DecorationBinding);
uint32_t binding_index = refl.get_decoration(resource.id, spv::Decoration::DecorationBinding);
un.texComponent = uint8_t(SpirvCrossBaseTypeToFormatType(componentType));
un.texDimension = uint8_t(SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed));
un.regIndex = binding_index;
un.regCount = 0; // unused
@@ -963,13 +1019,24 @@ namespace bgfx { namespace spirv
if (name.size() > 7
&& 0 == bx::strCmp(name.c_str() + name.length() - 7, "Texture") )
{
auto uniform_name = name.substr(0, name.length() - 7);
std::string uniform_name = name.substr(0, name.length() - 7);
uint32_t binding_index = refl.get_decoration(resource.id, spv::Decoration::DecorationBinding);
std::string sampler_name = uniform_name + "Sampler";
auto imageType = refl.get_type(resource.base_type_id).image;
auto componentType = refl.get_type(imageType.type).basetype;
spirv_cross::Bitset flags = refl.get_buffer_block_flags(resource.id);
UniformType::Enum type = flags.get(spv::DecorationNonWritable)
? UniformType::Enum(BGFX_UNIFORM_READONLYBIT | UniformType::End)
: UniformType::End;
Uniform un;
un.name = uniform_name;
un.type = UniformType::End;
un.type = type;
un.texComponent = uint8_t(SpirvCrossBaseTypeToFormatType(componentType));
un.texDimension = uint8_t(SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed));
un.regIndex = binding_index;
un.regCount = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; // for descriptor type
@@ -986,6 +1053,11 @@ namespace bgfx { namespace spirv
{
if (!bx::strFind(uniform.name.c_str(), name.c_str()).isEmpty())
{
spirv_cross::Bitset flags = refl.get_buffer_block_flags(resource.id);
UniformType::Enum type = flags.get(spv::DecorationNonWritable)
? UniformType::Enum(BGFX_UNIFORM_READONLYBIT | UniformType::End)
: UniformType::End;
uint32_t binding_index = refl.get_decoration(resource.id, spv::Decoration::DecorationBinding);
uniform.name = name;
uniform.type = UniformType::End;