From e14c5b1c3eb96bbea06f029afb25033565dd59ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sat, 5 Mar 2016 00:17:06 -0800 Subject: [PATCH] Spir-V WIP. --- src/renderer_d3d11.cpp | 3 +- src/renderer_d3d12.cpp | 7 +- src/shader_dx9bc.cpp | 92 ++-- src/shader_dx9bc.h | 16 +- src/shader_dxbc.cpp | 237 +++++----- src/shader_dxbc.h | 20 +- src/shader_spirv.cpp | 981 +++++++++++++++++++++++++---------------- src/shader_spirv.h | 166 +++++-- 8 files changed, 909 insertions(+), 613 deletions(-) diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 350369b1..1f73327d 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -3728,8 +3728,9 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { bx::MemoryReader rd(_code, _size); + bx::Error err; DxbcContext dxbc; - read(&rd, dxbc); + read(&rd, dxbc, &err); struct FindDepthOp { diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index 5d40904b..9c940f3f 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -2238,7 +2238,8 @@ data.NumQualityLevels = 0; bx::StaticMemoryBlockWriter wr(temp->data, temp->size); DxbcContext dxbc; - read(&rd, dxbc); + bx::Error err; + read(&rd, dxbc, &err); bool patchShader = true; if (BX_ENABLED(BGFX_CONFIG_DEBUG) ) @@ -2246,7 +2247,7 @@ data.NumQualityLevels = 0; union { uint32_t offset; void* ptr; } cast = { 0 }; filter(dxbc.shader, dxbc.shader, patchCb0, cast.ptr); - write(&wr, dxbc); + write(&wr, dxbc, &err); dxbcHash(temp->data + 20, temp->size - 20, temp->data + 4); @@ -2280,7 +2281,7 @@ data.NumQualityLevels = 0; uint32_t(program.m_vsh->m_size)/16 }; filter(dxbc.shader, dxbc.shader, patchCb0, cast.ptr); - write(&wr, dxbc); + write(&wr, dxbc, &err); dxbcHash(temp->data + 20, temp->size - 20, temp->data + 4); desc.PS.pShaderBytecode = temp->data; diff --git a/src/shader_dx9bc.cpp b/src/shader_dx9bc.cpp index b9823121..bb2b6a0e 100644 --- a/src/shader_dx9bc.cpp +++ b/src/shader_dx9bc.cpp @@ -274,12 +274,12 @@ namespace bgfx }; BX_STATIC_ASSERT(BX_COUNTOF(s_dx9bcDeclUsage) == Dx9bcDeclUsage::Count); - int32_t read(bx::ReaderI* _reader, Dx9bcSubOperand& _subOperand) + int32_t read(bx::ReaderI* _reader, Dx9bcSubOperand& _subOperand, bx::Error* _err) { int32_t size = 0; uint32_t token; - size += bx::read(_reader, token); + size += bx::read(_reader, token, _err); _subOperand.type = Dx9bcOperandType::Enum( ( (token & UINT32_C(0x70000000) ) >> 28) | ( (token & UINT32_C(0x00001800) ) >> 8) ); @@ -289,7 +289,7 @@ namespace bgfx return size; } - int32_t write(bx::WriterI* _writer, const Dx9bcSubOperand& _subOperand) + int32_t write(bx::WriterI* _writer, const Dx9bcSubOperand& _subOperand, bx::Error* _err) { int32_t size = 0; @@ -298,17 +298,17 @@ namespace bgfx token |= (_subOperand.type << 8) & UINT32_C(0x00001800); token |= _subOperand.regIndex & UINT32_C(0x000007ff); token |= (_subOperand.swizzleBits << 16) & UINT32_C(0x00ff0000); - size += bx::write(_writer, token); + size += bx::write(_writer, token, _err); return size; } - int32_t read(bx::ReaderI* _reader, Dx9bcOperand& _operand) + int32_t read(bx::ReaderI* _reader, Dx9bcOperand& _operand, bx::Error* _err) { int32_t size = 0; uint32_t token; - size += bx::read(_reader, token); + size += bx::read(_reader, token, _err); _operand.type = Dx9bcOperandType::Enum( ( (token & UINT32_C(0x70000000) ) >> 28) | ( (token & UINT32_C(0x00001800) ) >> 8) ); @@ -339,13 +339,13 @@ namespace bgfx if (Dx9bcOperandAddrMode::Relative == _operand.addrMode) { - size += read(_reader, _operand.subOperand); + size += read(_reader, _operand.subOperand, _err); } return size; } - int32_t write(bx::WriterI* _writer, const Dx9bcOperand& _operand) + int32_t write(bx::WriterI* _writer, const Dx9bcOperand& _operand, bx::Error* _err) { int32_t size = 0; @@ -354,22 +354,22 @@ namespace bgfx token |= (_operand.type << 8) & UINT32_C(0x00001800); token |= _operand.regIndex & UINT32_C(0x000007ff); token |= (_operand.addrMode << 13) & UINT32_C(0x00002000); - size += bx::write(_writer, token); + size += bx::write(_writer, token, _err); if (Dx9bcOperandAddrMode::Relative == _operand.addrMode) { - size += write(_writer, _operand.subOperand); + size += write(_writer, _operand.subOperand, _err); } return size; } - int32_t read(bx::ReaderI* _reader, Dx9bcInstruction& _instruction) + int32_t read(bx::ReaderI* _reader, Dx9bcInstruction& _instruction, bx::Error* _err) { int32_t size = 0; uint32_t token; - size += bx::read(_reader, token); + size += bx::read(_reader, token, _err); _instruction.opcode = Dx9bcOpcode::Enum( (token & UINT32_C(0x0000ffff) ) ); @@ -395,7 +395,7 @@ namespace bgfx for (int32_t ii = 0, num = _instruction.length-1; ii < num; ++ii) { uint32_t tmp; - size += bx::read(_reader, tmp); + size += bx::read(_reader, tmp, _err); } } @@ -436,24 +436,24 @@ namespace bgfx if (valuesBeforeOpcode && 0 < info.numValues) { - size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t) ); + size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t), _err); } _instruction.operand[0].destination = true; switch (_instruction.numOperands) { - case 6: size += read(_reader, _instruction.operand[currOp++]); - case 5: size += read(_reader, _instruction.operand[currOp++]); - case 4: size += read(_reader, _instruction.operand[currOp++]); - case 3: size += read(_reader, _instruction.operand[currOp++]); - case 2: size += read(_reader, _instruction.operand[currOp++]); - case 1: size += read(_reader, _instruction.operand[currOp++]); + case 6: size += read(_reader, _instruction.operand[currOp++], _err); + case 5: size += read(_reader, _instruction.operand[currOp++], _err); + case 4: size += read(_reader, _instruction.operand[currOp++], _err); + case 3: size += read(_reader, _instruction.operand[currOp++], _err); + case 2: size += read(_reader, _instruction.operand[currOp++], _err); + case 1: size += read(_reader, _instruction.operand[currOp++], _err); case 0: if (!valuesBeforeOpcode && 0 < info.numValues) { - size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t) ); + size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t), _err); } break; @@ -469,7 +469,7 @@ namespace bgfx return size; } - int32_t write(bx::WriterI* _writer, const Dx9bcInstruction& _instruction) + int32_t write(bx::WriterI* _writer, const Dx9bcInstruction& _instruction, bx::Error* _err) { int32_t size = 0; @@ -477,17 +477,17 @@ namespace bgfx token |= _instruction.opcode & UINT32_C(0x0000ffff); token |= (_instruction.specific << 16) & UINT32_C(0x00ff0000); token |= ( (_instruction.length - 1) << 24) & UINT32_C(0x0f000000); - size += bx::write(_writer, token); + size += bx::write(_writer, token, _err); uint32_t currOp = 0; switch (_instruction.numOperands) { - case 6: size += write(_writer, _instruction.operand[currOp++]); - case 5: size += write(_writer, _instruction.operand[currOp++]); - case 4: size += write(_writer, _instruction.operand[currOp++]); - case 3: size += write(_writer, _instruction.operand[currOp++]); - case 2: size += write(_writer, _instruction.operand[currOp++]); - case 1: size += write(_writer, _instruction.operand[currOp++]); + case 6: size += write(_writer, _instruction.operand[currOp++], _err); + case 5: size += write(_writer, _instruction.operand[currOp++], _err); + case 4: size += write(_writer, _instruction.operand[currOp++], _err); + case 3: size += write(_writer, _instruction.operand[currOp++], _err); + case 2: size += write(_writer, _instruction.operand[currOp++], _err); + case 1: size += write(_writer, _instruction.operand[currOp++], _err); case 0: break; } @@ -626,7 +626,7 @@ namespace bgfx return size; } - int32_t read(bx::ReaderSeekerI* _reader, Dx9bcShader& _shader) + int32_t read(bx::ReaderSeekerI* _reader, Dx9bcShader& _shader, bx::Error* _err) { int32_t size = 0; int64_t offset = bx::seek(_reader); @@ -634,7 +634,7 @@ namespace bgfx for (;;) { Dx9bcInstruction instruction; - int32_t length = read(_reader, instruction); + int32_t length = read(_reader, instruction, _err); size += length; if (Dx9bcOpcode::Count > instruction.opcode) @@ -662,22 +662,22 @@ namespace bgfx bx::seek(_reader, offset, bx::Whence::Begin); _shader.byteCode.resize(size); - bx::read(_reader, _shader.byteCode.data(), size); + bx::read(_reader, _shader.byteCode.data(), size, _err); return size; } - int32_t write(bx::WriterI* _writer, const Dx9bcShader& _shader) + int32_t write(bx::WriterI* _writer, const Dx9bcShader& _shader, bx::Error* _err) { - BX_UNUSED(_writer, _shader); + BX_UNUSED(_writer, _shader, _err); return 0; } - int32_t read(bx::ReaderSeekerI* _reader, Dx9bc& _bc) + int32_t read(bx::ReaderSeekerI* _reader, Dx9bc& _bc, bx::Error* _err) { int32_t size = 0; - size += bx::read(_reader, _bc.version); + size += bx::read(_reader, _bc.version, _err); bool pixelShader = (0xffff0000 == (_bc.version & 0xffff0000) ); uint32_t versionMajor = (_bc.version>>8)&0xff; @@ -689,27 +689,29 @@ namespace bgfx , versionMinor ); - size += read(_reader, _bc.shader); + size += read(_reader, _bc.shader, _err); return size; } - int32_t write(bx::WriterSeekerI* _writer, const Dx9bc& _dxbc) + int32_t write(bx::WriterSeekerI* _writer, const Dx9bc& _dxbc, bx::Error* _err) { - BX_UNUSED(_writer, _dxbc); + BX_UNUSED(_writer, _dxbc, _err); return 0; } - void parse(const Dx9bcShader& _src, Dx9bcParseFn _fn, void* _userData) + void parse(const Dx9bcShader& _src, Dx9bcParseFn _fn, void* _userData, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + bx::MemoryReader reader(_src.byteCode.data(), uint32_t(_src.byteCode.size() ) ); -//BX_TRACE("parse %d", _src.byteCode.size()); + bx::Error err; for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;) { Dx9bcInstruction instruction; - uint32_t size = read(&reader, instruction); + uint32_t size = read(&reader, instruction, _err); BX_CHECK(size/4 == instruction.length, "read %d, expected %d", size/4, instruction.length); BX_UNUSED(size); bool cont = _fn(token * sizeof(uint32_t), instruction, _userData); @@ -722,8 +724,10 @@ namespace bgfx } } - void filter(Dx9bcShader& _dst, const Dx9bcShader& _src, Dx9bcFilterFn _fn, void* _userData) + void filter(Dx9bcShader& _dst, const Dx9bcShader& _src, Dx9bcFilterFn _fn, void* _userData, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + bx::MemoryReader reader(_src.byteCode.data(), uint32_t(_src.byteCode.size() ) ); bx::MemoryBlock mb(g_allocator); @@ -732,7 +736,7 @@ namespace bgfx for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;) { Dx9bcInstruction instruction; - uint32_t size = read(&reader, instruction); + uint32_t size = read(&reader, instruction, _err); BX_CHECK(size/4 == instruction.length, "read %d, expected %d", size/4, instruction.length); BX_UNUSED(size); _fn(instruction, _userData); diff --git a/src/shader_dx9bc.h b/src/shader_dx9bc.h index 1b0215f0..0680d641 100644 --- a/src/shader_dx9bc.h +++ b/src/shader_dx9bc.h @@ -226,8 +226,8 @@ namespace bgfx int32_t value[4]; }; - int32_t read(bx::ReaderI* _reader, Dx9bcInstruction& _instruction); - int32_t write(bx::WriterI* _writer, const Dx9bcInstruction& _instruction); + int32_t read(bx::ReaderI* _reader, Dx9bcInstruction& _instruction, bx::Error* _err); + int32_t write(bx::WriterI* _writer, const Dx9bcInstruction& _instruction, bx::Error* _err); int32_t toString(char* _out, int32_t _size, const Dx9bcInstruction& _instruction); struct Dx9bcShader @@ -235,8 +235,8 @@ namespace bgfx stl::vector byteCode; }; - int32_t read(bx::ReaderSeekerI* _reader, Dx9bcShader& _shader); - int32_t write(bx::WriterI* _writer, const Dx9bcShader& _shader); + int32_t read(bx::ReaderSeekerI* _reader, Dx9bcShader& _shader, bx::Error* _err); + int32_t write(bx::WriterI* _writer, const Dx9bcShader& _shader, bx::Error* _err); struct Dx9bc { @@ -244,14 +244,14 @@ namespace bgfx Dx9bcShader shader; }; - int32_t read(bx::ReaderSeekerI* _reader, Dx9bc& _dx9bc); - int32_t write(bx::WriterSeekerI* _writer, const Dx9bc& _dx9bc); + int32_t read(bx::ReaderSeekerI* _reader, Dx9bc& _dx9bc, bx::Error* _err); + int32_t write(bx::WriterSeekerI* _writer, const Dx9bc& _dx9bc, bx::Error* _err); typedef bool (*Dx9bcParseFn)(uint32_t _offset, const Dx9bcInstruction& _instruction, void* _userData); - void parse(const Dx9bcShader& _src, Dx9bcParseFn _fn, void* _userData); + void parse(const Dx9bcShader& _src, Dx9bcParseFn _fn, void* _userData, bx::Error* _err = NULL); typedef void (*Dx9bcFilterFn)(Dx9bcInstruction& _instruction, void* _userData); - void filter(Dx9bcShader& _dst, const Dx9bcShader& _src, Dx9bcFilterFn _fn, void* _userData); + void filter(Dx9bcShader& _dst, const Dx9bcShader& _src, Dx9bcFilterFn _fn, void* _userData, bx::Error* _err = NULL); } // namespace bgfx diff --git a/src/shader_dxbc.cpp b/src/shader_dxbc.cpp index 36d81842..9f8b351e 100644 --- a/src/shader_dxbc.cpp +++ b/src/shader_dxbc.cpp @@ -552,7 +552,7 @@ namespace bgfx #define DXBC_MAX_NAME_STRING 512 - int32_t readString(bx::ReaderSeekerI* _reader, int64_t _offset, char* _out, uint32_t _max = DXBC_MAX_NAME_STRING) + int32_t readString(bx::ReaderSeekerI* _reader, int64_t _offset, char* _out, uint32_t _max, bx::Error* _err) { int64_t oldOffset = bx::seek(_reader); bx::seek(_reader, _offset, bx::Whence::Begin); @@ -562,7 +562,7 @@ namespace bgfx for (uint32_t ii = 0; ii < _max-1; ++ii) { char ch; - size += bx::read(_reader, ch); + size += bx::read(_reader, ch, _err); *_out++ = ch; if ('\0' == ch) @@ -755,7 +755,7 @@ namespace bgfx memcpy(_digest, hash, 16); } - int32_t read(bx::ReaderI* _reader, DxbcSubOperand& _subOperand) + int32_t read(bx::ReaderI* _reader, DxbcSubOperand& _subOperand, bx::Error* _err) { uint32_t token; int32_t size = 0; @@ -773,7 +773,7 @@ namespace bgfx // |+------------------------------- addressing mode 2 // +-------------------------------- extended - size += bx::read(_reader, token); + size += bx::read(_reader, token, _err); _subOperand.type = DxbcOperandType::Enum( (token & UINT32_C(0x000ff000) ) >> 12); _subOperand.numAddrModes = uint8_t( (token & UINT32_C(0x00300000) ) >> 20); _subOperand.addrMode = uint8_t( (token & UINT32_C(0x01c00000) ) >> 22); @@ -784,7 +784,7 @@ namespace bgfx switch (_subOperand.addrMode) { case DxbcOperandAddrMode::Imm32: - size += bx::read(_reader, _subOperand.regIndex); + size += bx::read(_reader, _subOperand.regIndex, _err); break; case DxbcOperandAddrMode::Reg: @@ -796,7 +796,7 @@ namespace bgfx case DxbcOperandAddrMode::RegImm32: { - size += bx::read(_reader, _subOperand.regIndex); + size += bx::read(_reader, _subOperand.regIndex, _err); DxbcSubOperand subOperand; size += read(_reader, subOperand); @@ -805,8 +805,8 @@ namespace bgfx case DxbcOperandAddrMode::RegImm64: { - size += bx::read(_reader, _subOperand.regIndex); - size += bx::read(_reader, _subOperand.regIndex); + size += bx::read(_reader, _subOperand.regIndex, _err); + size += bx::read(_reader, _subOperand.regIndex, _err); DxbcSubOperand subOperand; size += read(_reader, subOperand); @@ -821,7 +821,7 @@ namespace bgfx return size; } - int32_t write(bx::WriterI* _writer, const DxbcSubOperand& _subOperand) + int32_t write(bx::WriterI* _writer, const DxbcSubOperand& _subOperand, bx::Error* _err) { int32_t size = 0; @@ -832,12 +832,12 @@ namespace bgfx token |= (_subOperand.mode << 2) & UINT32_C(0x0000000c); token |= (_subOperand.modeBits << 4) & UINT32_C(0x00000ff0); token |= _subOperand.num & UINT32_C(0x00000003); - size += bx::write(_writer, token); + size += bx::write(_writer, token, _err); switch (_subOperand.addrMode) { case DxbcOperandAddrMode::Imm32: - size += bx::write(_writer, _subOperand.regIndex); + size += bx::write(_writer, _subOperand.regIndex, _err); break; case DxbcOperandAddrMode::Reg: @@ -849,7 +849,7 @@ namespace bgfx case DxbcOperandAddrMode::RegImm32: { - size += bx::write(_writer, _subOperand.regIndex); + size += bx::write(_writer, _subOperand.regIndex, _err); DxbcSubOperand subOperand; size += write(_writer, subOperand); @@ -858,8 +858,8 @@ namespace bgfx case DxbcOperandAddrMode::RegImm64: { - size += bx::write(_writer, _subOperand.regIndex); - size += bx::write(_writer, _subOperand.regIndex); + size += bx::write(_writer, _subOperand.regIndex, _err); + size += bx::write(_writer, _subOperand.regIndex, _err); DxbcSubOperand subOperand; size += write(_writer, subOperand); @@ -874,12 +874,12 @@ namespace bgfx return size; } - int32_t read(bx::ReaderI* _reader, DxbcOperand& _operand) + int32_t read(bx::ReaderI* _reader, DxbcOperand& _operand, bx::Error* _err) { int32_t size = 0; uint32_t token; - size += bx::read(_reader, token); + size += bx::read(_reader, token, _err); // 0 1 2 3 // 76543210765432107654321076543210 @@ -906,7 +906,7 @@ namespace bgfx if (_operand.extended) { - size += bx::read(_reader, _operand.extBits); + size += bx::read(_reader, _operand.extBits, _err); } switch (_operand.type) @@ -915,7 +915,7 @@ namespace bgfx _operand.num = 2 == _operand.num ? 4 : _operand.num; for (uint32_t ii = 0; ii < _operand.num; ++ii) { - size += bx::read(_reader, _operand.un.imm32[ii]); + size += bx::read(_reader, _operand.un.imm32[ii], _err); } break; @@ -923,7 +923,7 @@ namespace bgfx _operand.num = 2 == _operand.num ? 4 : _operand.num; for (uint32_t ii = 0; ii < _operand.num; ++ii) { - size += bx::read(_reader, _operand.un.imm64[ii]); + size += bx::read(_reader, _operand.un.imm64[ii], _err); } break; @@ -936,16 +936,16 @@ namespace bgfx switch (_operand.addrMode[ii]) { case DxbcOperandAddrMode::Imm32: - size += bx::read(_reader, _operand.regIndex[ii]); + size += bx::read(_reader, _operand.regIndex[ii], _err); break; case DxbcOperandAddrMode::Reg: - size += read(_reader, _operand.subOperand[ii]); + size += read(_reader, _operand.subOperand[ii], _err); break; case DxbcOperandAddrMode::RegImm32: - size += bx::read(_reader, _operand.regIndex[ii]); - size += read(_reader, _operand.subOperand[ii]); + size += bx::read(_reader, _operand.regIndex[ii], _err); + size += read(_reader, _operand.subOperand[ii], _err); break; default: @@ -957,7 +957,7 @@ namespace bgfx return size; } - int32_t write(bx::WriterI* _writer, const DxbcOperand& _operand) + int32_t write(bx::WriterI* _writer, const DxbcOperand& _operand, bx::Error* _err) { int32_t size = 0; @@ -973,7 +973,7 @@ namespace bgfx token |= (4 == _operand.num ? 2 : _operand.num) & UINT32_C(0x00000003); token |= ( (_operand.modeBits & "\x0f\xff\x03\x00"[_operand.mode]) << 4) & UINT32_C(0x00000ff0); - size += bx::write(_writer, token); + size += bx::write(_writer, token, _err); if (_operand.extended) { @@ -985,14 +985,14 @@ namespace bgfx case DxbcOperandType::Imm32: for (uint32_t ii = 0; ii < _operand.num; ++ii) { - size += bx::write(_writer, _operand.un.imm32[ii]); + size += bx::write(_writer, _operand.un.imm32[ii], _err); } break; case DxbcOperandType::Imm64: for (uint32_t ii = 0; ii < _operand.num; ++ii) { - size += bx::write(_writer, _operand.un.imm64[ii]); + size += bx::write(_writer, _operand.un.imm64[ii], _err); } break; @@ -1005,16 +1005,16 @@ namespace bgfx switch (_operand.addrMode[ii]) { case DxbcOperandAddrMode::Imm32: - size += bx::write(_writer, _operand.regIndex[ii]); + size += bx::write(_writer, _operand.regIndex[ii], _err); break; case DxbcOperandAddrMode::Reg: - size += write(_writer, _operand.subOperand[ii]); + size += write(_writer, _operand.subOperand[ii], _err); break; case DxbcOperandAddrMode::RegImm32: - size += bx::write(_writer, _operand.regIndex[ii]); - size += write(_writer, _operand.subOperand[ii]); + size += bx::write(_writer, _operand.regIndex[ii], _err); + size += write(_writer, _operand.subOperand[ii], _err); break; default: @@ -1026,12 +1026,12 @@ namespace bgfx return size; } - int32_t read(bx::ReaderI* _reader, DxbcInstruction& _instruction) + int32_t read(bx::ReaderI* _reader, DxbcInstruction& _instruction, bx::Error* _err) { uint32_t size = 0; uint32_t token; - size += bx::read(_reader, token); + size += bx::read(_reader, token, _err); // 0 1 2 3 // 76543210765432107654321076543210 @@ -1077,7 +1077,7 @@ namespace bgfx for (uint32_t ii = 0, num = (_instruction.length-2)/4; ii < num; ++ii) { char temp[16]; - size += bx::read(_reader, temp, 16); + size += bx::read(_reader, temp, 16, _err); } } @@ -1190,7 +1190,7 @@ namespace bgfx uint32_t extBits; size += bx::read(_reader, extBits); extended = 0 != (extBits & UINT32_C(0x80000000) ); - _instruction.extended[ii] = DxbcInstruction::ExtendedType::Enum(extBits & UINT32_C(0x0000001f) ); + _instruction.extended[ii ] = DxbcInstruction::ExtendedType::Enum(extBits & UINT32_C(0x0000001f) ); _instruction.extended[ii+1] = DxbcInstruction::ExtendedType::Count; switch (_instruction.extended[ii]) @@ -1244,7 +1244,7 @@ namespace bgfx case DxbcOpcode::DCL_FUNCTION_TABLE: { uint32_t tableId; - size += read(_reader, tableId); + size += read(_reader, tableId, _err); uint32_t num; size += read(_reader, num); @@ -1252,7 +1252,7 @@ namespace bgfx for (uint32_t ii = 0; ii < num; ++ii) { uint32_t bodyId; - size += read(_reader, bodyId); + size += read(_reader, bodyId, _err); } } break; @@ -1260,10 +1260,10 @@ namespace bgfx case DxbcOpcode::DCL_INTERFACE: { uint32_t interfaceId; - size += read(_reader, interfaceId); + size += read(_reader, interfaceId, _err); uint32_t num; - size += read(_reader, num); + size += read(_reader, num, _err); BX_CHECK(false, "not implemented."); } @@ -1279,16 +1279,16 @@ namespace bgfx _instruction.numOperands = info.numOperands; switch (info.numOperands) { - case 6: size += read(_reader, _instruction.operand[currOp++]); - case 5: size += read(_reader, _instruction.operand[currOp++]); - case 4: size += read(_reader, _instruction.operand[currOp++]); - case 3: size += read(_reader, _instruction.operand[currOp++]); - case 2: size += read(_reader, _instruction.operand[currOp++]); - case 1: size += read(_reader, _instruction.operand[currOp++]); + case 6: size += read(_reader, _instruction.operand[currOp++], _err); + case 5: size += read(_reader, _instruction.operand[currOp++], _err); + case 4: size += read(_reader, _instruction.operand[currOp++], _err); + case 3: size += read(_reader, _instruction.operand[currOp++], _err); + case 2: size += read(_reader, _instruction.operand[currOp++], _err); + case 1: size += read(_reader, _instruction.operand[currOp++], _err); case 0: if (0 < info.numValues) { - size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t) ); + size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t), _err); } break; @@ -1304,7 +1304,7 @@ namespace bgfx return size; } - int32_t write(bx::WriterI* _writer, const DxbcInstruction& _instruction) + int32_t write(bx::WriterI* _writer, const DxbcInstruction& _instruction, bx::Error* _err) { uint32_t token = 0; token |= (_instruction.opcode ) & UINT32_C(0x000007ff); @@ -1366,7 +1366,7 @@ namespace bgfx uint32_t size =0; size += bx::write(_writer, token); -; + for (uint32_t ii = 0; _instruction.extended[ii] != DxbcInstruction::ExtendedType::Count; ++ii) { // 0 1 2 3 @@ -1427,18 +1427,18 @@ namespace bgfx break; } - size += bx::write(_writer, token); + size += bx::write(_writer, token, _err); } for (uint32_t ii = 0; ii < _instruction.numOperands; ++ii) { - size += write(_writer, _instruction.operand[ii]); + size += write(_writer, _instruction.operand[ii], _err); } const DxbcOpcodeInfo& info = s_dxbcOpcodeInfo[_instruction.opcode]; if (0 < info.numValues) { - size += bx::write(_writer, _instruction.value, info.numValues*sizeof(uint32_t) ); + size += bx::write(_writer, _instruction.value, info.numValues*sizeof(uint32_t), _err); } return size; @@ -1609,15 +1609,15 @@ namespace bgfx return size; } - int32_t read(bx::ReaderSeekerI* _reader, DxbcSignature& _signature) + int32_t read(bx::ReaderSeekerI* _reader, DxbcSignature& _signature, bx::Error* _err) { int32_t size = 0; int64_t offset = bx::seek(_reader); uint32_t num; - size += bx::read(_reader, num); - size += bx::read(_reader, _signature.key); + size += bx::read(_reader, num, _err); + size += bx::read(_reader, _signature.key, _err); for (uint32_t ii = 0; ii < num; ++ii) { @@ -1627,20 +1627,20 @@ namespace bgfx size += bx::read(_reader, nameOffset); char name[DXBC_MAX_NAME_STRING]; - readString(_reader, offset + nameOffset, name); + readString(_reader, offset + nameOffset, name, DXBC_MAX_NAME_STRING, _err); element.name = name; - size += bx::read(_reader, element.semanticIndex); - size += bx::read(_reader, element.valueType); - size += bx::read(_reader, element.componentType); - size += bx::read(_reader, element.registerIndex); - size += bx::read(_reader, element.mask); - size += bx::read(_reader, element.readWriteMask); - size += bx::read(_reader, element.stream); + size += bx::read(_reader, element.semanticIndex, _err); + size += bx::read(_reader, element.valueType, _err); + size += bx::read(_reader, element.componentType, _err); + size += bx::read(_reader, element.registerIndex, _err); + size += bx::read(_reader, element.mask, _err); + size += bx::read(_reader, element.readWriteMask, _err); + size += bx::read(_reader, element.stream, _err); // padding uint8_t padding; - size += bx::read(_reader, padding); + size += bx::read(_reader, padding, _err); _signature.elements.push_back(element); } @@ -1648,13 +1648,13 @@ namespace bgfx return size; } - int32_t write(bx::WriterI* _writer, const DxbcSignature& _signature) + int32_t write(bx::WriterI* _writer, const DxbcSignature& _signature, bx::Error* _err) { int32_t size = 0; const uint32_t num = uint32_t(_signature.elements.size() ); - size += bx::write(_writer, num); - size += bx::write(_writer, _signature.key); + size += bx::write(_writer, num, _err); + size += bx::write(_writer, _signature.key, _err); typedef stl::unordered_map NameOffsetMap; NameOffsetMap nom; @@ -1669,7 +1669,7 @@ namespace bgfx if (it == nom.end() ) { nom.insert(stl::make_pair(element.name, nameOffset) ); - size += bx::write(_writer, nameOffset); + size += bx::write(_writer, nameOffset, _err); nameOffset += uint32_t(element.name.size() + 1); } else @@ -1677,15 +1677,14 @@ namespace bgfx size += bx::write(_writer, it->second); } - size += bx::write(_writer, element.semanticIndex); - size += bx::write(_writer, element.valueType); - size += bx::write(_writer, element.componentType); - size += bx::write(_writer, element.registerIndex); - size += bx::write(_writer, element.mask); - size += bx::write(_writer, element.readWriteMask); - size += bx::write(_writer, element.stream); - size += bx::write(_writer, pad); - + size += bx::write(_writer, element.semanticIndex, _err); + size += bx::write(_writer, element.valueType, _err); + size += bx::write(_writer, element.componentType, _err); + size += bx::write(_writer, element.registerIndex, _err); + size += bx::write(_writer, element.mask, _err); + size += bx::write(_writer, element.readWriteMask, _err); + size += bx::write(_writer, element.stream, _err); + size += bx::write(_writer, pad, _err); } uint32_t len = 0; @@ -1696,42 +1695,42 @@ namespace bgfx if (it != nom.end() ) { nom.erase(it); - size += bx::write(_writer, element.name.c_str(), uint32_t(element.name.size() + 1) ); + size += bx::write(_writer, element.name.c_str(), uint32_t(element.name.size() + 1), _err); len += uint32_t(element.name.size() + 1); } } // align 4 bytes - size += bx::writeRep(_writer, 0xab, (len+3)/4*4 - len); + size += bx::writeRep(_writer, 0xab, (len+3)/4*4 - len, _err); return size; } - int32_t read(bx::ReaderSeekerI* _reader, DxbcShader& _shader) + int32_t read(bx::ReaderSeekerI* _reader, DxbcShader& _shader, bx::Error* _err) { int32_t size = 0; - size += bx::read(_reader, _shader.version); + size += bx::read(_reader, _shader.version, _err); uint32_t bcLength; - size += bx::read(_reader, bcLength); + size += bx::read(_reader, bcLength, _err); uint32_t len = (bcLength-2)*sizeof(uint32_t); _shader.byteCode.resize(len); - size += bx::read(_reader, _shader.byteCode.data(), len); + size += bx::read(_reader, _shader.byteCode.data(), len, _err); return size; } - int32_t write(bx::WriterI* _writer, const DxbcShader& _shader) + int32_t write(bx::WriterI* _writer, const DxbcShader& _shader, bx::Error* _err) { const uint32_t len = uint32_t(_shader.byteCode.size() ); const uint32_t bcLength = len / sizeof(uint32_t) + 2; int32_t size = 0; - size += bx::write(_writer, _shader.version); - size += bx::write(_writer, bcLength); - size += bx::write(_writer, _shader.byteCode.data(), len); + size += bx::write(_writer, _shader.version, _err); + size += bx::write(_writer, bcLength, _err); + size += bx::write(_writer, _shader.byteCode.data(), len, _err); return size; } @@ -1743,10 +1742,10 @@ namespace bgfx #define DXBC_CHUNK_INPUT_SIGNATURE BX_MAKEFOURCC('I', 'S', 'G', 'N') #define DXBC_CHUNK_OUTPUT_SIGNATURE BX_MAKEFOURCC('O', 'S', 'G', 'N') - int32_t read(bx::ReaderSeekerI* _reader, DxbcContext& _dxbc) + int32_t read(bx::ReaderSeekerI* _reader, DxbcContext& _dxbc, bx::Error* _err) { int32_t size = 0; - size += bx::read(_reader, _dxbc.header); + size += bx::read(_reader, _dxbc.header, _err); _dxbc.shader.shex = false; for (uint32_t ii = 0; ii < _dxbc.header.numChunks; ++ii) @@ -1754,15 +1753,15 @@ namespace bgfx bx::seek(_reader, sizeof(DxbcContext::Header) + ii*sizeof(uint32_t), bx::Whence::Begin); uint32_t chunkOffset; - size += bx::read(_reader, chunkOffset); + size += bx::read(_reader, chunkOffset, _err); bx::seek(_reader, chunkOffset, bx::Whence::Begin); uint32_t fourcc; - size += bx::read(_reader, fourcc); + size += bx::read(_reader, fourcc, _err); uint32_t chunkSize; - size += bx::read(_reader, chunkSize); + size += bx::read(_reader, chunkSize, _err); switch (fourcc) { @@ -1771,18 +1770,18 @@ namespace bgfx // fallthrough case DXBC_CHUNK_SHADER: - size += read(_reader, _dxbc.shader); + size += read(_reader, _dxbc.shader, _err); break; case BX_MAKEFOURCC('I', 'S', 'G', '1'): case DXBC_CHUNK_INPUT_SIGNATURE: - size += read(_reader, _dxbc.inputSignature); + size += read(_reader, _dxbc.inputSignature, _err); break; case BX_MAKEFOURCC('O', 'S', 'G', '1'): case BX_MAKEFOURCC('O', 'S', 'G', '5'): case DXBC_CHUNK_OUTPUT_SIGNATURE: - size += read(_reader, _dxbc.outputSignature); + size += read(_reader, _dxbc.outputSignature, _err); break; case BX_MAKEFOURCC('A', 'o', 'n', '9'): // Contains DX9BC for feature level 9.x (*s_4_0_level_9_*) shaders. @@ -1816,43 +1815,43 @@ namespace bgfx return size; } - int32_t write(bx::WriterSeekerI* _writer, const DxbcContext& _dxbc) + int32_t write(bx::WriterSeekerI* _writer, const DxbcContext& _dxbc, bx::Error* _err) { int32_t size = 0; int64_t dxbcOffset = bx::seek(_writer); size += bx::write(_writer, DXBC_CHUNK_HEADER); - size += bx::writeRep(_writer, 0, 16); + size += bx::writeRep(_writer, 0, 16, _err); - size += bx::write(_writer, UINT32_C(1) ); + size += bx::write(_writer, UINT32_C(1), _err); int64_t sizeOffset = bx::seek(_writer); - size += bx::writeRep(_writer, 0, 4); + size += bx::writeRep(_writer, 0, 4, _err); uint32_t numChunks = 3; - size += bx::write(_writer, numChunks); + size += bx::write(_writer, numChunks, _err); int64_t chunksOffsets = bx::seek(_writer); - size += bx::writeRep(_writer, 0, numChunks*sizeof(uint32_t) ); + size += bx::writeRep(_writer, 0, numChunks*sizeof(uint32_t), _err); uint32_t chunkOffset[3]; uint32_t chunkSize[3]; chunkOffset[0] = uint32_t(bx::seek(_writer) - dxbcOffset); - size += write(_writer, DXBC_CHUNK_INPUT_SIGNATURE); - size += write(_writer, UINT32_C(0) ); - chunkSize[0] = write(_writer, _dxbc.inputSignature); + size += write(_writer, DXBC_CHUNK_INPUT_SIGNATURE, _err); + size += write(_writer, UINT32_C(0), _err); + chunkSize[0] = write(_writer, _dxbc.inputSignature, _err); chunkOffset[1] = uint32_t(bx::seek(_writer) - dxbcOffset); - size += write(_writer, DXBC_CHUNK_OUTPUT_SIGNATURE); - size += write(_writer, UINT32_C(0) ); - chunkSize[1] = write(_writer, _dxbc.outputSignature); + size += write(_writer, DXBC_CHUNK_OUTPUT_SIGNATURE, _err); + size += write(_writer, UINT32_C(0), _err); + chunkSize[1] = write(_writer, _dxbc.outputSignature, _err); chunkOffset[2] = uint32_t(bx::seek(_writer) - dxbcOffset); - size += write(_writer, _dxbc.shader.shex ? DXBC_CHUNK_SHADER_EX : DXBC_CHUNK_SHADER); - size += write(_writer, UINT32_C(0) ); - chunkSize[2] = write(_writer, _dxbc.shader); + size += write(_writer, _dxbc.shader.shex ? DXBC_CHUNK_SHADER_EX : DXBC_CHUNK_SHADER, _err); + size += write(_writer, UINT32_C(0), _err); + chunkSize[2] = write(_writer, _dxbc.shader, _err); size += 0 + chunkSize[0] @@ -1863,15 +1862,15 @@ namespace bgfx int64_t eof = bx::seek(_writer); bx::seek(_writer, sizeOffset, bx::Whence::Begin); - bx::write(_writer, size); + bx::write(_writer, size, _err); bx::seek(_writer, chunksOffsets, bx::Whence::Begin); - bx::write(_writer, chunkOffset, sizeof(chunkOffset) ); + bx::write(_writer, chunkOffset, sizeof(chunkOffset), _err); for (uint32_t ii = 0; ii < BX_COUNTOF(chunkOffset); ++ii) { bx::seek(_writer, chunkOffset[ii]+4, bx::Whence::Begin); - bx::write(_writer, chunkSize[ii]); + bx::write(_writer, chunkSize[ii], _err); } bx::seek(_writer, eof, bx::Whence::Begin); @@ -1879,14 +1878,16 @@ namespace bgfx return size; } - void parse(const DxbcShader& _src, DxbcParseFn _fn, void* _userData) + void parse(const DxbcShader& _src, DxbcParseFn _fn, void* _userData, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + bx::MemoryReader reader(_src.byteCode.data(), uint32_t(_src.byteCode.size() ) ); for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;) { DxbcInstruction instruction; - uint32_t size = read(&reader, instruction); + uint32_t size = read(&reader, instruction, _err); BX_CHECK(size/4 == instruction.length, "read %d, expected %d", size/4, instruction.length); BX_UNUSED(size); bool cont = _fn(token * sizeof(uint32_t), instruction, _userData); @@ -1899,8 +1900,10 @@ namespace bgfx } } - void filter(DxbcShader& _dst, const DxbcShader& _src, DxbcFilterFn _fn, void* _userData) + void filter(DxbcShader& _dst, const DxbcShader& _src, DxbcFilterFn _fn, void* _userData, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + bx::MemoryReader reader(_src.byteCode.data(), uint32_t(_src.byteCode.size() ) ); bx::MemoryBlock mb(g_allocator); @@ -1909,12 +1912,12 @@ namespace bgfx for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;) { DxbcInstruction instruction; - uint32_t size = read(&reader, instruction); + uint32_t size = read(&reader, instruction, _err); BX_CHECK(size/4 == instruction.length, "read %d, expected %d", size/4, instruction.length); BX_UNUSED(size); _fn(instruction, _userData); - write(&writer, instruction); + write(&writer, instruction, _err); token += instruction.length; } diff --git a/src/shader_dxbc.h b/src/shader_dxbc.h index 4aa3420f..381fd2f7 100644 --- a/src/shader_dxbc.h +++ b/src/shader_dxbc.h @@ -540,8 +540,8 @@ namespace bgfx DxbcOperand operand[6]; }; - int32_t read(bx::ReaderI* _reader, DxbcInstruction& _instruction); - int32_t write(bx::WriterI* _writer, const DxbcInstruction& _instruction); + int32_t read(bx::ReaderI* _reader, DxbcInstruction& _instruction, bx::Error* _err); + int32_t write(bx::WriterI* _writer, const DxbcInstruction& _instruction, bx::Error* _err); int32_t toString(char* _out, int32_t _size, const DxbcInstruction& _instruction); struct DxbcSignature @@ -562,8 +562,8 @@ namespace bgfx stl::vector elements; }; - int32_t read(bx::ReaderSeekerI* _reader, DxbcSignature& _signature); - int32_t write(bx::WriterI* _writer, const DxbcSignature& _signature); + int32_t read(bx::ReaderSeekerI* _reader, DxbcSignature& _signature, bx::Error* _err); + int32_t write(bx::WriterI* _writer, const DxbcSignature& _signature, bx::Error* _err); struct DxbcShader { @@ -572,14 +572,14 @@ namespace bgfx bool shex; }; - int32_t read(bx::ReaderSeekerI* _reader, DxbcShader& _shader); - int32_t write(bx::WriterI* _writer, const DxbcShader& _shader); + int32_t read(bx::ReaderSeekerI* _reader, DxbcShader& _shader, bx::Error* _err); + int32_t write(bx::WriterI* _writer, const DxbcShader& _shader, bx::Error* _err); typedef bool (*DxbcParseFn)(uint32_t _offset, const DxbcInstruction& _instruction, void* _userData); - void parse(const DxbcShader& _src, DxbcParseFn _fn, void* _userData); + void parse(const DxbcShader& _src, DxbcParseFn _fn, void* _userData, bx::Error* _err = NULL); typedef void (*DxbcFilterFn)(DxbcInstruction& _instruction, void* _userData); - void filter(DxbcShader& _dst, const DxbcShader& _src, DxbcFilterFn _fn, void* _userData); + void filter(DxbcShader& _dst, const DxbcShader& _src, DxbcFilterFn _fn, void* _userData, bx::Error* _err = NULL); struct DxbcContext { @@ -598,8 +598,8 @@ namespace bgfx DxbcShader shader; }; - int32_t read(bx::ReaderSeekerI* _reader, DxbcContext& _dxbc); - int32_t write(bx::WriterSeekerI* _writer, const DxbcContext& _dxbc); + int32_t read(bx::ReaderSeekerI* _reader, DxbcContext& _dxbc, bx::Error* _err); + int32_t write(bx::WriterSeekerI* _writer, const DxbcContext& _dxbc, bx::Error* _err); /// Calculate DXBC hash from data. void dxbcHash(const void* _data, uint32_t _size, void* _digest); diff --git a/src/shader_spirv.cpp b/src/shader_spirv.cpp index 927222d3..1db9943e 100644 --- a/src/shader_spirv.cpp +++ b/src/shader_spirv.cpp @@ -8,313 +8,353 @@ namespace bgfx { - struct SpirvOpcodeInfo + struct SpvOpcodeInfo { - uint8_t numOperands; - uint8_t numValues; - bool hasVariable; + bool hasType; + bool hasResult; + SpvOperand::Enum operands[8]; }; - static const SpirvOpcodeInfo s_sprivOpcodeInfo[] = + static const SpvOpcodeInfo s_spvOpcodeInfo[] = { - { 0, 0, false }, // Nop, - { 0, 0, false }, // Undef, - { 0, 0, false }, // SourceContinued, - { 0, 0, false }, // Source, - { 0, 0, false }, // SourceExtension, - { 0, 0, false }, // Name, - { 0, 0, false }, // MemberName, - { 0, 0, false }, // String, - { 0, 0, false }, // Line, - { 0, 0, false }, // Extension, - { 0, 0, false }, // ExtInstImport, - { 0, 0, false }, // ExtInst, - { 0, 0, false }, // MemoryModel, - { 0, 0, false }, // EntryPoint, - { 0, 0, false }, // ExecutionMode, - { 0, 0, false }, // Capability, - { 0, 0, false }, // TypeVoid, - { 0, 0, false }, // TypeBool, - { 0, 0, false }, // TypeInt, - { 0, 0, false }, // TypeFloat, - { 0, 0, false }, // TypeVector, - { 0, 0, false }, // TypeMatrix, - { 0, 0, false }, // TypeImage, - { 0, 0, false }, // TypeSampler, - { 0, 0, false }, // TypeSampledImage, - { 0, 0, false }, // TypeArray, - { 0, 0, false }, // TypeRuntimeArray, - { 0, 0, false }, // TypeStruct, - { 0, 0, false }, // TypeOpaque, - { 0, 0, false }, // TypePointer, - { 0, 0, false }, // TypeFunction, - { 0, 0, false }, // TypeEvent, - { 0, 0, false }, // TypeDeviceEvent, - { 0, 0, false }, // TypeReserveId, - { 0, 0, false }, // TypeQueue, - { 0, 0, false }, // TypePipe, - { 0, 0, false }, // TypeForwardPointer, - { 0, 0, false }, // ConstantTrue, - { 0, 0, false }, // ConstantFalse, - { 0, 0, false }, // Constant, - { 0, 0, false }, // ConstantComposite, - { 0, 0, false }, // ConstantSampler, - { 0, 0, false }, // ConstantNull, - { 0, 0, false }, // SpecConstantTrue, - { 0, 0, false }, // SpecConstantFalse, - { 0, 0, false }, // SpecConstant, - { 0, 0, false }, // SpecConstantComposite, - { 0, 0, false }, // SpecConstantOp, - { 0, 0, false }, // Function, - { 0, 0, false }, // FunctionParameter, - { 0, 0, false }, // FunctionEnd, - { 0, 0, false }, // FunctionCall, - { 0, 0, false }, // Variable, - { 0, 0, false }, // ImageTexelPointer, - { 0, 0, false }, // Load, - { 0, 0, false }, // Store, - { 0, 0, false }, // CopyMemory, - { 0, 0, false }, // CopyMemorySized, - { 0, 0, false }, // AccessChain, - { 0, 0, false }, // InBoundsAccessChain, - { 0, 0, false }, // PtrAccessChain, - { 0, 0, false }, // ArrayLength, - { 0, 0, false }, // GenericPtrMemSemantics, - { 0, 0, false }, // InBoundsPtrAccessChain, - { 0, 0, false }, // Decorate, - { 0, 0, false }, // MemberDecorate, - { 0, 0, false }, // DecorationGroup, - { 0, 0, false }, // GroupDecorate, - { 0, 0, false }, // GroupMemberDecorate, - { 0, 0, false }, // VectorExtractDynamic, - { 0, 0, false }, // VectorInsertDynamic, - { 0, 0, false }, // VectorShuffle, - { 0, 0, false }, // CompositeConstruct, - { 0, 0, false }, // CompositeExtract, - { 0, 0, false }, // CompositeInsert, - { 0, 0, false }, // CopyObject, - { 0, 0, false }, // Transpose, - { 0, 0, false }, // SampledImage, - { 0, 0, false }, // ImageSampleImplicitLod, - { 0, 0, false }, // ImageSampleExplicitLod, - { 0, 0, false }, // ImageSampleDrefImplicitLod, - { 0, 0, false }, // ImageSampleDrefExplicitLod, - { 0, 0, false }, // ImageSampleProjImplicitLod, - { 0, 0, false }, // ImageSampleProjExplicitLod, - { 0, 0, false }, // ImageSampleProjDrefImplicitLod, - { 0, 0, false }, // ImageSampleProjDrefExplicitLod, - { 0, 0, false }, // ImageFetch, - { 0, 0, false }, // ImageGather, - { 0, 0, false }, // ImageDrefGather, - { 0, 0, false }, // ImageRead, - { 0, 0, false }, // ImageWrite, - { 0, 0, false }, // Image, - { 0, 0, false }, // ImageQueryFormat, - { 0, 0, false }, // ImageQueryOrder, - { 0, 0, false }, // ImageQuerySizeLod, - { 0, 0, false }, // ImageQuerySize, - { 0, 0, false }, // ImageQueryLod, - { 0, 0, false }, // ImageQueryLevels, - { 0, 0, false }, // ImageQuerySamples, - { 0, 0, false }, // ConvertFToU, - { 0, 0, false }, // ConvertFToS, - { 0, 0, false }, // ConvertSToF, - { 0, 0, false }, // ConvertUToF, - { 0, 0, false }, // UConvert, - { 0, 0, false }, // SConvert, - { 0, 0, false }, // FConvert, - { 0, 0, false }, // QuantizeToF16, - { 0, 0, false }, // ConvertPtrToU, - { 0, 0, false }, // SatConvertSToU, - { 0, 0, false }, // SatConvertUToS, - { 0, 0, false }, // ConvertUToPtr, - { 0, 0, false }, // PtrCastToGeneric, - { 0, 0, false }, // GenericCastToPtr, - { 0, 0, false }, // GenericCastToPtrExplicit, - { 0, 0, false }, // Bitcast, - { 0, 0, false }, // SNegate, - { 0, 0, false }, // FNegate, - { 0, 0, false }, // IAdd, - { 0, 0, false }, // FAdd, - { 0, 0, false }, // ISub, - { 0, 0, false }, // FSub, - { 0, 0, false }, // IMul, - { 0, 0, false }, // FMul, - { 0, 0, false }, // UDiv, - { 0, 0, false }, // SDiv, - { 0, 0, false }, // FDiv, - { 0, 0, false }, // UMod, - { 0, 0, false }, // SRem, - { 0, 0, false }, // SMod, - { 0, 0, false }, // FRem, - { 0, 0, false }, // FMod, - { 0, 0, false }, // VectorTimesScalar, - { 0, 0, false }, // MatrixTimesScalar, - { 0, 0, false }, // VectorTimesMatrix, - { 0, 0, false }, // MatrixTimesVector, - { 0, 0, false }, // MatrixTimesMatrix, - { 0, 0, false }, // OuterProduct, - { 0, 0, false }, // Dot, - { 0, 0, false }, // IAddCarry, - { 0, 0, false }, // ISubBorrow, - { 0, 0, false }, // UMulExtended, - { 0, 0, false }, // SMulExtended, - { 0, 0, false }, // Any, - { 0, 0, false }, // All, - { 0, 0, false }, // IsNan, - { 0, 0, false }, // IsInf, - { 0, 0, false }, // IsFinite, - { 0, 0, false }, // IsNormal, - { 0, 0, false }, // SignBitSet, - { 0, 0, false }, // LessOrGreater, - { 0, 0, false }, // Ordered, - { 0, 0, false }, // Unordered, - { 0, 0, false }, // LogicalEqual, - { 0, 0, false }, // LogicalNotEqual, - { 0, 0, false }, // LogicalOr, - { 0, 0, false }, // LogicalAnd, - { 0, 0, false }, // LogicalNot, - { 0, 0, false }, // Select, - { 0, 0, false }, // IEqual, - { 0, 0, false }, // INotEqual, - { 0, 0, false }, // UGreaterThan, - { 0, 0, false }, // SGreaterThan, - { 0, 0, false }, // UGreaterThanEqual, - { 0, 0, false }, // SGreaterThanEqual, - { 0, 0, false }, // ULessThan, - { 0, 0, false }, // SLessThan, - { 0, 0, false }, // ULessThanEqual, - { 0, 0, false }, // SLessThanEqual, - { 0, 0, false }, // FOrdEqual, - { 0, 0, false }, // FUnordEqual, - { 0, 0, false }, // FOrdNotEqual, - { 0, 0, false }, // FUnordNotEqual, - { 0, 0, false }, // FOrdLessThan, - { 0, 0, false }, // FUnordLessThan, - { 0, 0, false }, // FOrdGreaterThan, - { 0, 0, false }, // FUnordGreaterThan, - { 0, 0, false }, // FOrdLessThanEqual, - { 0, 0, false }, // FUnordLessThanEqual, - { 0, 0, false }, // FOrdGreaterThanEqual, - { 0, 0, false }, // FUnordGreaterThanEqual, - { 0, 0, false }, // ShiftRightLogical, - { 0, 0, false }, // ShiftRightArithmetic, - { 0, 0, false }, // ShiftLeftLogical, - { 0, 0, false }, // BitwiseOr, - { 0, 0, false }, // BitwiseXor, - { 0, 0, false }, // BitwiseAnd, - { 0, 0, false }, // Not, - { 0, 0, false }, // BitFieldInsert, - { 0, 0, false }, // BitFieldSExtract, - { 0, 0, false }, // BitFieldUExtract, - { 0, 0, false }, // BitReverse, - { 0, 0, false }, // BitCount, - { 0, 0, false }, // DPdx, - { 0, 0, false }, // DPdy, - { 0, 0, false }, // Fwidth, - { 0, 0, false }, // DPdxFine, - { 0, 0, false }, // DPdyFine, - { 0, 0, false }, // FwidthFine, - { 0, 0, false }, // DPdxCoarse, - { 0, 0, false }, // DPdyCoarse, - { 0, 0, false }, // FwidthCoarse, - { 0, 0, false }, // EmitVertex, - { 0, 0, false }, // EndPrimitive, - { 0, 0, false }, // EmitStreamVertex, - { 0, 0, false }, // EndStreamPrimitive, - { 0, 0, false }, // ControlBarrier, - { 0, 0, false }, // MemoryBarrier, - { 0, 0, false }, // AtomicLoad, - { 0, 0, false }, // AtomicStore, - { 0, 0, false }, // AtomicExchange, - { 0, 0, false }, // AtomicCompareExchange, - { 0, 0, false }, // AtomicCompareExchangeWeak, - { 0, 0, false }, // AtomicIIncrement, - { 0, 0, false }, // AtomicIDecrement, - { 0, 0, false }, // AtomicIAdd, - { 0, 0, false }, // AtomicISub, - { 0, 0, false }, // AtomicSMin, - { 0, 0, false }, // AtomicUMin, - { 0, 0, false }, // AtomicSMax, - { 0, 0, false }, // AtomicUMax, - { 0, 0, false }, // AtomicAnd, - { 0, 0, false }, // AtomicOr, - { 0, 0, false }, // AtomicXor, - { 0, 0, false }, // Phi, - { 0, 0, false }, // LoopMerge, - { 0, 0, false }, // SelectionMerge, - { 0, 0, false }, // Label, - { 0, 0, false }, // Branch, - { 0, 0, false }, // BranchConditional, - { 0, 0, false }, // Switch, - { 0, 0, false }, // Kill, - { 0, 0, false }, // Return, - { 0, 0, false }, // ReturnValue, - { 0, 0, false }, // Unreachable, - { 0, 0, false }, // LifetimeStart, - { 0, 0, false }, // LifetimeStop, - { 0, 0, false }, // GroupAsyncCopy, - { 0, 0, false }, // GroupWaitEvents, - { 0, 0, false }, // GroupAll, - { 0, 0, false }, // GroupAny, - { 0, 0, false }, // GroupBroadcast, - { 0, 0, false }, // GroupIAdd, - { 0, 0, false }, // GroupFAdd, - { 0, 0, false }, // GroupFMin, - { 0, 0, false }, // GroupUMin, - { 0, 0, false }, // GroupSMin, - { 0, 0, false }, // GroupFMax, - { 0, 0, false }, // GroupUMax, - { 0, 0, false }, // GroupSMax, - { 0, 0, false }, // ReadPipe, - { 0, 0, false }, // WritePipe, - { 0, 0, false }, // ReservedReadPipe, - { 0, 0, false }, // ReservedWritePipe, - { 0, 0, false }, // ReserveReadPipePackets, - { 0, 0, false }, // ReserveWritePipePackets, - { 0, 0, false }, // CommitReadPipe, - { 0, 0, false }, // CommitWritePipe, - { 0, 0, false }, // IsValidReserveId, - { 0, 0, false }, // GetNumPipePackets, - { 0, 0, false }, // GetMaxPipePackets, - { 0, 0, false }, // GroupReserveReadPipePackets, - { 0, 0, false }, // GroupReserveWritePipePackets, - { 0, 0, false }, // GroupCommitReadPipe, - { 0, 0, false }, // GroupCommitWritePipe, - { 0, 0, false }, // EnqueueMarker, - { 0, 0, false }, // EnqueueKernel, - { 0, 0, false }, // GetKernelNDrangeSubGroupCount, - { 0, 0, false }, // GetKernelNDrangeMaxSubGroupSize, - { 0, 0, false }, // GetKernelWorkGroupSize, - { 0, 0, false }, // GetKernelPreferredWorkGroupSizeMultiple, - { 0, 0, false }, // RetainEvent, - { 0, 0, false }, // ReleaseEvent, - { 0, 0, false }, // CreateUserEvent, - { 0, 0, false }, // IsValidEvent, - { 0, 0, false }, // SetUserEventStatus, - { 0, 0, false }, // CaptureEventProfilingInfo, - { 0, 0, false }, // GetDefaultQueue, - { 0, 0, false }, // BuildNDRange, - { 0, 0, false }, // ImageSparseSampleImplicitLod, - { 0, 0, false }, // ImageSparseSampleExplicitLod, - { 0, 0, false }, // ImageSparseSampleDrefImplicitLod, - { 0, 0, false }, // ImageSparseSampleDrefExplicitLod, - { 0, 0, false }, // ImageSparseSampleProjImplicitLod, - { 0, 0, false }, // ImageSparseSampleProjExplicitLod, - { 0, 0, false }, // ImageSparseSampleProjDrefImplicitLod, - { 0, 0, false }, // ImageSparseSampleProjDrefExplicitLod, - { 0, 0, false }, // ImageSparseFetch, - { 0, 0, false }, // ImageSparseGather, - { 0, 0, false }, // ImageSparseDrefGather, - { 0, 0, false }, // ImageSparseTexelsResident, - { 0, 0, false }, // NoLine, - { 0, 0, false }, // AtomicFlagTestAndSet, - { 0, 0, false }, // AtomicFlagClear, - { 0, 0, false }, // ImageSparseRead, +#define SPV_OPERAND_1(_a0) SpvOperand::_a0 +#define SPV_OPERAND_2(_a0, _a1) SPV_OPERAND_1(_a0), SPV_OPERAND_1(_a1) +#define SPV_OPERAND_3(_a0, _a1, _a2) SPV_OPERAND_1(_a0), SPV_OPERAND_2(_a1, _a2) +#define SPV_OPERAND_4(_a0, _a1, _a2, _a3) SPV_OPERAND_1(_a0), SPV_OPERAND_3(_a1, _a2, _a3) +#define SPV_OPERAND_5(_a0, _a1, _a2, _a3, _a4) SPV_OPERAND_1(_a0), SPV_OPERAND_4(_a1, _a2, _a3, _a4) +#define SPV_OPERAND_6(_a0, _a1, _a2, _a3, _a4, _a5) SPV_OPERAND_1(_a0), SPV_OPERAND_5(_a1, _a2, _a3, _a4, _a5) +#define SPV_OPERAND_7(_a0, _a1, _a2, _a3, _a4, _a5, _a6) SPV_OPERAND_1(_a0), SPV_OPERAND_6(_a1, _a2, _a3, _a4, _a5, _a6) +#define SPV_OPERAND_8(_a0, _a1, _a2, _a3, _a4, _a5, _a6, _a7) SPV_OPERAND_1(_a0), SPV_OPERAND_7(_a1, _a2, _a3, _a4, _a5, _a6, _a7) +#define SPV_OPERAND_9(_a0, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) SPV_OPERAND_1(_a0), SPV_OPERAND_8(_a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) +#define SPV_OPERAND(...) { BX_MACRO_DISPATCHER(SPV_OPERAND_, __VA_ARGS__) BX_VA_ARGS_PASS(__VA_ARGS__) } +#define _ Count + { false, false, /* Nop, // 0 */ SPV_OPERAND(_) }, + { true, true, /* Undef, // 1 */ SPV_OPERAND(_) }, + { false, false, /* SourceContinued, // 2 */ SPV_OPERAND(_) }, + { false, false, /* Source, // 3 */ SPV_OPERAND(SourceLanguage, LiteralNumber, Id, LiteralString) }, + { false, false, /* SourceExtension, // 4 */ SPV_OPERAND(LiteralString) }, + { false, true, /* Name, // 5 */ SPV_OPERAND(LiteralString) }, + { false, true, /* MemberName, // 6 */ SPV_OPERAND(LiteralNumber, LiteralString) }, + { false, false, /* String, // 7 */ SPV_OPERAND(_) }, + { false, false, /* Line, // 8 */ SPV_OPERAND(_) }, + { false, false, /* ------------------------------- Invalid9 // 9 */ SPV_OPERAND(_) }, + { false, false, /* Extension, // 10 */ SPV_OPERAND(LiteralString) }, + { false, true, /* ExtInstImport, // 11 */ SPV_OPERAND(LiteralString) }, + { true, true, /* ExtInst, // 12 */ SPV_OPERAND(LiteralNumber) }, + { false, false, /* ------------------------------ Invalid13 // 13 */ SPV_OPERAND(_) }, + { false, false, /* MemoryModel, // 14 */ SPV_OPERAND(AddressingModel, MemoryModel) }, + { false, false, /* EntryPoint, // 15 */ SPV_OPERAND(ExecutionModel, Id, LiteralString) }, + { true, true, /* ExecutionMode, // 16 */ SPV_OPERAND(_) }, + { false, false, /* Capability, // 17 */ SPV_OPERAND(Capability ) }, + { false, false, /* ------------------------------ Invalid18 // 18 */ SPV_OPERAND(_) }, + { false, true, /* TypeVoid, // 19 */ SPV_OPERAND(LiteralNumber) }, + { false, true, /* TypeBool, // 20 */ SPV_OPERAND(LiteralNumber) }, + { false, true, /* TypeInt, // 21 */ SPV_OPERAND(LiteralNumber) }, + { false, true, /* TypeFloat, // 22 */ SPV_OPERAND(LiteralNumber) }, + { false, true, /* TypeVector, // 23 */ SPV_OPERAND(ComponentType, LiteralNumber) }, + { false, true, /* TypeMatrix, // 24 */ SPV_OPERAND(LiteralNumber) }, + { false, true, /* TypeImage, // 25 */ SPV_OPERAND(SampledType, Dim, LiteralNumber, LiteralNumber, LiteralNumber, LiteralNumber, ImageFormat, AccessQualifier) }, + { false, true, /* TypeSampler, // 26 */ SPV_OPERAND(LiteralNumber) }, + { false, true, /* TypeSampledImage, // 27 */ SPV_OPERAND(LiteralNumber) }, + { false, true, /* TypeArray, // 28 */ SPV_OPERAND(LiteralNumber) }, + { false, true, /* TypeRuntimeArray, // 29 */ SPV_OPERAND(_) }, + { false, true, /* TypeStruct, // 30 */ SPV_OPERAND(_) }, + { false, true, /* TypeOpaque, // 31 */ SPV_OPERAND(_) }, + { false, true, /* TypePointer, // 32 */ SPV_OPERAND(StorageClass, Id) }, + { false, true, /* TypeFunction, // 33 */ SPV_OPERAND(Id, Id, Id, Id, Id) }, + { false, true, /* TypeEvent, // 34 */ SPV_OPERAND(_) }, + { false, true, /* TypeDeviceEvent, // 35 */ SPV_OPERAND(_) }, + { false, true, /* TypeReserveId, // 36 */ SPV_OPERAND(_) }, + { false, true, /* TypeQueue, // 37 */ SPV_OPERAND(_) }, + { false, true, /* TypePipe, // 38 */ SPV_OPERAND(_) }, + { false, true, /* TypeForwardPointer, // 39 */ SPV_OPERAND(_) }, + { false, false, /* ------------------------------ Invalid40 // 40 */ SPV_OPERAND(_) }, + { true, true, /* ConstantTrue, // 41 */ SPV_OPERAND(_) }, + { true, true, /* ConstantFalse, // 42 */ SPV_OPERAND(_) }, + { true, true, /* Constant, // 43 */ SPV_OPERAND(LiteralRep) }, + { true, true, /* ConstantComposite, // 44 */ SPV_OPERAND(LiteralRep) }, + { true, true, /* ConstantSampler, // 45 */ SPV_OPERAND(SamplerAddressingMode, LiteralNumber, SamplerFilterMode) }, + { true, true, /* ConstantNull, // 46 */ SPV_OPERAND(_) }, + { false, false, /* ------------------------------ Invalid47 // 47 */ SPV_OPERAND(_) }, + { true, true, /* SpecConstantTrue, // 48 */ SPV_OPERAND(_) }, + { true, true, /* SpecConstantFalse, // 49 */ SPV_OPERAND(_) }, + { true, true, /* SpecConstant, // 50 */ SPV_OPERAND(_) }, + { true, true, /* SpecConstantComposite, // 51 */ SPV_OPERAND(_) }, + { true, true, /* SpecConstantOp, // 52 */ SPV_OPERAND(_) }, + { false, false, /* ------------------------------ Invalid53 // 53 */ SPV_OPERAND(_) }, + { true, true, /* Function, // 54 */ SPV_OPERAND(FunctionControl, Id) }, + { true, true, /* FunctionParameter, // 55 */ SPV_OPERAND(_) }, + { false, false, /* FunctionEnd, // 56 */ SPV_OPERAND(_) }, + { true, true, /* FunctionCall, // 57 */ SPV_OPERAND(Function, IdRep) }, + { false, false, /* ------------------------------ Invalid58 // 58 */ SPV_OPERAND(_) }, + { true, true, /* Variable, // 59 */ SPV_OPERAND(StorageClass, Id) }, + { true, true, /* ImageTexelPointer, // 60 */ SPV_OPERAND(_) }, + { true, true, /* Load, // 61 */ SPV_OPERAND(Pointer, MemoryAccess) }, + { false, false, /* Store, // 62 */ SPV_OPERAND(Pointer, Object, MemoryAccess) }, + { false, false, /* CopyMemory, // 63 */ SPV_OPERAND(_) }, + { false, false, /* CopyMemorySized, // 64 */ SPV_OPERAND(_) }, + { true, true, /* AccessChain, // 65 */ SPV_OPERAND(Base, IdRep) }, + { true, true, /* InBoundsAccessChain, // 66 */ SPV_OPERAND(Base, IdRep) }, + { true, true, /* PtrAccessChain, // 67 */ SPV_OPERAND(_) }, + { true, true, /* ArrayLength, // 68 */ SPV_OPERAND(_) }, + { true, true, /* GenericPtrMemSemantics, // 69 */ SPV_OPERAND(_) }, + { true, true, /* InBoundsPtrAccessChain, // 70 */ SPV_OPERAND(_) }, + { false, false, /* Decorate, // 71 */ SPV_OPERAND(Id, Decoration, LiteralRep) }, + { false, false, /* MemberDecorate, // 72 */ SPV_OPERAND(StructureType, LiteralNumber, Decoration, LiteralRep) }, + { false, false, /* DecorationGroup, // 73 */ SPV_OPERAND(_) }, + { false, false, /* GroupDecorate, // 74 */ SPV_OPERAND(_) }, + { false, false, /* GroupMemberDecorate, // 75 */ SPV_OPERAND(_) }, + { false, false, /* ------------------------------ Invalid76 // 76 */ SPV_OPERAND(_) }, + { true, true, /* VectorExtractDynamic, // 77 */ SPV_OPERAND(_) }, + { true, true, /* VectorInsertDynamic, // 78 */ SPV_OPERAND(_) }, + { true, true, /* VectorShuffle, // 79 */ SPV_OPERAND(Id, Id, LiteralRep) }, + { true, true, /* CompositeConstruct, // 80 */ SPV_OPERAND(IdRep) }, + { true, true, /* CompositeExtract, // 81 */ SPV_OPERAND(Composite, LiteralRep) }, + { true, true, /* CompositeInsert, // 82 */ SPV_OPERAND(Id, Composite, LiteralRep) }, + { true, true, /* CopyObject, // 83 */ SPV_OPERAND(Id) }, + { true, true, /* Transpose, // 84 */ SPV_OPERAND(Matrix) }, + { false, false, /* ------------------------------ Invalid85 // 85 */ SPV_OPERAND(_) }, + { true, true, /* SampledImage, // 86 */ SPV_OPERAND(_) }, + { true, true, /* ImageSampleImplicitLod, // 87 */ SPV_OPERAND(SampledImage, Coordinate, ImageOperands, IdRep) }, + { true, true, /* ImageSampleExplicitLod, // 88 */ SPV_OPERAND(SampledImage, Coordinate, ImageOperands, Id, IdRep) }, + { true, true, /* ImageSampleDrefImplicitLod, // 89 */ SPV_OPERAND(_) }, + { true, true, /* ImageSampleDrefExplicitLod, // 90 */ SPV_OPERAND(_) }, + { true, true, /* ImageSampleProjImplicitLod, // 91 */ SPV_OPERAND(_) }, + { true, true, /* ImageSampleProjExplicitLod, // 92 */ SPV_OPERAND(_) }, + { true, true, /* ImageSampleProjDrefImplicitLod, // 93 */ SPV_OPERAND(_) }, + { true, true, /* ImageSampleProjDrefExplicitLod, // 94 */ SPV_OPERAND(_) }, + { true, true, /* ImageFetch, // 95 */ SPV_OPERAND(_) }, + { true, true, /* ImageGather, // 96 */ SPV_OPERAND(SampledImage, Coordinate, Component, ImageOperands, IdRep) }, + { true, true, /* ImageDrefGather, // 97 */ SPV_OPERAND(SampledImage, Coordinate, Dref, ImageOperands, IdRep) }, + { true, true, /* ImageRead, // 98 */ SPV_OPERAND(_) }, + { false, false, /* ImageWrite, // 99 */ SPV_OPERAND(_) }, + { true, true, /* Image, // 100 */ SPV_OPERAND(_) }, + { true, true, /* ImageQueryFormat, // 101 */ SPV_OPERAND(_) }, + { true, true, /* ImageQueryOrder, // 102 */ SPV_OPERAND(_) }, + { true, true, /* ImageQuerySizeLod, // 103 */ SPV_OPERAND(_) }, + { true, true, /* ImageQuerySize, // 104 */ SPV_OPERAND(_) }, + { true, true, /* ImageQueryLod, // 105 */ SPV_OPERAND(_) }, + { true, true, /* ImageQueryLevels, // 106 */ SPV_OPERAND(_) }, + { true, true, /* ImageQuerySamples, // 107 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid108 // 108 */ SPV_OPERAND(_) }, + { true, true, /* ConvertFToU, // 109 */ SPV_OPERAND(_) }, + { true, true, /* ConvertFToS, // 110 */ SPV_OPERAND(_) }, + { true, true, /* ConvertSToF, // 111 */ SPV_OPERAND(_) }, + { true, true, /* ConvertUToF, // 112 */ SPV_OPERAND(_) }, + { true, true, /* UConvert, // 113 */ SPV_OPERAND(Id) }, + { true, true, /* SConvert, // 114 */ SPV_OPERAND(Id) }, + { true, true, /* FConvert, // 115 */ SPV_OPERAND(Id) }, + { true, true, /* QuantizeToF16, // 116 */ SPV_OPERAND(_) }, + { true, true, /* ConvertPtrToU, // 117 */ SPV_OPERAND(_) }, + { true, true, /* SatConvertSToU, // 118 */ SPV_OPERAND(_) }, + { true, true, /* SatConvertUToS, // 119 */ SPV_OPERAND(_) }, + { true, true, /* ConvertUToPtr, // 120 */ SPV_OPERAND(_) }, + { true, true, /* PtrCastToGeneric, // 121 */ SPV_OPERAND(_) }, + { true, true, /* GenericCastToPtr, // 122 */ SPV_OPERAND(_) }, + { true, true, /* GenericCastToPtrExplicit, // 123 */ SPV_OPERAND(_) }, + { true, true, /* Bitcast, // 124 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid125 // 125 */ SPV_OPERAND(_) }, + { true, true, /* SNegate, // 126 */ SPV_OPERAND(Id) }, + { true, true, /* FNegate, // 127 */ SPV_OPERAND(Id) }, + { true, true, /* IAdd, // 128 */ SPV_OPERAND(Id, Id) }, + { true, true, /* FAdd, // 129 */ SPV_OPERAND(Id, Id) }, + { true, true, /* ISub, // 130 */ SPV_OPERAND(Id, Id) }, + { true, true, /* FSub, // 131 */ SPV_OPERAND(Id, Id) }, + { true, true, /* IMul, // 132 */ SPV_OPERAND(Id, Id) }, + { true, true, /* FMul, // 133 */ SPV_OPERAND(Id, Id) }, + { true, true, /* UDiv, // 134 */ SPV_OPERAND(Id, Id) }, + { true, true, /* SDiv, // 135 */ SPV_OPERAND(Id, Id) }, + { true, true, /* FDiv, // 136 */ SPV_OPERAND(Id, Id) }, + { true, true, /* UMod, // 137 */ SPV_OPERAND(Id, Id) }, + { true, true, /* SRem, // 138 */ SPV_OPERAND(Id, Id) }, + { true, true, /* SMod, // 139 */ SPV_OPERAND(Id, Id) }, + { true, true, /* FRem, // 140 */ SPV_OPERAND(Id, Id) }, + { true, true, /* FMod, // 141 */ SPV_OPERAND(Id, Id) }, + { true, true, /* VectorTimesScalar, // 142 */ SPV_OPERAND(Vector, Scalar) }, + { true, true, /* MatrixTimesScalar, // 143 */ SPV_OPERAND(Matrix, Scalar) }, + { true, true, /* VectorTimesMatrix, // 144 */ SPV_OPERAND(Vector, Matrix) }, + { true, true, /* MatrixTimesVector, // 145 */ SPV_OPERAND(Matrix, Vector) }, + { true, true, /* MatrixTimesMatrix, // 146 */ SPV_OPERAND(Matrix, Matrix) }, + { true, true, /* OuterProduct, // 147 */ SPV_OPERAND(Vector, Vector) }, + { true, true, /* Dot, // 148 */ SPV_OPERAND(Vector, Vector) }, + { true, true, /* IAddCarry, // 149 */ SPV_OPERAND(Id, Id) }, + { true, true, /* ISubBorrow, // 150 */ SPV_OPERAND(Id, Id) }, + { true, true, /* UMulExtended, // 151 */ SPV_OPERAND(Id, Id) }, + { true, true, /* SMulExtended, // 152 */ SPV_OPERAND(Id, Id) }, + { false, false, /* ----------------------------- Invalid153 // 153 */ SPV_OPERAND(_) }, + { true, true, /* Any, // 154 */ SPV_OPERAND(Vector) }, + { true, true, /* All, // 155 */ SPV_OPERAND(Vector) }, + { true, true, /* IsNan, // 156 */ SPV_OPERAND(Id) }, + { true, true, /* IsInf, // 157 */ SPV_OPERAND(Id) }, + { true, true, /* IsFinite, // 158 */ SPV_OPERAND(Id) }, + { true, true, /* IsNormal, // 159 */ SPV_OPERAND(Id) }, + { true, true, /* SignBitSet, // 160 */ SPV_OPERAND(Id) }, + { true, true, /* LessOrGreater, // 161 */ SPV_OPERAND(Id, Id) }, + { true, true, /* Ordered, // 162 */ SPV_OPERAND(Id, Id) }, + { true, true, /* Unordered, // 163 */ SPV_OPERAND(_) }, + { true, true, /* LogicalEqual, // 164 */ SPV_OPERAND(_) }, + { true, true, /* LogicalNotEqual, // 165 */ SPV_OPERAND(_) }, + { true, true, /* LogicalOr, // 166 */ SPV_OPERAND(_) }, + { true, true, /* LogicalAnd, // 167 */ SPV_OPERAND(_) }, + { true, true, /* LogicalNot, // 168 */ SPV_OPERAND(_) }, + { true, true, /* Select, // 169 */ SPV_OPERAND(Condition, Id, Id) }, + { true, true, /* IEqual, // 170 */ SPV_OPERAND(_) }, + { true, true, /* INotEqual, // 171 */ SPV_OPERAND(_) }, + { true, true, /* UGreaterThan, // 172 */ SPV_OPERAND(_) }, + { true, true, /* SGreaterThan, // 173 */ SPV_OPERAND(_) }, + { true, true, /* UGreaterThanEqual, // 174 */ SPV_OPERAND(_) }, + { true, true, /* SGreaterThanEqual, // 175 */ SPV_OPERAND(_) }, + { true, true, /* ULessThan, // 176 */ SPV_OPERAND(_) }, + { true, true, /* SLessThan, // 177 */ SPV_OPERAND(_) }, + { true, true, /* ULessThanEqual, // 178 */ SPV_OPERAND(_) }, + { true, true, /* SLessThanEqual, // 179 */ SPV_OPERAND(_) }, + { true, true, /* FOrdEqual, // 180 */ SPV_OPERAND(_) }, + { true, true, /* FUnordEqual, // 181 */ SPV_OPERAND(_) }, + { true, true, /* FOrdNotEqual, // 182 */ SPV_OPERAND(_) }, + { true, true, /* FUnordNotEqual, // 183 */ SPV_OPERAND(_) }, + { true, true, /* FOrdLessThan, // 184 */ SPV_OPERAND(_) }, + { true, true, /* FUnordLessThan, // 185 */ SPV_OPERAND(_) }, + { true, true, /* FOrdGreaterThan, // 186 */ SPV_OPERAND(_) }, + { true, true, /* FUnordGreaterThan, // 187 */ SPV_OPERAND(_) }, + { true, true, /* FOrdLessThanEqual, // 188 */ SPV_OPERAND(_) }, + { true, true, /* FUnordLessThanEqual, // 189 */ SPV_OPERAND(_) }, + { true, true, /* FOrdGreaterThanEqual, // 190 */ SPV_OPERAND(_) }, + { true, true, /* FUnordGreaterThanEqual, // 191 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid192 // 192 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid193 // 193 */ SPV_OPERAND(_) }, + { true, true, /* ShiftRightLogical, // 194 */ SPV_OPERAND(_) }, + { true, true, /* ShiftRightArithmetic, // 195 */ SPV_OPERAND(_) }, + { true, true, /* ShiftLeftLogical, // 196 */ SPV_OPERAND(_) }, + { true, true, /* BitwiseOr, // 197 */ SPV_OPERAND(_) }, + { true, true, /* BitwiseXor, // 198 */ SPV_OPERAND(_) }, + { true, true, /* BitwiseAnd, // 199 */ SPV_OPERAND(_) }, + { true, true, /* Not, // 200 */ SPV_OPERAND(_) }, + { true, true, /* BitFieldInsert, // 201 */ SPV_OPERAND(_) }, + { true, true, /* BitFieldSExtract, // 202 */ SPV_OPERAND(_) }, + { true, true, /* BitFieldUExtract, // 203 */ SPV_OPERAND(_) }, + { true, true, /* BitReverse, // 204 */ SPV_OPERAND(_) }, + { true, true, /* BitCount, // 205 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid206 // 206 */ SPV_OPERAND(_) }, + { true, true, /* DPdx, // 207 */ SPV_OPERAND(_) }, + { true, true, /* DPdy, // 208 */ SPV_OPERAND(_) }, + { true, true, /* Fwidth, // 209 */ SPV_OPERAND(_) }, + { true, true, /* DPdxFine, // 210 */ SPV_OPERAND(_) }, + { true, true, /* DPdyFine, // 211 */ SPV_OPERAND(_) }, + { true, true, /* FwidthFine, // 212 */ SPV_OPERAND(_) }, + { true, true, /* DPdxCoarse, // 213 */ SPV_OPERAND(_) }, + { true, true, /* DPdyCoarse, // 214 */ SPV_OPERAND(_) }, + { true, true, /* FwidthCoarse, // 215 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid216 // 216 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid217 // 217 */ SPV_OPERAND(_) }, + { false, false, /* EmitVertex, // 218 */ SPV_OPERAND(_) }, + { false, false, /* EndPrimitive, // 219 */ SPV_OPERAND(_) }, + { false, false, /* EmitStreamVertex, // 220 */ SPV_OPERAND(_) }, + { false, false, /* EndStreamPrimitive, // 221 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid222 // 222 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid223 // 223 */ SPV_OPERAND(_) }, + { false, false, /* ControlBarrier, // 224 */ SPV_OPERAND(_) }, + { false, false, /* MemoryBarrier, // 225 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid226 // 226 */ SPV_OPERAND(_) }, + { true, true, /* AtomicLoad, // 227 */ SPV_OPERAND(_) }, + { false, false, /* AtomicStore, // 228 */ SPV_OPERAND(_) }, + { true, true, /* AtomicExchange, // 229 */ SPV_OPERAND(_) }, + { true, true, /* AtomicCompareExchange, // 230 */ SPV_OPERAND(_) }, + { true, true, /* AtomicCompareExchangeWeak, // 231 */ SPV_OPERAND(_) }, + { true, true, /* AtomicIIncrement, // 232 */ SPV_OPERAND(_) }, + { true, true, /* AtomicIDecrement, // 233 */ SPV_OPERAND(_) }, + { true, true, /* AtomicIAdd, // 234 */ SPV_OPERAND(_) }, + { true, true, /* AtomicISub, // 235 */ SPV_OPERAND(_) }, + { true, true, /* AtomicSMin, // 236 */ SPV_OPERAND(_) }, + { true, true, /* AtomicUMin, // 237 */ SPV_OPERAND(_) }, + { true, true, /* AtomicSMax, // 238 */ SPV_OPERAND(_) }, + { true, true, /* AtomicUMax, // 239 */ SPV_OPERAND(_) }, + { true, true, /* AtomicAnd, // 240 */ SPV_OPERAND(_) }, + { true, true, /* AtomicOr, // 241 */ SPV_OPERAND(_) }, + { true, true, /* AtomicXor, // 242 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid243 // 243 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid244 // 244 */ SPV_OPERAND(_) }, + { true, true, /* Phi, // 245 */ SPV_OPERAND(_) }, + { false, false, /* LoopMerge, // 246 */ SPV_OPERAND(_) }, + { false, false, /* SelectionMerge, // 247 */ SPV_OPERAND(_) }, + { false, true, /* Label, // 248 */ SPV_OPERAND(_) }, + { false, false, /* Branch, // 249 */ SPV_OPERAND(Id) }, + { false, false, /* BranchConditional, // 250 */ SPV_OPERAND(Condition, Id, Id, LiteralRep) }, + { false, false, /* Switch, // 251 */ SPV_OPERAND(_) }, + { false, false, /* Kill, // 252 */ SPV_OPERAND(_) }, + { false, false, /* Return, // 253 */ SPV_OPERAND(_) }, + { false, false, /* ReturnValue, // 254 */ SPV_OPERAND(Id) }, + { false, false, /* Unreachable, // 255 */ SPV_OPERAND(_) }, + { false, false, /* LifetimeStart, // 256 */ SPV_OPERAND(_) }, + { false, false, /* LifetimeStop, // 257 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid258 // 258 */ SPV_OPERAND(_) }, + { true, true, /* GroupAsyncCopy, // 259 */ SPV_OPERAND(_) }, + { false, false, /* GroupWaitEvents, // 260 */ SPV_OPERAND(_) }, + { true, true, /* GroupAll, // 261 */ SPV_OPERAND(_) }, + { true, true, /* GroupAny, // 262 */ SPV_OPERAND(_) }, + { true, true, /* GroupBroadcast, // 263 */ SPV_OPERAND(_) }, + { true, true, /* GroupIAdd, // 264 */ SPV_OPERAND(_) }, + { true, true, /* GroupFAdd, // 265 */ SPV_OPERAND(_) }, + { true, true, /* GroupFMin, // 266 */ SPV_OPERAND(_) }, + { true, true, /* GroupUMin, // 267 */ SPV_OPERAND(_) }, + { true, true, /* GroupSMin, // 268 */ SPV_OPERAND(_) }, + { true, true, /* GroupFMax, // 269 */ SPV_OPERAND(_) }, + { true, true, /* GroupUMax, // 270 */ SPV_OPERAND(_) }, + { true, true, /* GroupSMax, // 271 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid272 // 272 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid273 // 273 */ SPV_OPERAND(_) }, + { true, true, /* ReadPipe, // 274 */ SPV_OPERAND(_) }, + { true, true, /* WritePipe, // 275 */ SPV_OPERAND(_) }, + { true, true, /* ReservedReadPipe, // 276 */ SPV_OPERAND(_) }, + { true, true, /* ReservedWritePipe, // 277 */ SPV_OPERAND(_) }, + { true, true, /* ReserveReadPipePackets, // 278 */ SPV_OPERAND(_) }, + { true, true, /* ReserveWritePipePackets, // 279 */ SPV_OPERAND(_) }, + { false, false, /* CommitReadPipe, // 280 */ SPV_OPERAND(_) }, + { false, false, /* CommitWritePipe, // 281 */ SPV_OPERAND(_) }, + { true, true, /* IsValidReserveId, // 282 */ SPV_OPERAND(_) }, + { true, true, /* GetNumPipePackets, // 283 */ SPV_OPERAND(_) }, + { true, true, /* GetMaxPipePackets, // 284 */ SPV_OPERAND(_) }, + { true, true, /* GroupReserveReadPipePackets, // 285 */ SPV_OPERAND(_) }, + { true, true, /* GroupReserveWritePipePackets, // 286 */ SPV_OPERAND(_) }, + { false, false, /* GroupCommitReadPipe, // 287 */ SPV_OPERAND(_) }, + { false, false, /* GroupCommitWritePipe, // 288 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid289 // 289 */ SPV_OPERAND(_) }, + { false, false, /* ----------------------------- Invalid290 // 290 */ SPV_OPERAND(_) }, + { true, true, /* EnqueueMarker, // 291 */ SPV_OPERAND(_) }, + { true, true, /* EnqueueKernel, // 292 */ SPV_OPERAND(_) }, + { true, true, /* GetKernelNDrangeSubGroupCount, // 293 */ SPV_OPERAND(_) }, + { true, true, /* GetKernelNDrangeMaxSubGroupSize, // 294 */ SPV_OPERAND(_) }, + { true, true, /* GetKernelWorkGroupSize, // 295 */ SPV_OPERAND(_) }, + { true, true, /* GetKernelPreferredWorkGroupSizeMultiple, // 296 */ SPV_OPERAND(_) }, + { false, false, /* RetainEvent, // 297 */ SPV_OPERAND(_) }, + { false, false, /* ReleaseEvent, // 298 */ SPV_OPERAND(_) }, + { true, true, /* CreateUserEvent, // 299 */ SPV_OPERAND(_) }, + { true, true, /* IsValidEvent, // 300 */ SPV_OPERAND(_) }, + { false, false, /* SetUserEventStatus, // 301 */ SPV_OPERAND(_) }, + { false, false, /* CaptureEventProfilingInfo, // 302 */ SPV_OPERAND(_) }, + { true, true, /* GetDefaultQueue, // 303 */ SPV_OPERAND(_) }, + { true, true, /* BuildNDRange, // 304 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseSampleImplicitLod, // 305 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseSampleExplicitLod, // 306 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseSampleDrefImplicitLod, // 307 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseSampleDrefExplicitLod, // 308 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseSampleProjImplicitLod, // 309 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseSampleProjExplicitLod, // 310 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseSampleProjDrefImplicitLod, // 311 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseSampleProjDrefExplicitLod, // 312 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseFetch, // 313 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseGather, // 314 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseDrefGather, // 315 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseTexelsResident, // 316 */ SPV_OPERAND(_) }, + { false, false, /* NoLine, // 317 */ SPV_OPERAND(_) }, + { true, true, /* AtomicFlagTestAndSet, // 318 */ SPV_OPERAND(_) }, + { false, false, /* AtomicFlagClear, // 319 */ SPV_OPERAND(_) }, + { true, true, /* ImageSparseRead, // 320 */ SPV_OPERAND(_) }, +#undef _ +#undef SPV_OPERAND }; - BX_STATIC_ASSERT(BX_COUNTOF(s_sprivOpcodeInfo) == SpirvOpcode::Count); + BX_STATIC_ASSERT(BX_COUNTOF(s_spvOpcodeInfo) == SpvOpcode::Count); - const char* s_spirvOpcode[] = + const char* s_spvOpcode[] = { "Nop", "Undef", @@ -325,13 +365,16 @@ namespace bgfx "MemberName", "String", "Line", + "Invalid9", "Extension", "ExtInstImport", "ExtInst", + "Invalid13", "MemoryModel", "EntryPoint", "ExecutionMode", "Capability", + "Invalid18", "TypeVoid", "TypeBool", "TypeInt", @@ -353,21 +396,25 @@ namespace bgfx "TypeQueue", "TypePipe", "TypeForwardPointer", + "Invalid40", "ConstantTrue", "ConstantFalse", "Constant", "ConstantComposite", "ConstantSampler", "ConstantNull", + "Invalid47", "SpecConstantTrue", "SpecConstantFalse", "SpecConstant", "SpecConstantComposite", "SpecConstantOp", + "Invalid53", "Function", "FunctionParameter", "FunctionEnd", "FunctionCall", + "Invalid58", "Variable", "ImageTexelPointer", "Load", @@ -385,6 +432,7 @@ namespace bgfx "DecorationGroup", "GroupDecorate", "GroupMemberDecorate", + "Invalid76", "VectorExtractDynamic", "VectorInsertDynamic", "VectorShuffle", @@ -393,6 +441,7 @@ namespace bgfx "CompositeInsert", "CopyObject", "Transpose", + "Invalid85", "SampledImage", "ImageSampleImplicitLod", "ImageSampleExplicitLod", @@ -415,6 +464,7 @@ namespace bgfx "ImageQueryLod", "ImageQueryLevels", "ImageQuerySamples", + "Invalid108", "ConvertFToU", "ConvertFToS", "ConvertSToF", @@ -431,6 +481,7 @@ namespace bgfx "GenericCastToPtr", "GenericCastToPtrExplicit", "Bitcast", + "Invalid125", "SNegate", "FNegate", "IAdd", @@ -458,6 +509,7 @@ namespace bgfx "ISubBorrow", "UMulExtended", "SMulExtended", + "Invalid153", "Any", "All", "IsNan", @@ -496,6 +548,8 @@ namespace bgfx "FUnordLessThanEqual", "FOrdGreaterThanEqual", "FUnordGreaterThanEqual", + "Invalid192", + "Invalid193", "ShiftRightLogical", "ShiftRightArithmetic", "ShiftLeftLogical", @@ -508,6 +562,7 @@ namespace bgfx "BitFieldUExtract", "BitReverse", "BitCount", + "Invalid206", "DPdx", "DPdy", "Fwidth", @@ -517,12 +572,17 @@ namespace bgfx "DPdxCoarse", "DPdyCoarse", "FwidthCoarse", + "Invalid216", + "Invalid217", "EmitVertex", "EndPrimitive", "EmitStreamVertex", + "Invalid222", + "Invalid223", "EndStreamPrimitive", "ControlBarrier", "MemoryBarrier", + "Invalid226", "AtomicLoad", "AtomicStore", "AtomicExchange", @@ -539,6 +599,8 @@ namespace bgfx "AtomicAnd", "AtomicOr", "AtomicXor", + "Invalid243", + "Invalid244", "Phi", "LoopMerge", "SelectionMerge", @@ -552,6 +614,7 @@ namespace bgfx "Unreachable", "LifetimeStart", "LifetimeStop", + "Invalid258", "GroupAsyncCopy", "GroupWaitEvents", "GroupAll", @@ -565,6 +628,8 @@ namespace bgfx "GroupFMax", "GroupUMax", "GroupSMax", + "Invalid272", + "Invalid273", "ReadPipe", "WritePipe", "ReservedReadPipe", @@ -580,6 +645,8 @@ namespace bgfx "GroupReserveWritePipePackets", "GroupCommitReadPipe", "GroupCommitWritePipe", + "Invalid289", + "Invalid290", "EnqueueMarker", "EnqueueKernel", "GetKernelNDrangeSubGroupCount", @@ -611,165 +678,301 @@ namespace bgfx "AtomicFlagClear", "ImageSparseRead", }; - BX_STATIC_ASSERT(BX_COUNTOF(s_spirvOpcode) == SpirvOpcode::Count); + BX_STATIC_ASSERT(BX_COUNTOF(s_spvOpcode) == SpvOpcode::Count); - const char* getName(SpirvOpcode::Enum _opcode) + const char* getName(SpvOpcode::Enum _opcode) { - BX_CHECK(_opcode < SpirvOpcode::Count, "Unknown opcode id %d.", _opcode); - return s_spirvOpcode[_opcode]; + BX_WARN(_opcode < SpvOpcode::Count, "Unknown opcode id %d.", _opcode); + return _opcode < SpvOpcode::Count + ? s_spvOpcode[_opcode] + : "?SpvOpcode?" + ; } - int32_t read(bx::ReaderI* _reader, SpirvOperand& _operand) + static const char* s_spvStorageClass[] = + { + "UniformConstant", + "Input", + "Uniform", + "Output", + "Workgroup", + "CrossWorkgroup", + "Private", + "Function", + "Generic", + "PushConstant", + "AtomicCounter", + "Image", + }; + BX_STATIC_ASSERT(BX_COUNTOF(s_spvStorageClass) == SpvStorageClass::Count); + + const char* getName(SpvStorageClass::Enum _enum) + { + BX_CHECK(_enum < SpvStorageClass::Count, "Unknown storage class id %d.", _enum); + return _enum < SpvStorageClass::Count + ? s_spvStorageClass[_enum] + : "?SpvStorageClass?" + ; + } + + int32_t read(bx::ReaderI* _reader, SpvOperand& _operand, bx::Error* _err) { int32_t size = 0; - BX_UNUSED(_operand); uint32_t token; - size += bx::read(_reader, token); + _operand.literalString = ""; + + switch (_operand.type) + { + case SpvOperand::LiteralString: + do + { + size += bx::read(_reader, token, _err); + _operand.literalString.append( (char*)&token, (char*)&token + sizeof(token) ); + } + while (0 != (token & 0xff000000) && _err->isOk() ); + break; + + default: + size += bx::read(_reader, _operand.data[0], _err); + break; + } return size; } - int32_t read(bx::ReaderI* _reader, SpirvInstruction& _instruction) + int32_t read(bx::ReaderI* _reader, SpvInstruction& _instruction, bx::Error* _err) { int32_t size = 0; uint32_t token; - size += bx::read(_reader, token); + size += bx::read(_reader, token, _err); - _instruction.opcode = SpirvOpcode::Enum( (token & UINT32_C(0x0000ffff) ) ); - _instruction.length = uint16_t( (token & UINT32_C(0xffff0000) ) >> 16); + _instruction.opcode = SpvOpcode::Enum( (token & UINT32_C(0x0000ffff) ) ); + _instruction.length = uint16_t( (token & UINT32_C(0xffff0000) ) >> 16); + + if (_instruction.opcode >= SpvOpcode::Count) + { + BX_ERROR_SET(_err, BGFX_SHADER_SPIRV_INVALID_INSTRUCTION, "SPIR-V: Invalid instruction."); + return size; + } + + if (0 == _instruction.length) + { + return size; + } + + const SpvOpcodeInfo& info = s_spvOpcodeInfo[_instruction.opcode]; + _instruction.hasType = info.hasType; + _instruction.hasResult = info.hasResult; + + if (info.hasType) + { + size += read(_reader, _instruction.type, _err); + } + + if (info.hasResult) + { + size += read(_reader, _instruction.result, _err); + } uint32_t currOp = 0; - - const SpirvOpcodeInfo& info = s_sprivOpcodeInfo[_instruction.opcode]; - - if (0 < info.numValues) + switch (_instruction.opcode) { - size += read(_reader, _instruction.un.value, info.numValues*sizeof(uint32_t) ); - } + case SpvOpcode::EntryPoint: + _instruction.operand[currOp].type = info.operands[currOp]; + size += read(_reader, _instruction.operand[currOp++], _err); + _instruction.operand[currOp].type = info.operands[currOp]; + size += read(_reader, _instruction.operand[currOp++], _err); + _instruction.operand[currOp].type = info.operands[currOp]; + size += read(_reader, _instruction.operand[currOp++], _err); - if (info.hasVariable) - { - while (size/4 != _instruction.length) + _instruction.operand[currOp].type = SpvOperand::Id; + for (uint32_t ii = 0, num = _instruction.length - size/4; ii < num; ++ii) { - uint32_t tmp; - size += bx::read(_reader, tmp); + size += read(_reader, _instruction.operand[currOp], _err); } - } - else - { - _instruction.numOperands = info.numOperands; - switch (info.numOperands) + break; + + default: + for (;size/4 != _instruction.length && _err->isOk(); ++currOp) { - case 6: size += read(_reader, _instruction.operand[currOp++]); - case 5: size += read(_reader, _instruction.operand[currOp++]); - case 4: size += read(_reader, _instruction.operand[currOp++]); - case 3: size += read(_reader, _instruction.operand[currOp++]); - case 2: size += read(_reader, _instruction.operand[currOp++]); - case 1: size += read(_reader, _instruction.operand[currOp++]); - case 0: + _instruction.operand[currOp].type = info.operands[currOp]; + size += read(_reader, _instruction.operand[currOp], _err); + } + break; + } + + _instruction.numOperands = currOp; + + return size; + } + + int32_t write(bx::WriterI* _writer, const SpvInstruction& _instruction, bx::Error* _err) + { + int32_t size = 0; + BX_UNUSED(_writer, _instruction, _err); + return size; + } + + int32_t toString(char* _out, int32_t _size, const SpvInstruction& _instruction) + { + int32_t size = 0; + + if (_instruction.hasResult) + { + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , " %%%d = " + , _instruction.result + ); + } + + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , "%s" + , getName(_instruction.opcode) + ); + + for (uint32_t ii = 0, num = _instruction.numOperands; ii < num; ++ii) + { + const SpvOperand& operand = _instruction.operand[ii]; + switch (operand.type) + { + case SpvOperand::AddressingModel: + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , "%sAddressingModel(%d)" + , 0 == ii ? " " : ", " + , operand.data[0] + ); + break; + + case SpvOperand::FunctionControl: + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , "%s0x%08x" + , 0 == ii ? " " : ", " + , operand.data[0] + ); + break; + + case SpvOperand::LiteralNumber: + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , "%s%d" + , 0 == ii ? " " : ", " + , operand.data[0] + ); + break; + + case SpvOperand::LiteralString: + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , "%s%s" + , 0 == ii ? " " : ", " + , operand.literalString.c_str() + ); + break; + + case SpvOperand::MemoryModel: + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , "%sMemoryModel(%d)" + , 0 == ii ? " " : ", " + , operand.data[0] + ); + break; + + case SpvOperand::StorageClass: + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , "%s%s" + , 0 == ii ? " " : ", " + , getName(SpvStorageClass::Enum(operand.data[0]) ) + ); + break; + + case SpvOperand::Count: + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , "%s__%d__" + , 0 == ii ? " " : ", " + , operand.data[0] + ); break; default: - BX_WARN(false, "Instruction %s with invalid number of operands %d (numValues %d)." - , getName(_instruction.opcode) - , info.numOperands - , info.numValues - ); + size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) + , "%s%%%d" + , 0 == ii ? " " : ", " + , operand.data[0] + ); break; - } - BX_WARN(size/4 == _instruction.length, "read %d, expected %d, %s" - , size/4 - , _instruction.length - , getName(_instruction.opcode) - ); - while (size/4 != _instruction.length) - { - uint32_t tmp; - size += bx::read(_reader, tmp); } } return size; } - int32_t write(bx::WriterI* _writer, const SpirvInstruction& _instruction) + int32_t read(bx::ReaderSeekerI* _reader, SpvShader& _shader, bx::Error* _err) { int32_t size = 0; - BX_UNUSED(_writer, _instruction); - return size; - } - int32_t toString(char* _out, int32_t _size, const SpirvInstruction& _instruction) - { - int32_t size = 0; - size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) - , "%s %d (%d, %d)" - , getName(_instruction.opcode) - , _instruction.numOperands - , _instruction.un.value[0] - , _instruction.un.value[1] - ); + uint32_t numBytes = uint32_t(bx::getSize(_reader) - bx::seek(_reader) ); + _shader.byteCode.resize(numBytes); + size += bx::read(_reader, _shader.byteCode.data(), numBytes, _err); return size; } - int32_t read(bx::ReaderSeekerI* _reader, SpirvShader& _shader) + int32_t write(bx::WriterI* _writer, const SpvShader& _shader, bx::Error* _err) { int32_t size = 0; - - uint32_t len = uint32_t(bx::getSize(_reader) - bx::seek(_reader) ); - _shader.byteCode.resize(len); - size += bx::read(_reader, _shader.byteCode.data(), len); - - return size; - } - - int32_t write(bx::WriterI* _writer, const SpirvShader& _shader) - { - int32_t size = 0; - BX_UNUSED(_writer, _shader); + BX_UNUSED(_writer, _shader, _err); return size; } #define SPIRV_MAGIC 0x07230203 - int32_t read(bx::ReaderSeekerI* _reader, Spirv& _spirv) + int32_t read(bx::ReaderSeekerI* _reader, SpirV& _spirv, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + int32_t size = 0; - size += bx::read(_reader, _spirv.header); + size += bx::read(_reader, _spirv.header, _err); - if (size != sizeof(Spirv::Header) + if (!_err->isOk() + || size != sizeof(SpirV::Header) || _spirv.header.magic != SPIRV_MAGIC ) { - // error - return -size; + BX_ERROR_SET(_err, BGFX_SHADER_SPIRV_INVALID_HEADER, "SPIR-V: Invalid header."); + return size; } - size += read(_reader, _spirv.shader); + size += read(_reader, _spirv.shader, _err); return size; } - int32_t write(bx::WriterSeekerI* _writer, const Spirv& _spirv) + int32_t write(bx::WriterSeekerI* _writer, const SpirV& _spirv, bx::Error* _err) { int32_t size = 0; - BX_UNUSED(_writer, _spirv); + BX_UNUSED(_writer, _spirv, _err); return size; } - void parse(const SpirvShader& _src, SpirvParseFn _fn, void* _userData) + void parse(const SpvShader& _src, SpirvParseFn _fn, void* _userData, bx::Error* _err) { - bx::MemoryReader reader(_src.byteCode.data(), uint32_t(_src.byteCode.size() ) ); + BX_ERROR_SCOPE(_err); + + uint32_t numBytes = uint32_t(_src.byteCode.size() ); + bx::MemoryReader reader(_src.byteCode.data(), numBytes); for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;) { - SpirvInstruction instruction; - uint32_t size = read(&reader, instruction); + SpvInstruction instruction; + uint32_t size = read(&reader, instruction, _err); + + if (!_err->isOk() ) + { + return; + } + BX_CHECK(size/4 == instruction.length, "read %d, expected %d, %s" , size/4 , instruction.length diff --git a/src/shader_spirv.h b/src/shader_spirv.h index b083d122..9a7c81b1 100644 --- a/src/shader_spirv.h +++ b/src/shader_spirv.h @@ -8,11 +8,14 @@ #include +BX_ERROR_RESULT(BGFX_SHADER_SPIRV_INVALID_HEADER, BX_MAKEFOURCC('S', 'H', 0, 1) ); +BX_ERROR_RESULT(BGFX_SHADER_SPIRV_INVALID_INSTRUCTION, BX_MAKEFOURCC('S', 'H', 0, 2) ); + namespace bgfx { // Reference: https://www.khronos.org/registry/spir-v/specs/1.0/SPIRV.html - struct SpirvOpcode + struct SpvOpcode { enum Enum { @@ -25,13 +28,16 @@ namespace bgfx MemberName, String, Line, + Invalid9, Extension, ExtInstImport, ExtInst, + Invalid13, MemoryModel, EntryPoint, ExecutionMode, Capability, + Invalid18, TypeVoid, TypeBool, TypeInt, @@ -53,21 +59,25 @@ namespace bgfx TypeQueue, TypePipe, TypeForwardPointer, + Invalid40, ConstantTrue, ConstantFalse, Constant, ConstantComposite, ConstantSampler, ConstantNull, + Invalid47, SpecConstantTrue, SpecConstantFalse, SpecConstant, SpecConstantComposite, SpecConstantOp, + Invalid53, Function, FunctionParameter, FunctionEnd, FunctionCall, + Invalid58, Variable, ImageTexelPointer, Load, @@ -85,6 +95,7 @@ namespace bgfx DecorationGroup, GroupDecorate, GroupMemberDecorate, + Invalid76, VectorExtractDynamic, VectorInsertDynamic, VectorShuffle, @@ -93,6 +104,7 @@ namespace bgfx CompositeInsert, CopyObject, Transpose, + Invalid85, SampledImage, ImageSampleImplicitLod, ImageSampleExplicitLod, @@ -115,6 +127,7 @@ namespace bgfx ImageQueryLod, ImageQueryLevels, ImageQuerySamples, + Invalid108, ConvertFToU, ConvertFToS, ConvertSToF, @@ -131,6 +144,7 @@ namespace bgfx GenericCastToPtr, GenericCastToPtrExplicit, Bitcast, + Invalid125, SNegate, FNegate, IAdd, @@ -158,6 +172,7 @@ namespace bgfx ISubBorrow, UMulExtended, SMulExtended, + Invalid153, Any, All, IsNan, @@ -196,6 +211,8 @@ namespace bgfx FUnordLessThanEqual, FOrdGreaterThanEqual, FUnordGreaterThanEqual, + Invalid192, + Invalid193, ShiftRightLogical, ShiftRightArithmetic, ShiftLeftLogical, @@ -208,6 +225,7 @@ namespace bgfx BitFieldUExtract, BitReverse, BitCount, + Invalid206, DPdx, DPdy, Fwidth, @@ -217,12 +235,17 @@ namespace bgfx DPdxCoarse, DPdyCoarse, FwidthCoarse, + Invalid216, + Invalid217, EmitVertex, EndPrimitive, EmitStreamVertex, EndStreamPrimitive, + Invalid222, + Invalid223, ControlBarrier, MemoryBarrier, + Invalid226, AtomicLoad, AtomicStore, AtomicExchange, @@ -239,6 +262,8 @@ namespace bgfx AtomicAnd, AtomicOr, AtomicXor, + Invalid243, + Invalid244, Phi, LoopMerge, SelectionMerge, @@ -252,6 +277,7 @@ namespace bgfx Unreachable, LifetimeStart, LifetimeStop, + Invalid258, GroupAsyncCopy, GroupWaitEvents, GroupAll, @@ -265,6 +291,8 @@ namespace bgfx GroupFMax, GroupUMax, GroupSMax, + Invalid272, + Invalid273, ReadPipe, WritePipe, ReservedReadPipe, @@ -280,6 +308,8 @@ namespace bgfx GroupReserveWritePipePackets, GroupCommitReadPipe, GroupCommitWritePipe, + Invalid289, + Invalid290, EnqueueMarker, EnqueueKernel, GetKernelNDrangeSubGroupCount, @@ -360,10 +390,12 @@ namespace bgfx SubgroupLocalInvocationId, VertexIndex, InstanceIndex, + + Count }; }; - struct SpirvExecutionModel + struct SpvExecutionModel { enum Enum { @@ -379,7 +411,19 @@ namespace bgfx }; }; - struct SpirvMemoryModel + struct SpvAddressingModel + { + enum Enum + { + Logical, + Physical32, + Physical64, + + Count + }; + }; + + struct SpvMemoryModel { enum Enum { @@ -391,7 +435,7 @@ namespace bgfx }; }; - struct SpirvStorageClass + struct SpvStorageClass { enum Enum { @@ -407,10 +451,12 @@ namespace bgfx PushConstant, AtomicCounter, Image, + + Count }; }; - struct SpirvResourceDim + struct SpvResourceDim { enum Enum { @@ -424,7 +470,7 @@ namespace bgfx }; }; - struct SpirvDecoration + struct SpvDecoration { enum Enum { @@ -476,52 +522,90 @@ namespace bgfx }; }; - struct SpirvOperand + struct SpvOperand { - }; - - struct SpirvInstruction - { - SpirvOpcode::Enum opcode; - uint16_t length; - - uint8_t numOperands; - SpirvOperand operand[6]; - - union + enum Enum { - struct ResultTypeId - { - uint32_t resultType; - uint32_t id; - }; + AccessQualifier, + AddressingModel, + Base, + Capability, + Component, + ComponentType, + Composite, + Condition, + Coordinate, + Decoration, + Dim, + Dref, + ExecutionModel, + Function, + FunctionControl, + Id, + IdRep, + ImageFormat, + ImageOperands, + LiteralNumber, + LiteralRep, + LiteralString, + Matrix, + MemoryAccess, + MemoryModel, + Object, + Pointer, + SampledType, + SampledImage, + SamplerAddressingMode, + SamplerFilterMode, + Scalar, + SourceLanguage, + StorageClass, + StructureType, + Vector, - ResultTypeId constant; - ResultTypeId constantComposite; + Count + }; - uint32_t value[8]; - } un; + Enum type; + uint32_t data[4]; + + uint32_t target; + stl::string literalString; }; - int32_t read(bx::ReaderI* _reader, SpirvInstruction& _instruction); - int32_t write(bx::WriterI* _writer, const SpirvInstruction& _instruction); - int32_t toString(char* _out, int32_t _size, const SpirvInstruction& _instruction); + struct SpvInstruction + { + SpvOpcode::Enum opcode; + uint16_t length; + uint16_t numOperands; - struct SpirvShader + uint32_t type; + uint32_t result; + bool hasType; + bool hasResult; + + SpvOperand operand[8]; + }; + + int32_t read(bx::ReaderI* _reader, SpvInstruction& _instruction, bx::Error* _err); + int32_t write(bx::WriterI* _writer, const SpvInstruction& _instruction, bx::Error* _err); + int32_t toString(char* _out, int32_t _size, const SpvInstruction& _instruction); + + struct SpvShader { stl::vector byteCode; }; - int32_t read(bx::ReaderSeekerI* _reader, SpirvShader& _shader); - int32_t write(bx::WriterI* _writer, const SpirvShader& _shader); + int32_t read(bx::ReaderSeekerI* _reader, SpvShader& _shader, bx::Error* _err); + int32_t write(bx::WriterI* _writer, const SpvShader& _shader, bx::Error* _err); - typedef bool (*SpirvParseFn)(uint32_t _offset, const SpirvInstruction& _instruction, void* _userData); - void parse(const SpirvShader& _src, SpirvParseFn _fn, void* _userData); + typedef bool (*SpirvParseFn)(uint32_t _offset, const SpvInstruction& _instruction, void* _userData); + void parse(const SpvShader& _src, SpirvParseFn _fn, void* _userData, bx::Error* _err = NULL); - typedef void (*SpirvFilterFn)(SpirvInstruction& _instruction, void* _userData); - void filter(SpirvShader& _dst, const SpirvShader& _src, SpirvFilterFn _fn, void* _userData); + typedef void (*SpirvFilterFn)(SpvInstruction& _instruction, void* _userData); + void filter(SpvShader& _dst, const SpvShader& _src, SpirvFilterFn _fn, void* _userData, bx::Error* _err = NULL); - struct Spirv + struct SpirV { struct Header { @@ -533,11 +617,11 @@ namespace bgfx }; Header header; - SpirvShader shader; + SpvShader shader; }; - int32_t read(bx::ReaderSeekerI* _reader, Spirv& _spirv); - int32_t write(bx::WriterSeekerI* _writer, const Spirv& _spirv); + int32_t read(bx::ReaderSeekerI* _reader, SpirV& _spirv, bx::Error* _err); + int32_t write(bx::WriterSeekerI* _writer, const SpirV& _spirv, bx::Error* _err); } // namespace bgfx