2021年2月26日金曜日

File Size in C

Problem with using fseek/ftell

From cppreference.com - fseek, SEEK_END may not be supported. In this case, ftell doesn't indicates true file size.

Binary streams are not required to support SEEK_END, in particular if additional null bytes are output.

Reliable method

Should use OS specific functions.

Windows

HANDLE file;
LARGE_INTEGER result;
int64_t size = TRUE == GetFileSizeEx(file, &result)? result.QuadPart : 0;

Others

FILE file;
int32_t fd = fileno(file); //If file has not been opened, the result will be undefined.
struct stat64 status;
int64_t size = 0<=fstat64(fd, &status)? status.st_size : 0;

2021年2月14日日曜日

Usage of DirectX Shader Compiler

Build

  • Repository
  • Prerequisites
    • ATL
    • .Net Framework 4.5

Options

Common Options

Common Options
-help Display available options
-nologo Suppress copyright message
-Qunused-arguments Don't emit warning for unused driver arguments

Compilation Options

Compilation Options
-all-resources-bound Enables agressive flattening
-auto-binding-space <value> Set auto binding space - enables auto resource binding in libraries
-Cc Output color coded assembly listings
-default-linkage <value> Set default linkage for non-shader functions when compiling or linking to a library target (internal, external)
-denorm <value> select denormal value options (any, preserve, ftz). any is the default.
-D <value> Define macro
-enable-16bit-types Enable 16bit types and disable min precision types. Available in HLSL 2018 and shader model 6.2
-encoding <value> Set default encoding for text outputs (utf8
-export-shaders-only Only export shaders when compiling a library
-exports <value> Specify exports when compiling a library: export1[[,export1_clone,...]=internal_name][;...]
-E <value> Entry point name
-Fc <file> Output assembly code listing file
-fdiagnostics-show-option Print option name with mappable diagnostics
-Fd <file> Write debug information to the given file, or automatically named file in directory when ending in ''
-Fe <file> Output warnings and errors to the given file
-Fh <file> Output header file containing object code
-flegacy-macro-expansion Expand the operands before performing token-pasting operation (fxc behavior)
-flegacy-resource-reservation Reserve unused explicit register assignments for compatibility with shader model 5.0 and below
-fno-diagnostics-show-option Do not print option name with mappable diagnostics
-force-rootsig-ver <profile> force root signature version (rootsig_1_1 if omitted)
-Fo <file> Output object file
-Fre <file> Output reflection to the given file
-Frs <file> Output root signature to the given file
-Fsh <file> Output shader hash to the given file
-Gec Enable backward compatibility mode
-Ges Enable strict mode
-Gfa Avoid flow control constructs
-Gfp Prefer flow control constructs
-Gis Force IEEE strictness
-HV <value> HLSL version (2016, 2017, 2018). Default is 2018
-H Show header includes and nesting depth
-ignore-line-directives Ignore line directives
-I <value> Add directory to include search path
-Lx Output hexadecimal literals
-Ni Output instruction numbers in assembly listings
-no-legacy-cbuf-layout Do not use legacy cbuffer load
-no-warnings Suppress warnings
-No Output instruction byte offsets in assembly listings
-Odump Print the optimizer commands.
-Od Disable optimizations
-pack-optimized Optimize signature packing assuming identical signature provided for each connecting stage
-pack-prefix-stable (default) Pack signatures preserving prefix-stable property - appended elements will not disturb placement of prior elements
-recompile recompile from DXIL container with Debug Info or Debug Info bitcode file
-res-may-alias Assume that UAVs/SRVs may alias
-rootsig-define <value> Read root signature from a #define
-T <profile> Set target profile.
ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5,
vs_6_0, vs_6_1, vs_6_2, vs_6_3, vs_6_4, vs_6_5,
gs_6_0, gs_6_1, gs_6_2, gs_6_3, gs_6_4, gs_6_5,
hs_6_0, hs_6_1, hs_6_2, hs_6_3, hs_6_4, hs_6_5,
ds_6_0, ds_6_1, ds_6_2, ds_6_3, ds_6_4, ds_6_5,
cs_6_0, cs_6_1, cs_6_2, cs_6_3, cs_6_4, cs_6_5,
lib_6_1, lib_6_2, lib_6_3, lib_6_4, lib_6_5,
ms_6_5,
as_6_5,
-Vd Disable validation
-Vi Display details about the include process.
-Vn <name> Use <name> as variable name in header file
-WX Treat warnings as errors
-Zi Enable debug information
-Zpc Pack matrices in column-major order
-Zpr Pack matrices in row-major order
-Zsb Compute Shader Hash considering only output binary
-Zss Compute Shader Hash considering source information

Optimization Options

Optimization Options
-O0 Optimization Level 0
-O1 Optimization Level 1
-O2 Optimization Level 2
-O3 Optimization Level 3 (Default)

Rewriter Options

Rewriter Options
-extract-entry-uniforms Move uniform parameters from entry point to global scope
-global-extern-by-default Set extern on non-static globals
-keep-user-macro Write out user defines after rewritten HLSL
-line-directive Add line directive
-remove-unused-functions Remove unused functions and types
-remove-unused-globals Remove unused static globals and functions
-skip-fn-body Translate function definitions to declarations
-skip-static Remove static functions and globals when used with -skip-fn-body
-unchanged Rewrite HLSL, without changes.

SPIR-V CodeGen Options

SPIR-V CodeGen Options
-fspv-debug=<value> Specify whitelist of debug info category (file -> source -> line, tool)
-fspv-extension=<value> Specify SPIR-V extension permitted to use
-fspv-flatten-resource-arrays Flatten arrays of resources so each array element takes one binding number
-fspv-reflect Emit additional SPIR-V instructions to aid reflection
-fspv-target-env=<value> Specify the target environment: vulkan1.0 (default) or vulkan1.1
-fvk-auto-shift-bindings Apply fvk-*-shift to resources without an explicit register assignment.
-fvk-b-shift <shift> <space> Specify Vulkan binding number shift for b-type register
-fvk-bind-globals <binding> <set> Specify Vulkan binding number and set number for the $Globals cbuffer
-fvk-bind-register <type-number> <space> <binding> <set> Specify Vulkan descriptor set and binding for a specific register
-fvk-invert-y Negate SV_Position.y before writing to stage output in VS/DS/GS to accommodate Vulkan's coordinate system
-fvk-s-shift <shift> <space> Specify Vulkan binding number shift for s-type register
-fvk-t-shift <shift> <space> Specify Vulkan binding number shift for t-type register
-fvk-u-shift <shift> <space> Specify Vulkan binding number shift for u-type register
-fvk-use-dx-layout Use DirectX memory layout for Vulkan resources
-fvk-use-dx-position-w Reciprocate SV_Position.w after reading from stage input in PS to accommodate the difference between Vulkan and DirectX
-fvk-use-gl-layout Use strict OpenGL std140/std430 memory layout for Vulkan resources
-fvk-use-scalar-layout Use scalar memory layout for Vulkan resources
-Oconfig=<value> Specify a comma-separated list of SPIRV-Tools passes to customize optimization configuration (see http://khr.io/hlsl2spirv#optimization)
-spirv Generate SPIR-V code

Utility Options

Utility Options
-dumpbin Load a binary file rather than compiling
-extractrootsignature Extract root signature from shader bytecode (must be used with /Fo <file>)
-getprivate <file> Save private data from shader blob
-P <value> Preprocess to file (must be used alone)
-Qembed_debug Embed PDB in shader container (must be used with /Zi)
-Qstrip_debug Strip debug information from 4_0+ shader bytecode (must be used with /Fo <file>)
-Qstrip_priv Strip private data from shader bytecode (must be used with /Fo <file>)
-Qstrip_reflect Strip reflection data from shader bytecode (must be used with /Fo <file>)
-Qstrip_rootsignature Strip root signature data from shader bytecode (must be used with /Fo <file>)
-setprivate <file> Private data to add to compiled shader blob
-setrootsignature <file> Attach root signature to shader bytecode
-verifyrootsignature <file> Verify shader bytecode with root signature

Warning Options

Warning Options
-W[no-]<warning> Enable/Disable the specified warning

2020年8月1日土曜日

GLFW - Opening a window -

Opening a window with GLEW and GLFW

CMake

Minimal CMakeLists.txt to build an OpenGL application.
CMake
cmake_minimum_required(VERSION 3.15)

set(CMAKE_CONFIGURATION_TYPES "Debug" "Release")
set(ProjectName "test00")
project(${ProjectName})

set(SOURCES "test00.cpp")

set(FILES ${SOURCES})

add_executable(${ProjectName} ${FILES})

set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -std=gnu++11 -march=native")
set(CMAKE_CXX_FLAGS_DEBUG "-O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2")

target_link_libraries(${ProjectName} glfw GLEW GL)

Minimal

Open a blank window.
cpp
#include 

#include 
#include 
#include 

int main(int argc, char** argv)
{
    glewExperimental = true;
    if(!glfwInit()){
        fprintf(stderr, "Error: failed to initialize GLFW\n");
        return -1;
    }
    glfwWindowHint(GLFW_SAMPLES, 0);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow* window = glfwCreateWindow(800, 600, "Test00", NULL, NULL);
    if(NULL == window){
        fprintf(stderr, "Error: failed to open GLFW window\n");
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    if(GLEW_OK != glewInit()){
        fprintf(stderr, "Error: failed to initialize GLEW\n");
        return -1;
    }
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
    do{
        glClear(GL_COLOR_BUFFER_BIT);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && 0 == glfwWindowShouldClose(window));
    return 0;
}

Offscreen

Offscreen rendering only
cpp
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
GLFWwindow* offscreen_context = glfwCreateWindow(640, 480, "", NULL, NULL);

2020年3月29日日曜日

ChaCha

はじめに

アルゴリズムやコードを使用するにあたり, 著作権や特許権の調査には手間がかかります.
ストリーム暗号ChaChaは, 特許的に訴えられる可能性がかなり低いアルゴリズムと思われます.
著作権的にもRFCやWikipediaからコードを実装すれば訴えられる可能性は低いです.
RFCやWikipediaから実装すると, コードが似てしまうのはどうしようもないと思います.

ストリーム暗号は, 入力された文をバイト単位などで逐次, 暗号化・複合する暗号アルゴリズムを指します. RC4またはARCFOURが有名です.
ストリーム暗号は, 事前に文の長さを知る必要がなく, 文の長さに制限もありません. ブロック暗号は, 文を固定長のブロックに分割して暗号化・複合する暗号アルゴリズムを指します. AESが有名です.
固定長のブロックごとに分割するため, 文が足りない場合に何かしらの規則でデータを埋める必要があります.

ChaChaの実装コードをここに書き留めておきますが, "これをコピーしました"と言っても, 簡単に使えないのだろうなと, 虚しい気持ちになります.
初期ベクトル, nonceを, 用途によって設定できるインターフェイスを用意すべきでしょう.
鍵の長さについても, 任意の長さの鍵を256bitに合わせるインターフェイスを用意すべきでしょう.

実装

実装
#ifndef INC_CHACHA_H_
/**
@file ChaCha.h
@author taqu

USAGE:
Put '#define CHACHA_IMPLEMENTATION' before including this file to create the implementation.
*/
#ifdef __cplusplus
#include <cstdint>
#else
#include <stdint.h>
#endif

#ifdef __cplusplus
namespace cppchacha
{
#endif

void chacha20_encrypt256(const uint32_t key[8], const uint32_t nonce[2], uint32_t size, uint8_t* message);

#ifdef __cplusplus
}
#endif
#endif //INC_CHACHA_H_

#ifdef CHACHA_IMPLEMENTATION

#define ROTL(a,b) (((a)<<(b)) | ((a)>>(32-(b))))
#define QR(a,b,c,d) (\
        a += b, d ^= a, d = ROTL(d,16),\
        c += d, b ^= c, b = ROTL(b,12),\
        a += b, d ^= a, d = ROTL(d, 8),\
        c += d, b ^= c, b = ROTL(b, 7))

#ifdef __cplusplus
namespace cppchacha
{
#endif

#ifdef __cplusplus
namespace
{
#define CHACHA_STATIC
#define CHACHA_CAST(type, ptr) reinterpret_cast<type>(ptr)

#else //__cplusplus
#define CHACHA_STATIC static
#define CHACHA_CAST(type, ptr) (type)(ptr)

#endif //__cplusplus

//'expa', 'nd 3', '2-by', 'te k'
static const uint32_t iv_32[4] = {0x65787061U, 0x6e642033U, 0x322d6279U, 0x7465206bU};

CHACHA_STATIC void chacha20_block(uint32_t out[16], const uint32_t in[16])
{
    uint32_t x[16];
    for(int32_t i=0; i<16; ++i){
        x[i] = in[i];
    }
    for(int32_t i=0; i<10; ++i){
        //Odd round
        QR(x[0], x[4],  x[8], x[12]); //Column 0
        QR(x[1], x[5],  x[9], x[13]); //Column 1
        QR(x[2], x[6], x[10], x[14]); //Column 2
        QR(x[3], x[7], x[11], x[15]); //Column 3
        //Even round
        QR(x[0], x[5], x[10], x[15]); //Diagonal 0
        QR(x[1], x[6], x[11], x[12]); //Diagonal 1
        QR(x[2], x[7],  x[8], x[13]); //Diagonal 2
        QR(x[3], x[4],  x[9], x[14]); //Diagonal 3
    }
    for(int32_t i=0; i<16; ++i){
        out[i] = x[i] + in[i];
    }
}

void chacha20_encrypt(uint32_t input[16], uint32_t size, uint8_t* message)
{
    uint32_t output[16];
    uint32_t* p = CHACHA_CAST(uint32_t*, message);
    uint64_t* counter = CHACHA_CAST(uint64_t*, &input[12]);
    for(;;){
        chacha20_block(output, input);
        *counter += 1;
        if(size<=64){
            uint8_t* pb = CHACHA_CAST(uint8_t*, p);
            uint8_t* po = CHACHA_CAST(uint8_t*, output);
            for(uint32_t i=0; i<size; ++i){
                pb[i] = pb[i] ^ po[i];
            }
            break;
        }else{
            for(uint32_t i = 0; i < 16; ++i){
                p[i] ^= output[i];
            }
            size -= 64;
            p += 16;
        }
    }
}

#ifdef __cplusplus
}
#endif

void chacha20_encrypt256(const uint32_t key[8], const uint32_t nonce[2], uint32_t size, uint8_t* message)
{
    uint32_t input[16];

    for(int32_t i=0; i<4; ++i){
        input[i] = iv_32[i];
    }

    for(int32_t i=0; i<8; ++i){
        input[4+i] = key[i];
    }

    input[12] = 0;
    input[13] = 0;
    input[14] = nonce[0];
    input[15] = nonce[1];
    chacha20_encrypt(input, size, message);
}

#ifdef __cplusplus
}
#endif

#endif //CHACHA_IMPLEMENTATION

使い方

使い方
#define CHACHA_IMPLEMENTATION
#include <string.h>
#include <assert.h>
#include <random>
#include <chrono>
#include <iostream>
#include "ChaCha.h"

int main(int, char**)
{
    using namespace cppchacha;
    const uint8_t key[8*4] = {
        0x23U, 0xADU, 0x52U, 0xB1U, 0x5FU, 0xA7U, 0xEBU, 0xDCU,
        0x46U, 0x72U, 0xD7U, 0x22U, 0x89U, 0x25U, 0x3DU, 0x95U,
        0xDCU, 0x9AU, 0x43U, 0x24U, 0xFCU, 0x36U, 0x9FU, 0x59U,
        0x3FU, 0xDCU, 0xC7U, 0x73U, 0x3AU, 0xD7U, 0x76U, 0x17};
    const uint8_t nonce[2*4] = {
        0x5AU, 0x5FU, 0x6CU, 0x13U, 0xC1U, 0xF1U, 0x26U, 0x53U};

    std::random_device seed_gen;
 std::mt19937 engine(seed_gen());

    int32_t length = 1025 * 1025;
    char* message0 = reinterpret_cast<char*>(malloc(length*sizeof(char)));
    char* message1 = reinterpret_cast<char*>(malloc(length*sizeof(char)));
    for(int32_t i=0; i<length; ++i){
        message0[i] = static_cast<char>(engine());
    }

    memcpy(message1, message0, length);

    std::chrono::high_resolution_clock::time_point begin;
    std::chrono::microseconds elapsed_time;

    begin = std::chrono::high_resolution_clock::now();
    chacha20_encrypt256(reinterpret_cast<const uint32_t*>(key), reinterpret_cast<const uint32_t*>(nonce), length, reinterpret_cast<uint8_t*>(message1));
    chacha20_encrypt256(reinterpret_cast<const uint32_t*>(key), reinterpret_cast<const uint32_t*>(nonce), length, reinterpret_cast<uint8_t*>(message1));
    elapsed_time = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - begin);
    std::cout << elapsed_time.count() << std::endl;

    for(int32_t i=0; i<length; ++i){
        assert(message0[i] == message1[i]);
    }
    free(message1);
    free(message0);
    return 0;
}

2020年1月12日日曜日

ポータブル Vim

動機

Windows用のポータブルなエディタを用意したい.
ミーティング等でノートをとるときなどに使用したい.

  • ネットワークドライブ越しで使える
  • 簡単にコピーできるようにサイズが小さい
  • テキストエディタの機能だけでよい

Vim

Kaoriya版をベースにする.
vim.exe, gvim.exeの不要な方を削除する.

まず, HOMEの設定をしなければいけないため, vimrc_local.vimで設定する.

let $HOME=expand('%:p:h')

_vimrc, _gvimrcをvimrc, gvimrcの後にロードするため, ここに設定を書く.

プラグイン無効化

vimrcに以下を追加

let plugin_autodate_disable  = 1
let plugin_cmdex_disable     = 1
let plugin_dicwin_disable    = 1
let plugin_format_disable    = 1
let plugin_hz_ja_disable     = 1
let plugin_scrnmode_disable  = 1

vimdoc-jaも無効化して, plugins\vimdoc-jaを削除する.

プラグインインストール

必要なものは手動で行う.

フォント

見やすくないがWindows 7が全て駆逐されるまでは,

set guifont=MS_Mincho:h12:cSHIFTJIS