Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
# objs
datasets

# build
build
# directories
[Bb]uild*
venv

## log info
*_log.txt
Expand Down
1 change: 1 addition & 0 deletions include/rtm/aabb.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <cfloat>
#include "float.hpp"
#include "int.hpp"
#include "vec3.hpp"
Expand Down
3 changes: 2 additions & 1 deletion include/rtm/bvh.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "macros.hpp"
#include "int.hpp"
#include "aabb.hpp"
#include "mesh.hpp"
Expand Down Expand Up @@ -718,7 +719,7 @@ class BVH
cache.decisions[j] = cache.decisions[j - 1];
}

if(cache.decisions[1].cost == INFINITY) __debugbreak();
if(cache.decisions[1].cost == INFINITY) add_breakpoint();
}

struct CostItem
Expand Down
16 changes: 13 additions & 3 deletions include/rtm/float.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,20 @@

#ifndef __riscv
#include <cmath>
#include <intrin.h>
#if defined BUILD_PLATFORM_WINDOWS
#include <intrin.h>
#elif defined BUILD_PLATFORM_LINUX
#include <immintrin.h>
#endif
#include <cfenv>
#endif

#ifdef BUILD_PLATFORM_LINUX
// Declarations of intrinsics used that are defined but not declared in immintrin
extern __m128 _mm_cos_ps(__m128 __A);
extern __m128 _mm_sin_ps(__m128 __A);
#endif

namespace rtm
{

Expand Down Expand Up @@ -157,7 +167,7 @@ inline int32_t f32_to_i24(float f32, uint8_t max_exp = 127, int rounding = 0)
else if(rounding == 1)
norm = std::ceil(norm);

if(norm > ((1 << 23) - 1) || norm < -(1 << 23)) __debugbreak();
if(norm > ((1 << 23) - 1) || norm < -(1 << 23)) add_breakpoint();

return (int32_t)norm;
}
Expand Down Expand Up @@ -185,7 +195,7 @@ inline uint16_t f32_to_i16(float f32, uint8_t max_exp = 127, int rounding = 0)
else if(rounding == 1)
norm = std::ceil(norm);

if(norm > ((1 << 15) - 1) || norm < -(1 << 15)) __debugbreak();
if(norm > ((1 << 15) - 1) || norm < -(1 << 15)) add_breakpoint();
return (int16_t)norm;
}
#endif
Expand Down
File renamed without changes.
14 changes: 14 additions & 0 deletions include/rtm/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,18 @@

#if defined __x86_64__ || defined _M_X64
#define __x86
#endif

#if defined _WIN16 || defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 || defined __WIN32__ || defined __TOS_WIN__ || defined __WINDOWS__
#define BUILD_PLATFORM_WINDOWS
#elif defined __linux__
#define BUILD_PLATFORM_LINUX
#endif

//To add breakpoints for debugging at runtime
#if defined BUILD_PLATFORM_WINDOWS
#define add_breakpoint() __debugbreak()
#elif defined BUILD_PLATFORM_LINUX
#include <signal.h>
#define add_breakpoint() raise(SIGINT)
#endif
27 changes: 23 additions & 4 deletions include/rtm/mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,20 @@ class Mesh
public:
Mesh(std::string file_path) : mtl_lib("")
{
load_obj(file_path.c_str());
load_mtl(swap_path(mtl_lib, "../../../datasets/"), "../../../datasets/textures/");
if(!load_obj(file_path.c_str()))
{
printf("Mesh: failed to load mesh OBJ file %s\n", file_path.c_str());
return;
}
if(mtl_lib.length() > 0)
{
std::string parent_folder = parent_path(file_path);
if (!load_mtl(swap_path(mtl_lib, parent_folder), parent_folder + "textures/"))
{
printf("Mesh: failed to load mesh textures or MTL file %s\n", mtl_lib.c_str());
return;
}
}
}

static inline rtm::vec2 read_vec2(char* line)
Expand Down Expand Up @@ -344,15 +356,22 @@ class Mesh
return true;
}

static inline std::string parent_path(std::string path)
{
int i = 0;
for (i = path.size() - 2; i >= 0; --i)
if (path.at(i) == '/')
break;
return path.substr(0, i + 1);
}

static inline std::string swap_path(std::string current_path, std::string new_path)
{
int i = 0;
for(i = current_path.size() - 2; i >= 0; --i)
if(current_path.at(i) == '/')
break;

return new_path + current_path.substr(i + 1);;
return new_path + current_path.substr(i + 1);
}

static inline std::string to_string(rtm::vec3 v)
Expand Down
155 changes: 106 additions & 49 deletions include/rtm/texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ class Texture2D
int32_t comp;
Texel* texels;

private:
// allows Arches to shallow copy textures
// not to be used by kernels!!!
int32_t *pRefCount;

public:
Texture2D() : texels(nullptr) {};
Texture2D() : texels(nullptr), pRefCount(nullptr) {};
#ifndef __riscv
Texture2D(std::string filename)
{
Expand All @@ -34,85 +39,137 @@ class Texture2D
{
uint32_t size = width * height;
texels = (Texel*)malloc(sizeof(Texel) * size);
for(uint32_t i = 0; i < size; ++i)
for(uint32_t j = 0; j < comp; ++j)
texels[i].channel[j] = data[i * comp + j];
for(uint32_t j = 0; j < height; ++j)
for(uint32_t i = 0; i < width; ++i)
for(uint32_t k = 0; k < comp; ++k)
get_texel_addr(rtm::uvec2(i, j))->channel[k] = data[(j * width + i) * comp + k];

stbi_image_free(data);

pRefCount = (int32_t *)malloc(sizeof(int32_t));
*pRefCount = 1; // acquired first time by direct assignment

printf("Loaded: %s \n", filename.c_str());
}
else
{
texels = nullptr;
pRefCount = nullptr;
printf("Failed: %s \n", filename.c_str());
}
}

Texture2D(const Texture2D& other)
Texture2D(const Texture2D& other) : width(other.width), height(other.height), comp(other.comp)
{
other.acquire();
texels = other.texels;
pRefCount = other.pRefCount;
}

Texture2D& operator=(const Texture2D& other)
{
if (this == &other)
return *this;

// copy other members
width = other.width;
height = other.height;
comp = other.comp;

// following order is safer than 'first release, then acquire'
other.acquire(); // prebook ownership of new resource
release(); // release ownership of current resource
texels = other.texels; // acquire ownership of new resource
pRefCount = other.pRefCount;
return *this;
}

~Texture2D()
{
memcpy(this, &other, sizeof(Texture2D));
uint32_t size = sizeof(Texel) * width * height;
texels = (Texel*)malloc(size);
memcpy(texels, other.texels, size);
release();
}
#endif

Texture2D& operator=(const Texture2D& other)
rtm::vec4 sample(const rtm::vec2& uv) const
{
if(texels) free(texels);
memcpy(this, &other, sizeof(Texture2D));
uint32_t size = sizeof(Texel) * width * height;
texels = (Texel*)malloc(size);
memcpy(texels, other.texels, size);
return *this;
if(width == 0 && height == 0) return rtm::vec4(0.0f);
return read_nearest(uv);
}

~Texture2D()
rtm::uvec2 get_iuv(const rtm::vec2& uv, const rtm::vec2& offset = rtm::vec2(0.0f)) const
{
if(texels)
free(texels);
rtm::vec2 fuv = uv * rtm::vec2(width, height) + offset;
return rtm::uvec2(fuv[0], fuv[1]);
}
#endif

rtm::vec3 sample(const rtm::vec2& uv) const
rtm::vec2 get_fract_uv(const rtm::vec2& uv) const
{
if(width == 0 && height == 0) return rtm::vec3(0.0f);
if(width == 1 && height == 1) return read({0, 0});

rtm::vec2 _uv = rtm::mod(uv, rtm::vec2(1.0f)) * rtm::vec2(width, height);
//return read_nearest(_uv);

//rtm::vec2 _uv = rtm::mod(uv, rtm::vec2(1.0f)) * rtm::vec2(width, height);
rtm::vec3 s00 = read_nearest(_uv + rtm::vec2(-0.5f, -0.5f));
rtm::vec3 s10 = read_nearest(_uv + rtm::vec2(0.5f, -0.5f));
rtm::vec3 s01 = read_nearest(_uv + rtm::vec2(-0.5f, 0.5f));
rtm::vec3 s11 = read_nearest(_uv + rtm::vec2(0.5f, 0.5f));

rtm::vec2 ic = rtm::mod(_uv + rtm::vec2(0.5f), rtm::vec2(1.0f));
rtm::vec3 s0 = rtm::mix(s00, s01, ic.y);
rtm::vec3 s1 = rtm::mix(s10, s11, ic.y);
rtm::vec2 fuv = uv * rtm::vec2(width, height);
return (fuv - rtm::vec2((int32_t)fuv[0], (int32_t)fuv[1]));
}

return rtm::mix(s0, s1, ic.x);
Texel* get_texel_addr(const rtm::uvec2& iuv) const
{
uint32_t x = iuv[0] % width;
uint32_t y = iuv[1] % height;
#if 0
return &texels[y * width + x];
#else
static const uint32_t B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF};
static const uint32_t S[] = {1, 2, 4, 8};

x = (x | (x << S[3])) & B[3];
x = (x | (x << S[2])) & B[2];
x = (x | (x << S[1])) & B[1];
x = (x | (x << S[0])) & B[0];

y = (y | (y << S[3])) & B[3];
y = (y | (y << S[2])) & B[2];
y = (y | (y << S[1])) & B[1];
y = (y | (y << S[0])) & B[0];

return &texels[x | (y << 1)];
#endif
}

private:
rtm::vec3 read(const rtm::uvec2& iuv) const
static rtm::vec4 decode_texel(const Texel& texel)
{
uint i = iuv[1] * width + iuv[0];
return rtm::vec3(texels[i].channel[0], texels[i].channel[1], texels[i].channel[2]) * (1.0f / 255.0f);
return rtm::vec4(texel.channel[0], texel.channel[1], texel.channel[2], texel.channel[3]) * (1.0f / 255.0f);
}

rtm::uvec2 get_nearest(const rtm::vec2& uv) const
rtm::vec4 read_nearest(const rtm::vec2& uv, rtm::vec2 offset = rtm::vec2(0.0f)) const
{
rtm::uvec2 mv = rtm::uvec2(width, height);
rtm::uvec2 iuv = rtm::uvec2(uv[0], uv[1]) + mv;
iuv[0] = iuv[0] % mv[0]; iuv[1] = iuv[1] % mv[1];
return iuv;
rtm::uvec2 iuv = get_iuv(uv, offset);
Texel* texel = get_texel_addr(iuv);
return decode_texel(*texel);
}

rtm::vec3 read_nearest(const rtm::vec2& uv) const
#ifndef __riscv
private:
void acquire(void) const
{
rtm::vec3 v = read(get_nearest(uv));
return v;
if (!pRefCount)
return;

(*pRefCount)++;
}

void release(void)
{
if (!pRefCount)
return;

(*pRefCount)--;
if((*pRefCount) <= 0)
{
if(texels)
free(texels);
texels = nullptr;

free(pRefCount);
pRefCount = nullptr;
}
}
#endif
};

30 changes: 27 additions & 3 deletions scripts/log-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ def gauss(n=11,sigma=1):
data[i].append(float(re.findall(r'[\d]*[.][\d]+', line)[0]))


print(f"Total Cycles found: {len(cycles)}")
for i in range(len(keys)):
print(f"Key '{keys[i]}' found {len(data[i])} times")

show_unsmoothed = True
if show_unsmoothed:
for i in range(len(keys)):
Expand All @@ -49,13 +53,33 @@ def gauss(n=11,sigma=1):
kernel = np.array(gauss(kernel_size, 5))
kernel = kernel / kernel.sum()

# for i in range(len(keys)):
# if len(data[i]) == len(cycles):
# plt.plot(cycles, np.convolve(data[i], kernel, mode='same'), colors[i], label=keys[i])

for i in range(len(keys)):
if len(data[i]) == len(cycles):
plt.plot(cycles, np.convolve(data[i], kernel, mode='same'), colors[i], label=keys[i])
# determine the shortest length to keep (x, y) in sync
min_len = min(len(data[i]), len(cycles))

if min_len > 0:
# slice both to min_len so (x, y) match perfectly
x = cycles[:min_len]
y = data[i][:min_len]

# plot unsmoothed (faded)
plt.plot(x, y, colors[i], alpha=0.125)

# plot smoothed (solid with label)
smoothed = np.convolve(y, kernel, mode='same')
plt.plot(x, smoothed, colors[i], label=keys[i])
else:
print(f"Skipping {keys[i]} - no data matches found.")

plt.legend(loc="upper right")
plt.ylabel(ylabel)
plt.xlabel('Time (cycles)')
plt.yscale('log')
plt.grid()
plt.show()
plt.savefig("simulation_results.png") # save instead of show
print("Plot saved to simulation_results.png")
#plt.show()
Loading