Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"
This reverts commit 15b7df8ef1.
This commit is contained in:
@@ -1,545 +0,0 @@
|
||||
#include "dk_renderer.hpp"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <switch.h>
|
||||
|
||||
#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES /* Enforces GLSL std140/std430 alignment rules for glm types. */
|
||||
#define GLM_FORCE_INTRINSICS /* Enables usage of SIMD CPU instructions (requiring the above as well). */
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
namespace nvg {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr std::array VertexBufferState = { DkVtxBufferState{sizeof(NVGvertex), 0}, };
|
||||
|
||||
constexpr std::array VertexAttribState = {
|
||||
DkVtxAttribState{0, 0, offsetof(NVGvertex, x), DkVtxAttribSize_2x32, DkVtxAttribType_Float, 0},
|
||||
DkVtxAttribState{0, 0, offsetof(NVGvertex, u), DkVtxAttribSize_2x32, DkVtxAttribType_Float, 0},
|
||||
};
|
||||
|
||||
struct View {
|
||||
glm::vec2 size;
|
||||
};
|
||||
|
||||
void UpdateImage(dk::Image &image, CMemPool &scratchPool, dk::Device device, dk::Queue transferQueue, int type, int x, int y, int w, int h, const u8 *data) {
|
||||
/* Do not proceed if no data is provided upfront. */
|
||||
if (data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate memory from the pool for the image. */
|
||||
const size_t imageSize = type == NVG_TEXTURE_RGBA ? w * h * 4 : w * h;
|
||||
CMemPool::Handle tempimgmem = scratchPool.allocate(imageSize, DK_IMAGE_LINEAR_STRIDE_ALIGNMENT);
|
||||
memcpy(tempimgmem.getCpuAddr(), data, imageSize);
|
||||
|
||||
dk::UniqueCmdBuf tempcmdbuf = dk::CmdBufMaker{device}.create();
|
||||
CMemPool::Handle tempcmdmem = scratchPool.allocate(DK_MEMBLOCK_ALIGNMENT);
|
||||
tempcmdbuf.addMemory(tempcmdmem.getMemBlock(), tempcmdmem.getOffset(), tempcmdmem.getSize());
|
||||
|
||||
dk::ImageView imageView{image};
|
||||
tempcmdbuf.copyBufferToImage({ tempimgmem.getGpuAddr() }, imageView, { static_cast<uint32_t>(x), static_cast<uint32_t>(y), 0, static_cast<uint32_t>(w), static_cast<uint32_t>(h), 1 });
|
||||
|
||||
transferQueue.submitCommands(tempcmdbuf.finishList());
|
||||
transferQueue.waitIdle();
|
||||
|
||||
/* Destroy temp mem. */
|
||||
tempcmdmem.destroy();
|
||||
tempimgmem.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Texture::Texture(int id) : m_id(id) { /* ... */ }
|
||||
|
||||
Texture::~Texture() {
|
||||
m_image_mem.destroy();
|
||||
}
|
||||
|
||||
void Texture::Initialize(CMemPool &image_pool, CMemPool &scratch_pool, dk::Device device, dk::Queue queue, int type, int w, int h, int image_flags, const u8 *data) {
|
||||
m_texture_descriptor = {
|
||||
.width = w,
|
||||
.height = h,
|
||||
.type = type,
|
||||
.flags = image_flags,
|
||||
};
|
||||
|
||||
/* Create an image layout. */
|
||||
dk::ImageLayout layout;
|
||||
auto layout_maker = dk::ImageLayoutMaker{device}.setFlags(0).setDimensions(w, h);
|
||||
if (type == NVG_TEXTURE_RGBA) {
|
||||
layout_maker.setFormat(DkImageFormat_RGBA8_Unorm);
|
||||
} else {
|
||||
layout_maker.setFormat(DkImageFormat_R8_Unorm);
|
||||
}
|
||||
layout_maker.initialize(layout);
|
||||
|
||||
/* Initialize image. */
|
||||
m_image_mem = image_pool.allocate(layout.getSize(), layout.getAlignment());
|
||||
m_image.initialize(layout, m_image_mem.getMemBlock(), m_image_mem.getOffset());
|
||||
m_image_descriptor.initialize(m_image);
|
||||
|
||||
/* Only update the image if the data isn't null. */
|
||||
if (data != nullptr) {
|
||||
UpdateImage(m_image, scratch_pool, device, queue, type, 0, 0, w, h, data);
|
||||
}
|
||||
}
|
||||
|
||||
int Texture::GetId() {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
const DKNVGtextureDescriptor &Texture::GetDescriptor() {
|
||||
return m_texture_descriptor;
|
||||
}
|
||||
|
||||
dk::Image &Texture::GetImage() {
|
||||
return m_image;
|
||||
}
|
||||
|
||||
dk::ImageDescriptor &Texture::GetImageDescriptor() {
|
||||
return m_image_descriptor;
|
||||
}
|
||||
|
||||
DkRenderer::DkRenderer(unsigned int view_width, unsigned int view_height, dk::Device device, dk::Queue queue, CMemPool &image_mem_pool, CMemPool &code_mem_pool, CMemPool &data_mem_pool) :
|
||||
m_view_width(view_width), m_view_height(view_height), m_device(device), m_queue(queue), m_image_mem_pool(image_mem_pool), m_code_mem_pool(code_mem_pool), m_data_mem_pool(data_mem_pool), m_image_descriptor_mappings({0})
|
||||
{
|
||||
/* Create a dynamic command buffer and allocate memory for it. */
|
||||
m_dyn_cmd_buf = dk::CmdBufMaker{m_device}.create();
|
||||
m_dyn_cmd_mem.allocate(m_data_mem_pool, DynamicCmdSize);
|
||||
|
||||
m_image_descriptor_set.allocate(m_data_mem_pool);
|
||||
m_sampler_descriptor_set.allocate(m_data_mem_pool);
|
||||
|
||||
m_view_uniform_buffer = m_data_mem_pool.allocate(sizeof(View), DK_UNIFORM_BUF_ALIGNMENT);
|
||||
m_frag_uniform_buffer = m_data_mem_pool.allocate(sizeof(FragmentUniformSize), DK_UNIFORM_BUF_ALIGNMENT);
|
||||
|
||||
/* Create and bind preset samplers. */
|
||||
dk::UniqueCmdBuf init_cmd_buf = dk::CmdBufMaker{m_device}.create();
|
||||
CMemPool::Handle init_cmd_mem = m_data_mem_pool.allocate(DK_MEMBLOCK_ALIGNMENT);
|
||||
init_cmd_buf.addMemory(init_cmd_mem.getMemBlock(), init_cmd_mem.getOffset(), init_cmd_mem.getSize());
|
||||
|
||||
for (u8 i = 0; i < SamplerType_Total; i++) {
|
||||
const DkFilter filter = (i & SamplerType_Nearest) ? DkFilter_Nearest : DkFilter_Linear;
|
||||
const DkMipFilter mip_filter = (i & SamplerType_Nearest) ? DkMipFilter_Nearest : DkMipFilter_Linear;
|
||||
const DkWrapMode u_wrap_mode = (i & SamplerType_RepeatX) ? DkWrapMode_Repeat : DkWrapMode_ClampToEdge;
|
||||
const DkWrapMode v_wrap_mode = (i & SamplerType_RepeatY) ? DkWrapMode_Repeat : DkWrapMode_ClampToEdge;
|
||||
|
||||
auto sampler = dk::Sampler{};
|
||||
auto sampler_descriptor = dk::SamplerDescriptor{};
|
||||
sampler.setFilter(filter, filter, (i & SamplerType_MipFilter) ? mip_filter : DkMipFilter_None);
|
||||
sampler.setWrapMode(u_wrap_mode, v_wrap_mode);
|
||||
sampler_descriptor.initialize(sampler);
|
||||
m_sampler_descriptor_set.update(init_cmd_buf, i, sampler_descriptor);
|
||||
}
|
||||
|
||||
/* Flush the descriptor cache. */
|
||||
init_cmd_buf.barrier(DkBarrier_None, DkInvalidateFlags_Descriptors);
|
||||
|
||||
m_sampler_descriptor_set.bindForSamplers(init_cmd_buf);
|
||||
m_image_descriptor_set.bindForImages(init_cmd_buf);
|
||||
|
||||
m_queue.submitCommands(init_cmd_buf.finishList());
|
||||
m_queue.waitIdle();
|
||||
|
||||
init_cmd_mem.destroy();
|
||||
init_cmd_buf.destroy();
|
||||
}
|
||||
|
||||
DkRenderer::~DkRenderer() {
|
||||
if (m_vertex_buffer) {
|
||||
m_vertex_buffer->destroy();
|
||||
}
|
||||
|
||||
m_view_uniform_buffer.destroy();
|
||||
m_frag_uniform_buffer.destroy();
|
||||
m_textures.clear();
|
||||
}
|
||||
|
||||
int DkRenderer::AcquireImageDescriptor(std::shared_ptr<Texture> texture, int image) {
|
||||
int free_image_descriptor = m_last_image_descriptor + 1;
|
||||
int mapping = 0;
|
||||
|
||||
for (int desc = 0; desc <= m_last_image_descriptor; desc++) {
|
||||
mapping = m_image_descriptor_mappings[desc];
|
||||
|
||||
/* We've found the image descriptor requested. */
|
||||
if (mapping == image) {
|
||||
return desc;
|
||||
}
|
||||
|
||||
/* Update the free image descriptor. */
|
||||
if (mapping == 0 && free_image_descriptor == m_last_image_descriptor + 1) {
|
||||
free_image_descriptor = desc;
|
||||
}
|
||||
}
|
||||
|
||||
/* No descriptors are free. */
|
||||
if (free_image_descriptor >= static_cast<int>(MaxImages)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Update descriptor sets. */
|
||||
m_image_descriptor_set.update(m_dyn_cmd_buf, free_image_descriptor, texture->GetImageDescriptor());
|
||||
|
||||
/* Flush the descriptor cache. */
|
||||
m_dyn_cmd_buf.barrier(DkBarrier_None, DkInvalidateFlags_Descriptors);
|
||||
|
||||
/* Update the map. */
|
||||
m_image_descriptor_mappings[free_image_descriptor] = image;
|
||||
m_last_image_descriptor = free_image_descriptor;
|
||||
return free_image_descriptor;
|
||||
}
|
||||
|
||||
void DkRenderer::FreeImageDescriptor(int image) {
|
||||
for (int desc = 0; desc <= m_last_image_descriptor; desc++) {
|
||||
if (m_image_descriptor_mappings[desc] == image) {
|
||||
m_image_descriptor_mappings[desc] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DkRenderer::UpdateVertexBuffer(const void *data, size_t size) {
|
||||
/* Destroy the existing vertex buffer if it is too small. */
|
||||
if (m_vertex_buffer && m_vertex_buffer->getSize() < size) {
|
||||
m_vertex_buffer->destroy();
|
||||
m_vertex_buffer.reset();
|
||||
}
|
||||
|
||||
/* Create a new buffer if needed. */
|
||||
if (!m_vertex_buffer) {
|
||||
m_vertex_buffer = m_data_mem_pool.allocate(size);
|
||||
}
|
||||
|
||||
/* Copy data to the vertex buffer if it exists. */
|
||||
if (m_vertex_buffer) {
|
||||
memcpy(m_vertex_buffer->getCpuAddr(), data, size);
|
||||
}
|
||||
}
|
||||
|
||||
void DkRenderer::SetUniforms(const DKNVGcontext &ctx, int offset, int image) {
|
||||
m_dyn_cmd_buf.pushConstants(m_frag_uniform_buffer.getGpuAddr(), m_frag_uniform_buffer.getSize(), 0, ctx.fragSize, ctx.uniforms + offset);
|
||||
m_dyn_cmd_buf.bindUniformBuffer(DkStage_Fragment, 0, m_frag_uniform_buffer.getGpuAddr(), m_frag_uniform_buffer.getSize());
|
||||
|
||||
/* Attempt to find a texture. */
|
||||
const auto texture = this->FindTexture(image);
|
||||
if (texture == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Acquire an image descriptor. */
|
||||
const int image_desc_id = this->AcquireImageDescriptor(texture, image);
|
||||
if (image_desc_id == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int image_flags = texture->GetDescriptor().flags;
|
||||
uint32_t sampler_id = 0;
|
||||
|
||||
if (image_flags & NVG_IMAGE_GENERATE_MIPMAPS) sampler_id |= SamplerType_MipFilter;
|
||||
if (image_flags & NVG_IMAGE_NEAREST) sampler_id |= SamplerType_Nearest;
|
||||
if (image_flags & NVG_IMAGE_REPEATX) sampler_id |= SamplerType_RepeatX;
|
||||
if (image_flags & NVG_IMAGE_REPEATY) sampler_id |= SamplerType_RepeatY;
|
||||
|
||||
m_dyn_cmd_buf.bindTextures(DkStage_Fragment, 0, dkMakeTextureHandle(image_desc_id, sampler_id));
|
||||
}
|
||||
|
||||
void DkRenderer::DrawFill(const DKNVGcontext &ctx, const DKNVGcall &call) {
|
||||
DKNVGpath *paths = &ctx.paths[call.pathOffset];
|
||||
int npaths = call.pathCount;
|
||||
|
||||
/* Set the stencils to be used. */
|
||||
m_dyn_cmd_buf.setStencil(DkFace_FrontAndBack, 0xFF, 0x0, 0xFF);
|
||||
|
||||
/* Set the depth stencil state. */
|
||||
auto depth_stencil_state = dk::DepthStencilState{}
|
||||
.setStencilTestEnable(true)
|
||||
.setStencilFrontCompareOp(DkCompareOp_Always)
|
||||
.setStencilFrontFailOp(DkStencilOp_Keep)
|
||||
.setStencilFrontDepthFailOp(DkStencilOp_Keep)
|
||||
.setStencilFrontPassOp(DkStencilOp_IncrWrap)
|
||||
.setStencilBackCompareOp(DkCompareOp_Always)
|
||||
.setStencilBackFailOp(DkStencilOp_Keep)
|
||||
.setStencilBackDepthFailOp(DkStencilOp_Keep)
|
||||
.setStencilBackPassOp(DkStencilOp_DecrWrap);
|
||||
m_dyn_cmd_buf.bindDepthStencilState(depth_stencil_state);
|
||||
|
||||
/* Configure for shape drawing. */
|
||||
m_dyn_cmd_buf.bindColorWriteState(dk::ColorWriteState{}.setMask(0, 0));
|
||||
this->SetUniforms(ctx, call.uniformOffset, 0);
|
||||
m_dyn_cmd_buf.bindRasterizerState(dk::RasterizerState{}.setCullMode(DkFace_None));
|
||||
|
||||
/* Draw vertices. */
|
||||
for (int i = 0; i < npaths; i++) {
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_TriangleFan, paths[i].fillCount, 1, paths[i].fillOffset, 0);
|
||||
}
|
||||
|
||||
m_dyn_cmd_buf.bindColorWriteState(dk::ColorWriteState{});
|
||||
this->SetUniforms(ctx, call.uniformOffset + ctx.fragSize, call.image);
|
||||
m_dyn_cmd_buf.bindRasterizerState(dk::RasterizerState{});
|
||||
|
||||
if (ctx.flags & NVG_ANTIALIAS) {
|
||||
/* Configure stencil anti-aliasing. */
|
||||
depth_stencil_state
|
||||
.setStencilFrontCompareOp(DkCompareOp_Equal)
|
||||
.setStencilFrontFailOp(DkStencilOp_Keep)
|
||||
.setStencilFrontDepthFailOp(DkStencilOp_Keep)
|
||||
.setStencilFrontPassOp(DkStencilOp_Keep)
|
||||
.setStencilBackCompareOp(DkCompareOp_Equal)
|
||||
.setStencilBackFailOp(DkStencilOp_Keep)
|
||||
.setStencilBackDepthFailOp(DkStencilOp_Keep)
|
||||
.setStencilBackPassOp(DkStencilOp_Keep);
|
||||
m_dyn_cmd_buf.bindDepthStencilState(depth_stencil_state);
|
||||
|
||||
/* Draw fringes. */
|
||||
for (int i = 0; i < npaths; i++) {
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_TriangleStrip, paths[i].strokeCount, 1, paths[i].strokeOffset, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure and draw fill. */
|
||||
depth_stencil_state
|
||||
.setStencilFrontCompareOp(DkCompareOp_NotEqual)
|
||||
.setStencilFrontFailOp(DkStencilOp_Zero)
|
||||
.setStencilFrontDepthFailOp(DkStencilOp_Zero)
|
||||
.setStencilFrontPassOp(DkStencilOp_Zero)
|
||||
.setStencilBackCompareOp(DkCompareOp_NotEqual)
|
||||
.setStencilBackFailOp(DkStencilOp_Zero)
|
||||
.setStencilBackDepthFailOp(DkStencilOp_Zero)
|
||||
.setStencilBackPassOp(DkStencilOp_Zero);
|
||||
m_dyn_cmd_buf.bindDepthStencilState(depth_stencil_state);
|
||||
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_TriangleStrip, call.triangleCount, 1, call.triangleOffset, 0);
|
||||
|
||||
/* Reset the depth stencil state to default. */
|
||||
m_dyn_cmd_buf.bindDepthStencilState(dk::DepthStencilState{});
|
||||
}
|
||||
|
||||
void DkRenderer::DrawConvexFill(const DKNVGcontext &ctx, const DKNVGcall &call) {
|
||||
DKNVGpath *paths = &ctx.paths[call.pathOffset];
|
||||
int npaths = call.pathCount;
|
||||
|
||||
this->SetUniforms(ctx, call.uniformOffset, call.image);
|
||||
|
||||
for (int i = 0; i < npaths; i++) {
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_TriangleFan, paths[i].fillCount, 1, paths[i].fillOffset, 0);
|
||||
|
||||
/* Draw fringes. */
|
||||
if (paths[i].strokeCount > 0) {
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_TriangleStrip, paths[i].strokeCount, 1, paths[i].strokeOffset, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DkRenderer::DrawStroke(const DKNVGcontext &ctx, const DKNVGcall &call) {
|
||||
DKNVGpath* paths = &ctx.paths[call.pathOffset];
|
||||
int npaths = call.pathCount;
|
||||
|
||||
if (ctx.flags & NVG_STENCIL_STROKES) {
|
||||
/* Set the stencil to be used. */
|
||||
m_dyn_cmd_buf.setStencil(DkFace_Front, 0xFF, 0x0, 0xFF);
|
||||
|
||||
/* Configure for filling the stroke base without overlap. */
|
||||
auto depth_stencil_state = dk::DepthStencilState{}
|
||||
.setStencilTestEnable(true)
|
||||
.setStencilFrontCompareOp(DkCompareOp_Equal)
|
||||
.setStencilFrontFailOp(DkStencilOp_Keep)
|
||||
.setStencilFrontDepthFailOp(DkStencilOp_Keep)
|
||||
.setStencilFrontPassOp(DkStencilOp_Incr);
|
||||
m_dyn_cmd_buf.bindDepthStencilState(depth_stencil_state);
|
||||
this->SetUniforms(ctx, call.uniformOffset + ctx.fragSize, call.image);
|
||||
|
||||
/* Draw vertices. */
|
||||
for (int i = 0; i < npaths; i++) {
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_TriangleStrip, paths[i].strokeCount, 1, paths[i].strokeOffset, 0);
|
||||
}
|
||||
|
||||
/* Configure for drawing anti-aliased pixels. */
|
||||
depth_stencil_state.setStencilFrontPassOp(DkStencilOp_Keep);
|
||||
m_dyn_cmd_buf.bindDepthStencilState(depth_stencil_state);
|
||||
this->SetUniforms(ctx, call.uniformOffset, call.image);
|
||||
|
||||
/* Draw vertices. */
|
||||
for (int i = 0; i < npaths; i++) {
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_TriangleStrip, paths[i].strokeCount, 1, paths[i].strokeOffset, 0);
|
||||
}
|
||||
|
||||
/* Configure for clearing the stencil buffer. */
|
||||
depth_stencil_state
|
||||
.setStencilTestEnable(true)
|
||||
.setStencilFrontCompareOp(DkCompareOp_Always)
|
||||
.setStencilFrontFailOp(DkStencilOp_Zero)
|
||||
.setStencilFrontDepthFailOp(DkStencilOp_Zero)
|
||||
.setStencilFrontPassOp(DkStencilOp_Zero);
|
||||
m_dyn_cmd_buf.bindDepthStencilState(depth_stencil_state);
|
||||
|
||||
/* Draw vertices. */
|
||||
for (int i = 0; i < npaths; i++) {
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_TriangleStrip, paths[i].strokeCount, 1, paths[i].strokeOffset, 0);
|
||||
}
|
||||
|
||||
/* Reset the depth stencil state to default. */
|
||||
m_dyn_cmd_buf.bindDepthStencilState(dk::DepthStencilState{});
|
||||
} else {
|
||||
this->SetUniforms(ctx, call.uniformOffset, call.image);
|
||||
|
||||
/* Draw vertices. */
|
||||
for (int i = 0; i < npaths; i++) {
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_TriangleStrip, paths[i].strokeCount, 1, paths[i].strokeOffset, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DkRenderer::DrawTriangles(const DKNVGcontext &ctx, const DKNVGcall &call) {
|
||||
this->SetUniforms(ctx, call.uniformOffset, call.image);
|
||||
m_dyn_cmd_buf.draw(DkPrimitive_Triangles, call.triangleCount, 1, call.triangleOffset, 0);
|
||||
}
|
||||
|
||||
int DkRenderer::Create(DKNVGcontext &ctx) {
|
||||
m_vertex_shader.load(m_code_mem_pool, "romfs:/shaders/fill_vsh.dksh");
|
||||
|
||||
/* Load the appropriate fragment shader depending on whether AA is enabled. */
|
||||
if (ctx.flags & NVG_ANTIALIAS) {
|
||||
m_fragment_shader.load(m_code_mem_pool, "romfs:/shaders/fill_aa_fsh.dksh");
|
||||
} else {
|
||||
m_fragment_shader.load(m_code_mem_pool, "romfs:/shaders/fill_fsh.dksh");
|
||||
}
|
||||
|
||||
/* Set the size of fragment uniforms. */
|
||||
ctx.fragSize = FragmentUniformSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> DkRenderer::FindTexture(int id) {
|
||||
for (auto it = m_textures.begin(); it != m_textures.end(); it++) {
|
||||
if ((*it)->GetId() == id) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int DkRenderer::CreateTexture(const DKNVGcontext &ctx, int type, int w, int h, int image_flags, const unsigned char* data) {
|
||||
const auto texture_id = m_next_texture_id++;
|
||||
auto texture = std::make_shared<Texture>(texture_id);
|
||||
texture->Initialize(m_image_mem_pool, m_data_mem_pool, m_device, m_queue, type, w, h, image_flags, data);
|
||||
m_textures.push_back(texture);
|
||||
return texture->GetId();
|
||||
}
|
||||
|
||||
int DkRenderer::DeleteTexture(const DKNVGcontext &ctx, int image) {
|
||||
bool found = false;
|
||||
|
||||
for (auto it = m_textures.begin(); it != m_textures.end();) {
|
||||
/* Remove textures with the given id. */
|
||||
if ((*it)->GetId() == image) {
|
||||
it = m_textures.erase(it);
|
||||
found = true;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free any used image descriptors. */
|
||||
this->FreeImageDescriptor(image);
|
||||
return found;
|
||||
}
|
||||
|
||||
int DkRenderer::UpdateTexture(const DKNVGcontext &ctx, int image, int x, int y, int w, int h, const unsigned char *data) {
|
||||
const std::shared_ptr<Texture> texture = this->FindTexture(image);
|
||||
|
||||
/* Could not find a texture. */
|
||||
if (texture == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const DKNVGtextureDescriptor &tex_desc = texture->GetDescriptor();
|
||||
if (tex_desc.type == NVG_TEXTURE_RGBA) {
|
||||
data += y * tex_desc.width*4;
|
||||
} else {
|
||||
data += y * tex_desc.width;
|
||||
}
|
||||
x = 0;
|
||||
w = tex_desc.width;
|
||||
|
||||
UpdateImage(texture->GetImage(), m_data_mem_pool, m_device, m_queue, tex_desc.type, x, y, w, h, data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DkRenderer::GetTextureSize(const DKNVGcontext &ctx, int image, int *w, int *h) {
|
||||
const auto descriptor = this->GetTextureDescriptor(ctx, image);
|
||||
if (descriptor == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*w = descriptor->width;
|
||||
*h = descriptor->height;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const DKNVGtextureDescriptor *DkRenderer::GetTextureDescriptor(const DKNVGcontext &ctx, int id) {
|
||||
for (auto it = m_textures.begin(); it != m_textures.end(); it++) {
|
||||
if ((*it)->GetId() == id) {
|
||||
return &(*it)->GetDescriptor();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DkRenderer::Flush(DKNVGcontext &ctx) {
|
||||
if (ctx.ncalls > 0) {
|
||||
/* Prepare dynamic command buffer. */
|
||||
m_dyn_cmd_mem.begin(m_dyn_cmd_buf);
|
||||
|
||||
/* Update buffers with data. */
|
||||
this->UpdateVertexBuffer(ctx.verts, ctx.nverts * sizeof(NVGvertex));
|
||||
|
||||
/* Enable blending. */
|
||||
m_dyn_cmd_buf.bindColorState(dk::ColorState{}.setBlendEnable(0, true));
|
||||
|
||||
/* Setup. */
|
||||
m_dyn_cmd_buf.bindShaders(DkStageFlag_GraphicsMask, { m_vertex_shader, m_fragment_shader });
|
||||
m_dyn_cmd_buf.bindVtxAttribState(VertexAttribState);
|
||||
m_dyn_cmd_buf.bindVtxBufferState(VertexBufferState);
|
||||
m_dyn_cmd_buf.bindVtxBuffer(0, m_vertex_buffer->getGpuAddr(), m_vertex_buffer->getSize());
|
||||
|
||||
/* Push the view size to the uniform buffer and bind it. */
|
||||
const auto view = View{glm::vec2{m_view_width, m_view_height}};
|
||||
m_dyn_cmd_buf.pushConstants(m_view_uniform_buffer.getGpuAddr(), m_view_uniform_buffer.getSize(), 0, sizeof(view), &view);
|
||||
m_dyn_cmd_buf.bindUniformBuffer(DkStage_Vertex, 0, m_view_uniform_buffer.getGpuAddr(), m_view_uniform_buffer.getSize());
|
||||
|
||||
/* Iterate over calls. */
|
||||
for (int i = 0; i < ctx.ncalls; i++) {
|
||||
const DKNVGcall &call = ctx.calls[i];
|
||||
|
||||
/* Perform blending. */
|
||||
m_dyn_cmd_buf.bindBlendStates(0, { dk::BlendState{}.setFactors(static_cast<DkBlendFactor>(call.blendFunc.srcRGB), static_cast<DkBlendFactor>(call.blendFunc.dstRGB), static_cast<DkBlendFactor>(call.blendFunc.srcAlpha), static_cast<DkBlendFactor>(call.blendFunc.dstRGB)) });
|
||||
|
||||
if (call.type == DKNVG_FILL) {
|
||||
this->DrawFill(ctx, call);
|
||||
} else if (call.type == DKNVG_CONVEXFILL) {
|
||||
this->DrawConvexFill(ctx, call);
|
||||
} else if (call.type == DKNVG_STROKE) {
|
||||
this->DrawStroke(ctx, call);
|
||||
} else if (call.type == DKNVG_TRIANGLES) {
|
||||
this->DrawTriangles(ctx, call);
|
||||
}
|
||||
}
|
||||
|
||||
m_queue.submitCommands(m_dyn_cmd_mem.end(m_dyn_cmd_buf));
|
||||
}
|
||||
|
||||
/* Reset calls. */
|
||||
ctx.nverts = 0;
|
||||
ctx.npaths = 0;
|
||||
ctx.ncalls = 0;
|
||||
ctx.nuniforms = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
** Sample Framework for deko3d Applications
|
||||
** CApplication.cpp: Wrapper class containing common application boilerplate
|
||||
*/
|
||||
#include "CApplication.h"
|
||||
|
||||
CApplication::CApplication()
|
||||
{
|
||||
appletLockExit();
|
||||
appletSetFocusHandlingMode(AppletFocusHandlingMode_NoSuspend);
|
||||
}
|
||||
|
||||
CApplication::~CApplication()
|
||||
{
|
||||
appletSetFocusHandlingMode(AppletFocusHandlingMode_SuspendHomeSleep);
|
||||
appletUnlockExit();
|
||||
}
|
||||
|
||||
void CApplication::run()
|
||||
{
|
||||
u64 tick_ref = armGetSystemTick();
|
||||
u64 tick_saved = tick_ref;
|
||||
bool focused = appletGetFocusState() == AppletFocusState_InFocus;
|
||||
|
||||
onOperationMode(appletGetOperationMode());
|
||||
|
||||
for (;;)
|
||||
{
|
||||
u32 msg = 0;
|
||||
Result rc = appletGetMessage(&msg);
|
||||
if (R_SUCCEEDED(rc))
|
||||
{
|
||||
bool should_close = !appletProcessMessage(msg);
|
||||
if (should_close)
|
||||
return;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case AppletMessage_FocusStateChanged:
|
||||
{
|
||||
bool old_focused = focused;
|
||||
AppletFocusState state = appletGetFocusState();
|
||||
focused = state == AppletFocusState_InFocus;
|
||||
|
||||
onFocusState(state);
|
||||
if (focused == old_focused)
|
||||
break;
|
||||
if (focused)
|
||||
{
|
||||
appletSetFocusHandlingMode(AppletFocusHandlingMode_NoSuspend);
|
||||
tick_ref += armGetSystemTick() - tick_saved;
|
||||
}
|
||||
else
|
||||
{
|
||||
tick_saved = armGetSystemTick();
|
||||
appletSetFocusHandlingMode(AppletFocusHandlingMode_SuspendHomeSleepNotify);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AppletMessage_OperationModeChanged:
|
||||
onOperationMode(appletGetOperationMode());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (focused && !onFrame(armTicksToNs(armGetSystemTick() - tick_ref)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
** Sample Framework for deko3d Applications
|
||||
** CExternalImage.cpp: Utility class for loading images from the filesystem
|
||||
*/
|
||||
#include "CExternalImage.h"
|
||||
#include "FileLoader.h"
|
||||
|
||||
bool CExternalImage::load(CMemPool& imagePool, CMemPool& scratchPool, dk::Device device, dk::Queue transferQueue, const char* path, uint32_t width, uint32_t height, DkImageFormat format, uint32_t flags)
|
||||
{
|
||||
CMemPool::Handle tempimgmem = LoadFile(scratchPool, path, DK_IMAGE_LINEAR_STRIDE_ALIGNMENT);
|
||||
if (!tempimgmem)
|
||||
return false;
|
||||
|
||||
dk::UniqueCmdBuf tempcmdbuf = dk::CmdBufMaker{device}.create();
|
||||
CMemPool::Handle tempcmdmem = scratchPool.allocate(DK_MEMBLOCK_ALIGNMENT);
|
||||
tempcmdbuf.addMemory(tempcmdmem.getMemBlock(), tempcmdmem.getOffset(), tempcmdmem.getSize());
|
||||
|
||||
dk::ImageLayout layout;
|
||||
dk::ImageLayoutMaker{device}
|
||||
.setFlags(flags)
|
||||
.setFormat(format)
|
||||
.setDimensions(width, height)
|
||||
.initialize(layout);
|
||||
|
||||
m_mem = imagePool.allocate(layout.getSize(), layout.getAlignment());
|
||||
m_image.initialize(layout, m_mem.getMemBlock(), m_mem.getOffset());
|
||||
m_descriptor.initialize(m_image);
|
||||
|
||||
dk::ImageView imageView{m_image};
|
||||
tempcmdbuf.copyBufferToImage({ tempimgmem.getGpuAddr() }, imageView, { 0, 0, 0, width, height, 1 });
|
||||
transferQueue.submitCommands(tempcmdbuf.finishList());
|
||||
transferQueue.waitIdle();
|
||||
|
||||
tempcmdmem.destroy();
|
||||
tempimgmem.destroy();
|
||||
return true;
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
** Sample Framework for deko3d Applications
|
||||
** CIntrusiveTree.cpp: Intrusive red-black tree helper class
|
||||
*/
|
||||
#include "CIntrusiveTree.h"
|
||||
|
||||
// This red-black tree implementation is mostly based on mtheall's work,
|
||||
// which can be found here:
|
||||
// https://github.com/smealum/ctrulib/tree/master/libctru/source/util/rbtree
|
||||
|
||||
void CIntrusiveTreeBase::rotate(N* node, N::Leaf leaf)
|
||||
{
|
||||
N *tmp = node->child(leaf);
|
||||
N *parent = node->getParent();
|
||||
|
||||
node->child(leaf) = tmp->child(!leaf);
|
||||
if (tmp->child(!leaf))
|
||||
tmp->child(!leaf)->setParent(node);
|
||||
|
||||
tmp->child(!leaf) = node;
|
||||
tmp->setParent(parent);
|
||||
|
||||
if (parent)
|
||||
{
|
||||
if (node == parent->child(!leaf))
|
||||
parent->child(!leaf) = tmp;
|
||||
else
|
||||
parent->child(leaf) = tmp;
|
||||
}
|
||||
else
|
||||
m_root = tmp;
|
||||
|
||||
node->setParent(tmp);
|
||||
}
|
||||
|
||||
void CIntrusiveTreeBase::recolor(N* parent, N* node)
|
||||
{
|
||||
N *sibling;
|
||||
|
||||
while ((!node || node->isBlack()) && node != m_root)
|
||||
{
|
||||
N::Leaf leaf = node == parent->left() ? N::Right : N::Left;
|
||||
sibling = parent->child(leaf);
|
||||
|
||||
if (sibling->isRed())
|
||||
{
|
||||
sibling->setBlack();
|
||||
parent->setRed();
|
||||
rotate(parent, leaf);
|
||||
sibling = parent->child(leaf);
|
||||
}
|
||||
|
||||
N::Color clr[2];
|
||||
clr[N::Left] = sibling->left() ? sibling->left()->getColor() : N::Black;
|
||||
clr[N::Right] = sibling->right() ? sibling->right()->getColor() : N::Black;
|
||||
|
||||
if (clr[N::Left] == N::Black && clr[N::Right] == N::Black)
|
||||
{
|
||||
sibling->setRed();
|
||||
node = parent;
|
||||
parent = node->getParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clr[leaf] == N::Black)
|
||||
{
|
||||
sibling->child(!leaf)->setBlack();
|
||||
sibling->setRed();
|
||||
rotate(sibling, !leaf);
|
||||
sibling = parent->child(leaf);
|
||||
}
|
||||
|
||||
sibling->setColor(parent->getColor());
|
||||
parent->setBlack();
|
||||
sibling->child(leaf)->setBlack();
|
||||
rotate(parent, leaf);
|
||||
|
||||
node = m_root;
|
||||
}
|
||||
}
|
||||
|
||||
if (node)
|
||||
node->setBlack();
|
||||
}
|
||||
|
||||
auto CIntrusiveTreeBase::walk(N* node, N::Leaf leaf) const -> N*
|
||||
{
|
||||
if (node->child(leaf))
|
||||
{
|
||||
node = node->child(leaf);
|
||||
while (node->child(!leaf))
|
||||
node = node->child(!leaf);
|
||||
}
|
||||
else
|
||||
{
|
||||
N *parent = node->getParent();
|
||||
while (parent && node == parent->child(leaf))
|
||||
{
|
||||
node = parent;
|
||||
parent = node->getParent();
|
||||
}
|
||||
node = parent;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void CIntrusiveTreeBase::insert(N* node, N* parent)
|
||||
{
|
||||
node->left() = node->right() = nullptr;
|
||||
node->setParent(parent);
|
||||
node->setRed();
|
||||
|
||||
while ((parent = node->getParent()) && parent->isRed())
|
||||
{
|
||||
N *grandparent = parent->getParent();
|
||||
N::Leaf leaf = parent == grandparent->left() ? N::Right : N::Left;
|
||||
N *uncle = grandparent->child(leaf);
|
||||
|
||||
if (uncle && uncle->isRed())
|
||||
{
|
||||
uncle->setBlack();
|
||||
parent->setBlack();
|
||||
grandparent->setRed();
|
||||
|
||||
node = grandparent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parent->child(leaf) == node)
|
||||
{
|
||||
rotate(parent, leaf);
|
||||
|
||||
N* tmp = parent;
|
||||
parent = node;
|
||||
node = tmp;
|
||||
}
|
||||
|
||||
parent->setBlack();
|
||||
grandparent->setRed();
|
||||
rotate(grandparent, !leaf);
|
||||
}
|
||||
}
|
||||
|
||||
m_root->setBlack();
|
||||
}
|
||||
|
||||
void CIntrusiveTreeBase::remove(N* node)
|
||||
{
|
||||
N::Color color;
|
||||
N *child, *parent;
|
||||
|
||||
if (node->left() && node->right())
|
||||
{
|
||||
N *old = node;
|
||||
|
||||
node = node->right();
|
||||
while (node->left())
|
||||
node = node->left();
|
||||
|
||||
parent = old->getParent();
|
||||
if (parent)
|
||||
{
|
||||
if (parent->left() == old)
|
||||
parent->left() = node;
|
||||
else
|
||||
parent->right() = node;
|
||||
}
|
||||
else
|
||||
m_root = node;
|
||||
|
||||
child = node->right();
|
||||
parent = node->getParent();
|
||||
color = node->getColor();
|
||||
|
||||
if (parent == old)
|
||||
parent = node;
|
||||
else
|
||||
{
|
||||
if (child)
|
||||
child->setParent(parent);
|
||||
parent->left() = child;
|
||||
|
||||
node->right() = old->right();
|
||||
old->right()->setParent(node);
|
||||
}
|
||||
|
||||
node->setParent(old->getParent());
|
||||
node->setColor(old->getColor());
|
||||
node->left() = old->left();
|
||||
old->left()->setParent(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
child = node->left() ? node->right() : node->left();
|
||||
parent = node->getParent();
|
||||
color = node->getColor();
|
||||
|
||||
if (child)
|
||||
child->setParent(parent);
|
||||
if (parent)
|
||||
{
|
||||
if (parent->left() == node)
|
||||
parent->left() = child;
|
||||
else
|
||||
parent->right() = child;
|
||||
}
|
||||
else
|
||||
m_root = child;
|
||||
}
|
||||
|
||||
if (color == N::Black)
|
||||
recolor(parent, child);
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
** Sample Framework for deko3d Applications
|
||||
** CMemPool.cpp: Pooled dynamic memory allocation manager class
|
||||
*/
|
||||
#include "CMemPool.h"
|
||||
|
||||
inline auto CMemPool::_newSlice() -> Slice*
|
||||
{
|
||||
Slice* ret = m_sliceHeap.pop();
|
||||
if (!ret) ret = (Slice*)::malloc(sizeof(Slice));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline void CMemPool::_deleteSlice(Slice* s)
|
||||
{
|
||||
if (!s) return;
|
||||
m_sliceHeap.add(s);
|
||||
}
|
||||
|
||||
CMemPool::~CMemPool()
|
||||
{
|
||||
m_memMap.iterate([](Slice* s) { ::free(s); });
|
||||
m_sliceHeap.iterate([](Slice* s) { ::free(s); });
|
||||
m_blocks.iterate([](Block* blk) {
|
||||
blk->m_obj.destroy();
|
||||
::free(blk);
|
||||
});
|
||||
}
|
||||
|
||||
auto CMemPool::allocate(uint32_t size, uint32_t alignment) -> Handle
|
||||
{
|
||||
if (!size) return nullptr;
|
||||
if (alignment & (alignment - 1)) return nullptr;
|
||||
size = (size + alignment - 1) &~ (alignment - 1);
|
||||
#ifdef DEBUG_CMEMPOOL
|
||||
printf("Allocating size=%u alignment=0x%x\n", size, alignment);
|
||||
{
|
||||
Slice* temp = /*m_freeList*/m_memMap.first();
|
||||
while (temp)
|
||||
{
|
||||
printf("-- blk %p | 0x%08x-0x%08x | %s used\n", temp->m_block, temp->m_start, temp->m_end, temp->m_pool ? " " : "not");
|
||||
temp = /*m_freeList*/m_memMap.next(temp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t start_offset = 0;
|
||||
uint32_t end_offset = 0;
|
||||
Slice* slice = m_freeList.find(size, decltype(m_freeList)::LowerBound);
|
||||
while (slice)
|
||||
{
|
||||
#ifdef DEBUG_CMEMPOOL
|
||||
printf(" * Checking slice 0x%x - 0x%x\n", slice->m_start, slice->m_end);
|
||||
#endif
|
||||
start_offset = (slice->m_start + alignment - 1) &~ (alignment - 1);
|
||||
end_offset = start_offset + size;
|
||||
if (end_offset <= slice->m_end)
|
||||
break;
|
||||
slice = m_freeList.next(slice);
|
||||
}
|
||||
|
||||
if (!slice)
|
||||
{
|
||||
Block* blk = (Block*)::malloc(sizeof(Block));
|
||||
if (!blk)
|
||||
return nullptr;
|
||||
|
||||
uint32_t unusableSize = (m_flags & DkMemBlockFlags_Code) ? DK_SHADER_CODE_UNUSABLE_SIZE : 0;
|
||||
uint32_t blkSize = m_blockSize - unusableSize;
|
||||
blkSize = size > blkSize ? size : blkSize;
|
||||
blkSize = (blkSize + unusableSize + DK_MEMBLOCK_ALIGNMENT - 1) &~ (DK_MEMBLOCK_ALIGNMENT - 1);
|
||||
#ifdef DEBUG_CMEMPOOL
|
||||
printf(" ! Allocating block of size 0x%x\n", blkSize);
|
||||
#endif
|
||||
blk->m_obj = dk::MemBlockMaker{m_dev, blkSize}.setFlags(m_flags).create();
|
||||
if (!blk->m_obj)
|
||||
{
|
||||
::free(blk);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
slice = _newSlice();
|
||||
if (!slice)
|
||||
{
|
||||
blk->m_obj.destroy();
|
||||
::free(blk);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
slice->m_pool = nullptr;
|
||||
slice->m_block = blk;
|
||||
slice->m_start = 0;
|
||||
slice->m_end = blkSize - unusableSize;
|
||||
m_memMap.add(slice);
|
||||
|
||||
blk->m_cpuAddr = blk->m_obj.getCpuAddr();
|
||||
blk->m_gpuAddr = blk->m_obj.getGpuAddr();
|
||||
m_blocks.add(blk);
|
||||
|
||||
start_offset = 0;
|
||||
end_offset = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_CMEMPOOL
|
||||
printf(" * found it\n");
|
||||
#endif
|
||||
m_freeList.remove(slice);
|
||||
}
|
||||
|
||||
if (start_offset != slice->m_start)
|
||||
{
|
||||
Slice* t = _newSlice();
|
||||
if (!t) goto _bad;
|
||||
t->m_pool = nullptr;
|
||||
t->m_block = slice->m_block;
|
||||
t->m_start = slice->m_start;
|
||||
t->m_end = start_offset;
|
||||
#ifdef DEBUG_CMEMPOOL
|
||||
printf("-> subdivide left: %08x-%08x\n", t->m_start, t->m_end);
|
||||
#endif
|
||||
m_memMap.addBefore(slice, t);
|
||||
m_freeList.insert(t, true);
|
||||
slice->m_start = start_offset;
|
||||
}
|
||||
|
||||
if (end_offset != slice->m_end)
|
||||
{
|
||||
Slice* t = _newSlice();
|
||||
if (!t) goto _bad;
|
||||
t->m_pool = nullptr;
|
||||
t->m_block = slice->m_block;
|
||||
t->m_start = end_offset;
|
||||
t->m_end = slice->m_end;
|
||||
#ifdef DEBUG_CMEMPOOL
|
||||
printf("-> subdivide right: %08x-%08x\n", t->m_start, t->m_end);
|
||||
#endif
|
||||
m_memMap.addAfter(slice, t);
|
||||
m_freeList.insert(t, true);
|
||||
slice->m_end = end_offset;
|
||||
}
|
||||
|
||||
slice->m_pool = this;
|
||||
return slice;
|
||||
|
||||
_bad:
|
||||
m_freeList.insert(slice, true);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CMemPool::_destroy(Slice* slice)
|
||||
{
|
||||
slice->m_pool = nullptr;
|
||||
|
||||
Slice* left = m_memMap.prev(slice);
|
||||
Slice* right = m_memMap.next(slice);
|
||||
|
||||
if (left && left->canCoalesce(*slice))
|
||||
{
|
||||
slice->m_start = left->m_start;
|
||||
m_freeList.remove(left);
|
||||
m_memMap.remove(left);
|
||||
_deleteSlice(left);
|
||||
}
|
||||
|
||||
if (right && slice->canCoalesce(*right))
|
||||
{
|
||||
slice->m_end = right->m_end;
|
||||
m_freeList.remove(right);
|
||||
m_memMap.remove(right);
|
||||
_deleteSlice(right);
|
||||
}
|
||||
|
||||
m_freeList.insert(slice, true);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
** Sample Framework for deko3d Applications
|
||||
** CShader.cpp: Utility class for loading shaders from the filesystem
|
||||
*/
|
||||
#include "CShader.h"
|
||||
|
||||
struct DkshHeader
|
||||
{
|
||||
uint32_t magic; // DKSH_MAGIC
|
||||
uint32_t header_sz; // sizeof(DkshHeader)
|
||||
uint32_t control_sz;
|
||||
uint32_t code_sz;
|
||||
uint32_t programs_off;
|
||||
uint32_t num_programs;
|
||||
};
|
||||
|
||||
bool CShader::load(CMemPool& pool, const char* path)
|
||||
{
|
||||
FILE* f;
|
||||
DkshHeader hdr;
|
||||
void* ctrlmem;
|
||||
|
||||
m_codemem.destroy();
|
||||
|
||||
f = fopen(path, "rb");
|
||||
if (!f) return false;
|
||||
|
||||
if (!fread(&hdr, sizeof(hdr), 1, f))
|
||||
goto _fail0;
|
||||
|
||||
ctrlmem = malloc(hdr.control_sz);
|
||||
if (!ctrlmem)
|
||||
goto _fail0;
|
||||
|
||||
rewind(f);
|
||||
if (!fread(ctrlmem, hdr.control_sz, 1, f))
|
||||
goto _fail1;
|
||||
|
||||
m_codemem = pool.allocate(hdr.code_sz, DK_SHADER_CODE_ALIGNMENT);
|
||||
if (!m_codemem)
|
||||
goto _fail1;
|
||||
|
||||
if (!fread(m_codemem.getCpuAddr(), hdr.code_sz, 1, f))
|
||||
goto _fail2;
|
||||
|
||||
dk::ShaderMaker{m_codemem.getMemBlock(), m_codemem.getOffset()}
|
||||
.setControl(ctrlmem)
|
||||
.setProgramId(0)
|
||||
.initialize(m_shader);
|
||||
|
||||
free(ctrlmem);
|
||||
fclose(f);
|
||||
return true;
|
||||
|
||||
_fail2:
|
||||
m_codemem.destroy();
|
||||
_fail1:
|
||||
free(ctrlmem);
|
||||
_fail0:
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
** Sample Framework for deko3d Applications
|
||||
** FileLoader.cpp: Helpers for loading data from the filesystem directly into GPU memory
|
||||
*/
|
||||
#include "FileLoader.h"
|
||||
|
||||
CMemPool::Handle LoadFile(CMemPool& pool, const char* path, uint32_t alignment)
|
||||
{
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (!f) return nullptr;
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
uint32_t fsize = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
CMemPool::Handle mem = pool.allocate(fsize, alignment);
|
||||
if (!mem)
|
||||
{
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fread(mem.getCpuAddr(), fsize, 1, f);
|
||||
fclose(f);
|
||||
|
||||
return mem;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
Copyright (C) 2020 fincs
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user