mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-22 19:50:05 +00:00
Preserve float values during encoding and decoding roundtrip.
This commit is contained in:
parent
cfeac48a37
commit
610c525865
@ -96,6 +96,7 @@ include_directories(
|
||||
|
||||
set(SPIRV_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/utils/bitwisecast.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/binary.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/diagnostic.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/opcode.h
|
||||
|
41
include/utils/bitwisecast.h
Normal file
41
include/utils/bitwisecast.h
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2015 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
// "Materials"), to deal in the Materials without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
// permit persons to whom the Materials are furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
||||
// https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace spvutils {
|
||||
|
||||
// Performs a bitwise copy of source to the destination type Dest.
|
||||
template <typename Dest, typename Src>
|
||||
Dest BitwiseCast(Src source) {
|
||||
Dest dest;
|
||||
static_assert(sizeof(source) == sizeof(dest),
|
||||
"BitwiseCast: Source and destination must have the same size");
|
||||
std::memcpy(&dest, &source, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
} // namespace spvutils
|
@ -25,6 +25,8 @@
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <libspirv/libspirv.h>
|
||||
#include <utils/bitwisecast.h>
|
||||
|
||||
#include "binary.h"
|
||||
#include "diagnostic.h"
|
||||
#include "ext_inst.h"
|
||||
@ -41,6 +43,8 @@
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
using spvutils::BitwiseCast;
|
||||
|
||||
// Structures
|
||||
|
||||
struct spv_named_id_table_t {
|
||||
@ -434,13 +438,13 @@ spv_result_t spvTextEncodeOperand(
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
switch (literal.type) {
|
||||
case SPV_LITERAL_TYPE_INT_32:
|
||||
spvCheck(spvBinaryEncodeU32((uint32_t)literal.value.i32, pInst,
|
||||
position, pDiagnostic),
|
||||
spvCheck(spvBinaryEncodeU32(BitwiseCast<uint32_t>(literal.value.i32),
|
||||
pInst, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
break;
|
||||
case SPV_LITERAL_TYPE_INT_64: {
|
||||
spvCheck(spvBinaryEncodeU64((uint64_t)literal.value.i64, pInst,
|
||||
position, pDiagnostic),
|
||||
spvCheck(spvBinaryEncodeU64(BitwiseCast<uint64_t>(literal.value.i64),
|
||||
pInst, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_UINT_32: {
|
||||
@ -449,18 +453,18 @@ spv_result_t spvTextEncodeOperand(
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_UINT_64: {
|
||||
spvCheck(spvBinaryEncodeU64((uint64_t)literal.value.u64, pInst,
|
||||
position, pDiagnostic),
|
||||
spvCheck(spvBinaryEncodeU64(BitwiseCast<uint64_t>(literal.value.u64),
|
||||
pInst, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_FLOAT_32: {
|
||||
spvCheck(spvBinaryEncodeU32((uint32_t)literal.value.f, pInst,
|
||||
position, pDiagnostic),
|
||||
spvCheck(spvBinaryEncodeU32(BitwiseCast<uint32_t>(literal.value.f),
|
||||
pInst, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_FLOAT_64: {
|
||||
spvCheck(spvBinaryEncodeU64((uint64_t)literal.value.d, pInst,
|
||||
position, pDiagnostic),
|
||||
spvCheck(spvBinaryEncodeU64(BitwiseCast<uint64_t>(literal.value.d),
|
||||
pInst, position, pDiagnostic),
|
||||
return SPV_ERROR_INVALID_TEXT);
|
||||
} break;
|
||||
case SPV_LITERAL_TYPE_STRING: {
|
||||
|
@ -93,6 +93,35 @@ class TextToBinaryTestBase : public T {
|
||||
return diagnostic->error;
|
||||
}
|
||||
|
||||
// Encodes SPIR-V text into binary and then decodes the binary. Returns the
|
||||
// decoded text.
|
||||
std::string EncodeAndDecodeSuccessfully(const std::string& text_string) {
|
||||
SetText(text_string);
|
||||
DestroyBinary();
|
||||
spv_result_t error = spvTextToBinary(&text, opcodeTable, operandTable,
|
||||
extInstTable, &binary, &diagnostic);
|
||||
if (error) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
}
|
||||
EXPECT_EQ(SPV_SUCCESS, error);
|
||||
|
||||
spv_text decoded_text;
|
||||
error =
|
||||
spvBinaryToText(binary, SPV_BINARY_TO_TEXT_OPTION_NONE, opcodeTable,
|
||||
operandTable, extInstTable, &decoded_text, &diagnostic);
|
||||
if (error) {
|
||||
spvDiagnosticPrint(diagnostic);
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
}
|
||||
EXPECT_EQ(SPV_SUCCESS, error);
|
||||
|
||||
const std::string decoded_string = decoded_text->str;
|
||||
spvTextDestroy(decoded_text);
|
||||
|
||||
return decoded_string;
|
||||
}
|
||||
|
||||
void SetText(const std::string& code) {
|
||||
textString = code;
|
||||
text.str = textString.c_str();
|
||||
|
@ -24,6 +24,7 @@
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include <utils/bitwisecast.h>
|
||||
#include "TestFixture.h"
|
||||
#include "UnitSPIRV.h"
|
||||
#include <algorithm>
|
||||
@ -33,7 +34,8 @@
|
||||
|
||||
namespace {
|
||||
|
||||
using test_fixture::TextToBinaryTest;
|
||||
using spvutils::BitwiseCast;
|
||||
using test_fixture::TextToBinaryTest;
|
||||
|
||||
union char_word_t {
|
||||
char cs[4];
|
||||
@ -403,23 +405,36 @@ TEST_F(TextToBinaryTest, BadSwitchTruncatedCase) {
|
||||
EXPECT_STREQ("Expected operand, found next instruction instead.", diagnostic->error);
|
||||
}
|
||||
|
||||
using TextToBinaryFloatValueTest =
|
||||
test_fixture::TextToBinaryTestBase<::testing::TestWithParam<float>>;
|
||||
using TextToBinaryFloatValueTest = test_fixture::TextToBinaryTestBase<
|
||||
::testing::TestWithParam<std::pair<std::string, uint32_t>>>;
|
||||
|
||||
// TODO(dneto): Fix float parsing.
|
||||
TEST_P(TextToBinaryFloatValueTest, DISABLED_NormalValues) {
|
||||
std::stringstream input;
|
||||
input <<
|
||||
R"(OpTypeFloat %float 32
|
||||
%constval = OpConstant %float )"
|
||||
<< GetParam();
|
||||
const SpirvVector code = CompileSuccessfully(input.str());
|
||||
|
||||
EXPECT_EQ(code[6], GetParam());
|
||||
TEST_P(TextToBinaryFloatValueTest, NormalValues) {
|
||||
const std::string assembly = "%1 = OpTypeFloat 32\n%2 = OpConstant %1 ";
|
||||
const std::string input_string = assembly + GetParam().first;
|
||||
const std::string expected_string =
|
||||
"; SPIR-V\n; Version: 99\n; Generator: Khronos\n; "
|
||||
"Bound: 3\n; Schema: 0\n" +
|
||||
assembly + std::to_string(GetParam().second) + "\n";
|
||||
const std::string decoded_string = EncodeAndDecodeSuccessfully(input_string);
|
||||
EXPECT_EQ(expected_string, decoded_string);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(float, TextToBinaryFloatValueTest,
|
||||
::testing::ValuesIn(std::vector<float>{1.5, 0.0,
|
||||
-2.5}));
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
FloatValues, TextToBinaryFloatValueTest,
|
||||
::testing::ValuesIn(std::vector<std::pair<std::string, uint32_t>>{
|
||||
{"0.0", 0x00000000}, // +0
|
||||
{"!0x00000001", 0x00000001}, // +denorm
|
||||
{"!0x00800000", 0x00800000}, // +norm
|
||||
{"1.5", 0x3fc00000},
|
||||
{"!0x7f800000", 0x7f800000}, // +inf
|
||||
{"!0x7f800001", 0x7f800001}, // NaN
|
||||
|
||||
{"-0.0", 0x80000000}, // -0
|
||||
{"!0x80000001", 0x80000001}, // -denorm
|
||||
{"!0x80800000", 0x80800000}, // -norm
|
||||
{"-2.5", 0xc0200000},
|
||||
{"!0xff800000", 0xff800000}, // -inf
|
||||
{"!0xff800001", 0xff800001}, // NaN
|
||||
}));
|
||||
|
||||
} // anonymous namespace
|
||||
|
Loading…
Reference in New Issue
Block a user