#include "filesystem.h" #include "rendering.h" #include "tier0/lib.h" #include "tier1/utlvector.h" #include "vk_helper.h" #include "tier0/platform.h" #include "vulkan/vulkan_core.h" #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" VkSampler g_invalidTextureSampler; vk_buffer_t g_cameraProperties; CameraProjection *g_cameraDataMap; IMaterial *g_pDefaultMaterial; IMaterial *g_pCurrentMaterial; vk_image2d_t g_meshDepth; vk_image2d_t g_meshDepthMSAA; vk_image2d_t g_meshColor; vk_image2d_t g_meshColorMSAA; void IVulkan::Init() { char invalidTexture[1024] = {}; for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { int index = i * 16 + j; if ((i + j) % 2 == 0) { invalidTexture[index*4] = 255; } } } ITextureManager::LoadTexture(invalidTexture, 16, 16, 4); VkPhysicalDeviceProperties properties{}; vkGetPhysicalDeviceProperties(g_vkPhysicalDevice, &properties); VkSamplerCreateInfo samplerInfo{}; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.magFilter = VK_FILTER_NEAREST; samplerInfo.minFilter = VK_FILTER_NEAREST; samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; samplerInfo.anisotropyEnable = VK_FALSE; samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; samplerInfo.unnormalizedCoordinates = VK_FALSE; samplerInfo.compareEnable = VK_FALSE; samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.mipLodBias = 0.0f; samplerInfo.minLod = 0.0f; samplerInfo.maxLod = 0.0f; vkCreateSampler(g_vkDevice, &samplerInfo, nullptr, &g_invalidTextureSampler); g_cameraProperties.Create(sizeof(CameraProjection), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); g_cameraDataMap = (CameraProjection*)g_cameraProperties.Map(0, 64); g_meshDepth.Create(1280, 720, VK_FORMAT_D32_SFLOAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_SAMPLE_COUNT_1_BIT); g_meshDepthMSAA.Create(1280, 720, VK_FORMAT_D32_SFLOAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, VK_SAMPLE_COUNT_4_BIT); g_meshColor.Create(1280, 720, VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_SAMPLE_COUNT_1_BIT); g_meshColorMSAA.Create(1280, 720, VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, VK_SAMPLE_COUNT_4_BIT); IMeshRenderer::Init(); }; void IVulkan::Frame() { glm_mat4_identity(g_cameraDataMap->viewprojection); glm_perspective(glm_rad(90),(float)g_nWindowWidth/g_nWindowHeight, 0.01, 100, g_cameraDataMap->viewprojection); glm_rotate(g_cameraDataMap->viewprojection, glm_rad(90), (vec4){1,0,0,0}); glm_scale(g_cameraDataMap->viewprojection, (vec4){1,-1,1,1}); glm_rotate(g_cameraDataMap->viewprojection, glm_rad(90), (vec4){0,0,1,0}); if (g_bConfigNotify) { g_meshDepth.Destroy(); g_meshDepthMSAA.Destroy(); g_meshColor.Destroy(); g_meshColorMSAA.Destroy(); g_meshDepth.Create(g_nWindowWidth, g_nWindowHeight, VK_FORMAT_D32_SFLOAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_SAMPLE_COUNT_1_BIT); g_meshDepthMSAA.Create(g_nWindowWidth, g_nWindowHeight, VK_FORMAT_D32_SFLOAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, VK_SAMPLE_COUNT_1_BIT); g_meshColor.Create(g_nWindowWidth, g_nWindowHeight, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_SAMPLE_COUNT_1_BIT); g_meshColorMSAA.Create(g_nWindowWidth, g_nWindowHeight, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, VK_SAMPLE_COUNT_4_BIT); } IMeshRenderer::Frame(0); }; void vk_shader_t::Create( const char *szPath, VkShaderStageFlagBits shaderStage ) { FileHandle_t shader = IFileSystem::Open(szPath, IFILE_READ); if (!shader) Plat_FatalErrorFunc("Failed to open shader %s\n", szPath); CUtlBuffer buffer(IFileSystem::Size(shader)); IFileSystem::Read(shader, buffer.GetMemory(), buffer.GetSize()); Create(buffer, shaderStage); IFileSystem::Close(shader); } void vk_shader_t::Create( CUtlBuffer &spirv, VkShaderStageFlagBits shaderStage ) { if (m_shaderModule != NULL) Plat_FatalErrorFunc("Shader already exists"); VkShaderModuleCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; createInfo.codeSize = spirv.GetSize(); createInfo.pCode = (uint32_t*)spirv.GetMemory(); vkCreateShaderModule(g_vkDevice, &createInfo, NULL, &m_shaderModule); m_stageCreateInfo = {}; m_stageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; m_stageCreateInfo.module = m_shaderModule; m_stageCreateInfo.stage = shaderStage; m_stageCreateInfo.pName = "main"; } void vk_shader_t::Destroy( void ) { if (m_shaderModule == NULL) Plat_FatalErrorFunc("Shader doesn't exist"); vkDestroyShaderModule(g_vkDevice, m_shaderModule, NULL); } void vk_tripipeline_t::Create( CUtlVector &shaders, CUtlVector &bindings, uint32_t pushConstantSize, CUtlVector formats ) { VkPushConstantRange pushConstantRange = {}; pushConstantRange.stageFlags = VK_SHADER_STAGE_ALL; pushConstantRange.offset = 0; pushConstantRange.size = pushConstantSize; VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {}; descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptorSetLayoutCreateInfo.bindingCount = bindings.GetSize(); descriptorSetLayoutCreateInfo.pBindings = bindings.GetData(); vkCreateDescriptorSetLayout(g_vkDevice, &descriptorSetLayoutCreateInfo, NULL, &m_descriptorSetLayout); VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {}; pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutCreateInfo.setLayoutCount = 1; pipelineLayoutCreateInfo.pSetLayouts = &m_descriptorSetLayout; if (pushConstantSize != 0) { pipelineLayoutCreateInfo.pushConstantRangeCount = 1; pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; } vkCreatePipelineLayout(g_vkDevice, &pipelineLayoutCreateInfo, NULL, &m_layout); VkDynamicState dynamicStates[] = { /* pVertexInputState */ VK_DYNAMIC_STATE_VERTEX_INPUT_EXT, /* pInputAssemblyState */ VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE, VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, /* pTessellationState */ VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT, /* pViewportState */ VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT, VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, /* pRasterizationState */ VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT, VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE, VK_DYNAMIC_STATE_POLYGON_MODE_EXT, VK_DYNAMIC_STATE_CULL_MODE, VK_DYNAMIC_STATE_FRONT_FACE, VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE, VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_LINE_WIDTH, /* pMultisampleState */ VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT, VK_DYNAMIC_STATE_SAMPLE_MASK_EXT, VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT, /* pDepthStencilState */ VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE, VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE, VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, VK_DYNAMIC_STATE_STENCIL_OP, VK_DYNAMIC_STATE_DEPTH_BOUNDS, /* pColorBlendState */ VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT, VK_DYNAMIC_STATE_LOGIC_OP_EXT, VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT, VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT, VK_DYNAMIC_STATE_BLEND_CONSTANTS, }; VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, .dynamicStateCount = sizeof(dynamicStates)/sizeof(VkDynamicState), .pDynamicStates = dynamicStates, }; VkPipelineInputAssemblyStateCreateInfo piasci = { .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, .primitiveRestartEnable = VK_TRUE, }; VkPipelineRenderingCreateInfo prci = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .pNext = NULL, .colorAttachmentCount = (uint32_t)formats.GetSize(), .pColorAttachmentFormats = formats.GetData(), .depthAttachmentFormat = VK_FORMAT_D32_SFLOAT, }; VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo = {}; graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; graphicsPipelineCreateInfo.pInputAssemblyState = &piasci; graphicsPipelineCreateInfo.layout = m_layout; graphicsPipelineCreateInfo.pDynamicState = &pipelineDynamicStateCreateInfo; graphicsPipelineCreateInfo.stageCount = shaders.GetSize(); CUtlVector stages(graphicsPipelineCreateInfo.stageCount); uint32_t i = 0; for (auto &shader: shaders) { stages[i] = shader.m_stageCreateInfo; i++; } graphicsPipelineCreateInfo.pStages = stages.GetData(); graphicsPipelineCreateInfo.pNext = &prci; vkCreateGraphicsPipelines(g_vkDevice, NULL, 1, &graphicsPipelineCreateInfo, NULL, &m_pipeline); } void vk_tripipeline_t::Destroy() { } void vk_buffer_t::Create(size_t size, VkBufferUsageFlags usage) { VkBufferCreateInfo bufferCreateInfo = {}; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferCreateInfo.usage = usage; bufferCreateInfo.size = size; VmaAllocationCreateInfo allocInfo = {}; allocInfo.usage = VMA_MEMORY_USAGE_AUTO; allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT; m_nSize = size; vmaCreateBuffer(g_allocator, &bufferCreateInfo, &allocInfo, &m_buffer, &m_memory, NULL); } void vk_buffer_t::Destroy() { } void *vk_buffer_t::Map(size_t offset, size_t size) { void *pData; vmaMapMemory(g_allocator, m_memory, &pData); return pData; } void vk_buffer_t::Unmap() { vmaUnmapMemory(g_allocator, m_memory); } void vk_buffer_t::CopyTo(struct vk_image2d_t *image) { } void vk_buffer_t::CopyTo(struct vk_buffer_t *buffer) { } void vk_image2d_t::Create(size_t x, size_t y, VkFormat format, VkImageUsageFlags usage, VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT) { VkImageCreateInfo imageInfo={}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.imageType = VK_IMAGE_TYPE_2D; imageInfo.extent.width = x > 1 ? x : 1; imageInfo.extent.height = y > 1 ? y : 1; imageInfo.extent.depth = 1; imageInfo.mipLevels = 1; imageInfo.arrayLayers = 1; imageInfo.usage = usage; imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; imageInfo.format=format; imageInfo.samples = samples; VmaAllocationCreateInfo alloc = {}; alloc.usage=VMA_MEMORY_USAGE_AUTO; vmaCreateImage(g_allocator, &imageInfo,&alloc, &m_image, &m_memory,0); m_X=imageInfo.extent.width; m_Y=imageInfo.extent.width; m_format=format; VkImageView imageView = 0; VkImageViewCreateInfo imageViewCreateInfo={}; imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; imageViewCreateInfo.format = format; imageViewCreateInfo.image = m_image; imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; if (format == VK_FORMAT_D32_SFLOAT) { imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; } imageViewCreateInfo.subresourceRange.baseMipLevel = 0; imageViewCreateInfo.subresourceRange.levelCount = 1; imageViewCreateInfo.subresourceRange.baseArrayLayer = 0; imageViewCreateInfo.subresourceRange.layerCount = 1; vkCreateImageView(g_vkDevice, &imageViewCreateInfo, 0, &m_imageView); } void vk_image2d_t::Destroy() { vkDestroyImageView(g_vkDevice, m_imageView, NULL); vmaDestroyImage(g_allocator, m_image, NULL); } void CopyTo(struct vk_image2d_t *image); void CopyTo(struct vk_buffer_t *buffer); void *CVertexBuffer::Map() { if (!m_pAllocated) m_pAllocated = m_buffer.Map(0, m_buffer.m_nSize); return m_pAllocated; }; void CVertexBuffer::Unmap() { if (!m_pAllocated) return; m_buffer.Unmap(); m_pAllocated = 0; }; void *CIndexBuffer::Map() { if (!m_pAllocated) m_pAllocated = m_buffer.Map(0, m_buffer.m_nSize); return m_pAllocated; }; void CIndexBuffer::Unmap() { if (!m_pAllocated) return; m_buffer.Unmap(); m_pAllocated = 0; }; CUtlVector g_textures; CUtlVector g_newtextures; uint32_t ITextureManager::GetTexture(ITexture *pTexture) { uint32_t i = 0; for (ITexture *texture: g_textures) { if (texture == pTexture) return i; i++; }; return 0; } ITexture *ITextureManager::LoadTexture( void *pData, uint32_t X, uint32_t Y, uint32_t numChannels ) { CTexture *pTexture = new CTexture; *pTexture = {}; VkDeviceSize imageSize = X*Y*4; vk_buffer_t gpu_buffer = {}; gpu_buffer.Create(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); void *gpu_buffer_map = gpu_buffer.Map(0, 0); V_memcpy(gpu_buffer_map, pData, imageSize); gpu_buffer.Unmap(); pTexture->image = {}; pTexture->image.Create(X, Y, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); VkCommandPool commandPool; VkCommandBuffer commandBuffer; VkCommandPoolCreateInfo poolInfo{}; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolInfo.queueFamilyIndex = g_drawfamily; poolInfo.flags = 0; vkCreateCommandPool(g_vkDevice, &poolInfo, NULL, &commandPool); VkCommandBufferAllocateInfo cmdAllocInfo{}; cmdAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; cmdAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; cmdAllocInfo.commandPool = commandPool; cmdAllocInfo.commandBufferCount = 1; vkAllocateCommandBuffers(g_vkDevice, &cmdAllocInfo, &commandBuffer); VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; vkBeginCommandBuffer(commandBuffer, &beginInfo); VkImageMemoryBarrier barrier{}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.image = pTexture->image.m_image; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; barrier.subresourceRange.baseMipLevel = 0; barrier.subresourceRange.levelCount = 1; barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.layerCount = 1; barrier.srcAccessMask = 0; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &barrier ); VkBufferImageCopy region{}; region.bufferOffset = 0; region.bufferRowLength = 0; region.bufferImageHeight = 0; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.mipLevel = 0; region.imageSubresource.baseArrayLayer = 0; region.imageSubresource.layerCount = 1; region.imageOffset = {0, 0, 0}; region.imageExtent = {(uint32_t)X, (uint32_t)Y, 1}; vkCmdCopyBufferToImage( commandBuffer, gpu_buffer.m_buffer, pTexture->image.m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion ); barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &barrier ); vkEndCommandBuffer(commandBuffer); VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; vkQueueSubmit(g_drawQueue, 1, &submitInfo, VK_NULL_HANDLE); vkQueueWaitIdle(g_drawQueue); vkFreeCommandBuffers(g_vkDevice, commandPool, 1, &commandBuffer); vkDestroyCommandPool(g_vkDevice, commandPool, NULL); g_newtextures.AppendTail(pTexture); g_textures.AppendTail(pTexture); return pTexture; }; ITexture *ITextureManager::LoadTexture( const char *szName ) { for (ITexture *texture: g_textures) { if (!texture->szName) continue; if (!V_strcmp(texture->szName, szName)) return texture; }; FileHandle_t file = IFileSystem::Open(szName, IFILE_READ); if (!file) Plat_FatalErrorFunc("Failed to load %s\n", szName); CUtlBuffer buffer(IFileSystem::Size(file)); IFileSystem::Read(file, buffer.GetMemory(), buffer.GetSize()); int nImageX; int nImageY; int nImageChannels; stbi_uc *pixels = stbi_load_from_memory((stbi_uc*)buffer.GetMemory(), buffer.GetSize(), &nImageX, &nImageY, &nImageChannels, STBI_rgb_alpha); ITexture *pTexture = ITextureManager::LoadTexture(pixels, nImageX, nImageY, 4); pTexture->szName = szName; return pTexture; }; IMaterial *IRenderer::LoadMaterial( const char *szMaterial ) { FileHandle_t file = IFileSystem::Open(szMaterial, IFILE_READ); IMaterial *pMaterial = new IMaterial; if (!file) { return g_pDefaultMaterial; } IFileSystem::Close(file); } void IRenderer::SetMaterial( IMaterial *pMaterial ) { g_pCurrentMaterial = pMaterial; } IVertexBuffer *IRenderer::CreateVertexBuffer( uint32_t uSize ) { CVertexBuffer *pBuffer = new CVertexBuffer(); pBuffer->m_buffer.Create(uSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); return pBuffer; } IIndexBuffer *IRenderer::CreateIndexBuffer( uint32_t uSize ) { CIndexBuffer *pBuffer = new CIndexBuffer(); pBuffer->m_buffer.Create(uSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); return pBuffer; }