Error GrManagerImpl::initInternal(const GrManagerInitInfo& init) { ANKI_LOGI("Initializing Vulkan backend"); ANKI_CHECK(initInstance(init)); ANKI_CHECK(initSurface(init)); ANKI_CHECK(initDevice(init)); vkGetDeviceQueue(m_device, m_queueIdx, 0, &m_queue); ANKI_CHECK(initSwapchain(init)); { VkPipelineCacheCreateInfo ci = {}; ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; vkCreatePipelineCache(m_device, &ci, nullptr, &m_pplineCache); } ANKI_CHECK(initMemory(*init.m_config)); ANKI_CHECK(m_dsetAlloc.init(getAllocator(), m_device)); m_pplineLayFactory.init(getAllocator(), m_device, &m_dsetAlloc.getDescriptorSetLayoutFactory()); for(PerFrame& f : m_perFrame) { resetFrame(f); } glslang::InitializeProcess(); m_fences.init(getAllocator(), m_device); m_semaphores.init(getAllocator(), m_device); m_queryAlloc.init(getAllocator(), m_device); m_samplerCache = getAllocator().newInstance<GrObjectCache>(m_manager); // Set m_r8g8b8ImagesSupported { VkImageFormatProperties props = {}; VkResult res = vkGetPhysicalDeviceImageFormatProperties(m_physicalDevice, VK_FORMAT_R8G8B8_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &props); if(res == VK_ERROR_FORMAT_NOT_SUPPORTED) { ANKI_LOGI("R8G8B8 Images are not supported. Will workaround this"); m_r8g8b8ImagesSupported = false; } else { ANKI_ASSERT(res == VK_SUCCESS); ANKI_LOGI("R8G8B8 Images are supported"); m_r8g8b8ImagesSupported = true; } } // Set m_s8ImagesSupported { VkImageFormatProperties props = {}; VkResult res = vkGetPhysicalDeviceImageFormatProperties(m_physicalDevice, VK_FORMAT_S8_UINT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &props); if(res == VK_ERROR_FORMAT_NOT_SUPPORTED) { ANKI_LOGI("S8 Images are not supported. Will workaround this"); m_s8ImagesSupported = false; } else { ANKI_ASSERT(res == VK_SUCCESS); ANKI_LOGI("S8 Images are supported"); m_s8ImagesSupported = true; } } // Set m_d24S8ImagesSupported { VkImageFormatProperties props = {}; VkResult res = vkGetPhysicalDeviceImageFormatProperties(m_physicalDevice, VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &props); if(res == VK_ERROR_FORMAT_NOT_SUPPORTED) { ANKI_LOGI("D24S8 Images are not supported. Will workaround this"); m_d24S8ImagesSupported = false; } else { ANKI_ASSERT(res == VK_SUCCESS); ANKI_LOGI("D24S8 Images are supported"); m_d24S8ImagesSupported = true; } } return ErrorCode::NONE; }
//============================================================================== SceneFrameAllocator<U8> SceneNode::getFrameAllocator() const { ANKI_ASSERT(m_scene); return m_scene->getFrameAllocator(); }
Command(UserCallback callback, void* userData) : m_callback(callback), m_userData(userData) { ANKI_ASSERT(m_callback); }
//============================================================================== ProgramResourcePointer& Material::getProgram( const RenderingKey key, U32 shaderId) { ANKI_ASSERT((U)key.m_pass < m_passesCount); ANKI_ASSERT(key.m_lod < m_lodsCount); if(key.m_tessellation) { ANKI_ASSERT(m_tessellation); } // Calc the count that are before this shader U tessCount = m_tessellation ? 2 : 1; U count = 0; switch(shaderId) { case 4: // Count of geom count += 0; case 3: // Count of tess if(m_tessellation) { count += m_passesCount * m_lodsCount; } case 2: // Count of tess if(m_tessellation) { count += m_passesCount * m_lodsCount; } case 1: // Count of vert count += m_passesCount * m_lodsCount * tessCount; case 0: break; default: ANKI_ASSERT(0); } // Calc the idx U idx = 0; switch(shaderId) { case 0: idx = (U)key.m_pass * m_lodsCount * tessCount + key.m_lod * tessCount + (key.m_tessellation ? 1 : 0); break; case 1: case 2: case 4: idx = (U)key.m_pass * m_lodsCount + key.m_lod; break; default: ANKI_ASSERT(0); } idx += count; ANKI_ASSERT(idx < m_progs.size()); ProgramResourcePointer& out = m_progs[idx]; if(out.isLoaded()) { ANKI_ASSERT( computeShaderTypeIndex(out->getGlProgram().getType()) == shaderId); } return out; }
//============================================================================== void Material::populateVariables(const MaterialProgramCreator& mspc) { for(auto in : mspc.getInputVariables()) { if(in.m_constant) { continue; } MaterialVariable* mtlvar = nullptr; const GlProgramVariable* glvar = nullptr; // Find the input variable in one of the programs for(const ProgramResourcePointer& progr : m_progs) { const GlProgramHandle& prog = progr->getGlProgram(); glvar = prog.tryFindVariable(in.m_name.toCString()); if(glvar) { break; } } // Check if variable found if(glvar == nullptr) { throw ANKI_EXCEPTION("Variable not found in " "at least one program: %s", &in.m_name[0]); } switch(glvar->getDataType()) { // samplers case GL_SAMPLER_2D: case GL_SAMPLER_CUBE: { TextureResourcePointer tp; if(in.m_value.size() > 0) { tp = TextureResourcePointer( in.m_value[0].toCString(), m_resources); } auto alloc = m_resources->_getAllocator(); mtlvar = alloc.newInstance< MaterialVariableTemplate<TextureResourcePointer>>( glvar, false, &tp, 1, alloc); } break; // F32 case GL_FLOAT: mtlvar = newMaterialVariable<F32>(*glvar, in, m_resources->_getAllocator(), m_resources->_getTempAllocator()); break; // vec2 case GL_FLOAT_VEC2: mtlvar = newMaterialVariable<Vec2>(*glvar, in, m_resources->_getAllocator(), m_resources->_getTempAllocator()); break; // vec3 case GL_FLOAT_VEC3: mtlvar = newMaterialVariable<Vec3>(*glvar, in, m_resources->_getAllocator(), m_resources->_getTempAllocator()); break; // vec4 case GL_FLOAT_VEC4: mtlvar = newMaterialVariable<Vec4>(*glvar, in, m_resources->_getAllocator(), m_resources->_getTempAllocator()); break; // mat3 case GL_FLOAT_MAT3: mtlvar = newMaterialVariable<Mat3>(*glvar, in, m_resources->_getAllocator(), m_resources->_getTempAllocator()); break; // mat4 case GL_FLOAT_MAT4: mtlvar = newMaterialVariable<Mat4>(*glvar, in, m_resources->_getAllocator(), m_resources->_getTempAllocator()); break; // default is error default: ANKI_ASSERT(0); } m_vars.push_back(mtlvar); } }
//============================================================================== void Pps::run(GlCommandBufferHandle& jobs) { ANKI_ASSERT(m_enabled); // First SSAO because it depends on MS where HDR depends on IS if(m_ssao.getEnabled()) { m_ssao.run(jobs); } // Then SSLR because HDR depends on it if(m_sslr.getEnabled()) { m_sslr.run(jobs); } if(m_hdr.getEnabled()) { m_hdr.run(jobs); } if(m_lf.getEnabled()) { m_lf.run(jobs); } Bool drawToDefaultFbo = !m_r->getDbg().getEnabled() && !m_r->getIsOffscreen() && m_r->getRenderingQuality() == 1.0; if(drawToDefaultFbo) { m_r->getDefaultFramebuffer().bind(jobs, true); jobs.setViewport(0, 0, m_r->getWindowWidth(), m_r->getWindowHeight()); } else { m_fb.bind(jobs, true); jobs.setViewport(0, 0, m_r->getWidth(), m_r->getHeight()); } m_ppline.bind(jobs); m_r->getIs()._getRt().bind(jobs, 0); if(m_ssao.getEnabled()) { m_ssao.getRt().bind(jobs, 1); } if(m_lf.getEnabled()) { m_lf._getRt().bind(jobs, 2); } else if(m_hdr.getEnabled()) { m_hdr._getRt().bind(jobs, 2); } m_r->drawQuad(jobs); }
//============================================================================== Bool Gjk::update(const Support& a) { if(m_count == 2) { Vec4 ao = -a.m_v; // Compute the vectors parallel to the edges we'll test Vec4 ab = m_simplex[1].m_v - a.m_v; Vec4 ac = m_simplex[2].m_v - a.m_v; // Compute the triangle's normal Vec4 abc = ab.cross(ac); // Compute a vector within the plane of the triangle, // Pointing away from the edge ab Vec4 abp = ab.cross(abc); if(abp.dot(ao) > 0.0) { // The origin lies outside the triangle, near the edge ab m_simplex[2] = m_simplex[1]; m_simplex[1] = a; m_dir = crossAba(ab, ao); return false; } // Perform a similar test for the edge ac Vec4 acp = abc.cross(ac); if(acp.dot(ao) > 0.0) { m_simplex[1] = a; m_dir = crossAba(ac, ao); return false; } // If we get here, then the origin must be within the triangle, // but we care whether it is above or below it, so test if(abc.dot(ao) > 0.0) { m_simplex[3] = m_simplex[2]; m_simplex[2] = m_simplex[1]; m_simplex[1] = a; m_dir = abc; } else { m_simplex[3] = m_simplex[1]; m_simplex[1] = a; m_dir = -abc; } m_count = 3; // Again, need a tetrahedron to enclose the origin return false; } else if(m_count == 3) { Vec4 ao = -a.m_v; Vec4 ab = m_simplex[1].m_v - a.m_v; Vec4 ac = m_simplex[2].m_v - a.m_v; Vec4 abc = ab.cross(ac); Vec4 ad, acd, adb; if(abc.dot(ao) > 0.0) { // In front of triangle ABC goto check_face; } ad = m_simplex[3].m_v - a.m_v; acd = ac.cross(ad); if(acd.dot(ao) > 0.0) { // In front of triangle ACD m_simplex[1] = m_simplex[2]; m_simplex[2] = m_simplex[3]; ab = ac; ac = ad; abc = acd; goto check_face; } adb = ad.cross(ab); if(adb.dot(ao) > 0.0) { // In front of triangle ADB m_simplex[2] = m_simplex[1]; m_simplex[1] = m_simplex[3]; ac = ab; ab = ad; abc = adb; goto check_face; } // Behind all three faces, the origin is in the tetrahedron, we're done m_simplex[0] = a; m_count = 4; return true; check_face: // We have a CCW wound triangle ABC // the point is in front of this triangle // it is NOT "below" edge BC // it is NOT "above" the plane through A that's parallel to BC Vec4 abp = ab.cross(abc); if(abp.dot(ao) > 0.0) { m_simplex[2] = m_simplex[1]; m_simplex[1] = a; m_dir = crossAba(ab, ao); m_count = 2; return false; } Vec4 acp = abc.cross(ac); if(acp.dot(ao) > 0.0) { m_simplex[1] = a; m_dir = crossAba(ac, ao); m_count = 2; return false; } m_simplex[3] = m_simplex[2]; m_simplex[2] = m_simplex[1]; m_simplex[1] = a; m_dir = abc; m_count = 3; return false; } ANKI_ASSERT(0); return true; }
void PipelineImpl::initVertexState() { for(U i = 0; i < m_in.m_vertex.m_attributeCount; ++i) { const VertexAttributeBinding& binding = m_in.m_vertex.m_attributes[i]; Attribute& cache = m_cache.m_attribs[i]; // Component count if(binding.m_format == PixelFormat(ComponentFormat::R32, TransformFormat::FLOAT)) { cache.m_compCount = 1; cache.m_type = GL_FLOAT; cache.m_normalized = false; } else if(binding.m_format == PixelFormat(ComponentFormat::R32G32, TransformFormat::FLOAT)) { cache.m_compCount = 2; cache.m_type = GL_FLOAT; cache.m_normalized = false; } else if(binding.m_format == PixelFormat(ComponentFormat::R32G32B32, TransformFormat::FLOAT)) { cache.m_compCount = 3; cache.m_type = GL_FLOAT; cache.m_normalized = false; } else if(binding.m_format == PixelFormat(ComponentFormat::R32G32B32A32, TransformFormat::FLOAT)) { cache.m_compCount = 4; cache.m_type = GL_FLOAT; cache.m_normalized = false; } else if(binding.m_format == PixelFormat(ComponentFormat::R16G16, TransformFormat::FLOAT)) { cache.m_compCount = 2; cache.m_type = GL_HALF_FLOAT; cache.m_normalized = false; } else if(binding.m_format == PixelFormat(ComponentFormat::R16G16, TransformFormat::UNORM)) { cache.m_compCount = 2; cache.m_type = GL_UNSIGNED_SHORT; cache.m_normalized = true; } else if(binding.m_format == PixelFormat(ComponentFormat::R10G10B10A2, TransformFormat::SNORM)) { cache.m_compCount = 4; cache.m_type = GL_INT_2_10_10_10_REV; cache.m_normalized = true; } else if(binding.m_format == PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM)) { cache.m_compCount = 4; cache.m_type = GL_UNSIGNED_BYTE; cache.m_normalized = true; } else if(binding.m_format == PixelFormat(ComponentFormat::R8G8B8, TransformFormat::UNORM)) { cache.m_compCount = 3; cache.m_type = GL_UNSIGNED_BYTE; cache.m_normalized = true; } else { ANKI_ASSERT(0 && "TODO"); } } m_hashes.m_vertex = computeHash(&m_in.m_vertex, sizeof(m_in.m_vertex)); }
static void deletePrograms(GLsizei n, const GLuint* names) { ANKI_ASSERT(n == 1); ANKI_ASSERT(names); glDeleteProgram(*names); }
Error PipelineImpl::createGlPipeline() { Error err = ErrorCode::NONE; // Do checks U mask = 0; U count = 6; while(count-- != 0) { const ShaderPtr& shader = m_in.m_shaders[count]; if(shader.isCreated()) { ANKI_ASSERT(count == enumToType(shader->m_impl->m_type)); mask |= 1 << count; } } if(mask & (1 << 5)) { // Is compute m_compute = true; ANKI_ASSERT((mask & (1 << 5)) == (1 << 5) && "Compute should be alone in the pipeline"); } else { m_compute = false; const U fragVert = (1 << 0) | (1 << 4); ANKI_ASSERT((mask & fragVert) && "Should contain vert and frag"); (void)fragVert; const U tess = (1 << 1) | (1 << 2); if((mask & tess) != 0) { ANKI_ASSERT(((mask & tess) == 0x6) && "Should set both the tessellation shaders"); } } // Create and attach programs m_glName = glCreateProgram(); ANKI_ASSERT(m_glName != 0); for(U i = 0; i < m_in.m_shaders.getSize(); i++) { ShaderPtr& shader = m_in.m_shaders[i]; if(shader.isCreated()) { glAttachShader(m_glName, shader->m_impl->getGlName()); if(i == U(ShaderType::TESSELLATION_CONTROL) || i == U(ShaderType::TESSELLATION_EVALUATION)) { m_tessellation = true; } } } // Validate and check error glLinkProgram(m_glName); GLint status = 0; glGetProgramiv(m_glName, GL_LINK_STATUS, &status); if(!status) { GLint infoLen = 0; GLint charsWritten = 0; DynamicArrayAuto<char> infoLogTxt(getAllocator()); glGetProgramiv(m_glName, GL_INFO_LOG_LENGTH, &infoLen); infoLogTxt.create(infoLen + 1); glGetProgramInfoLog(m_glName, infoLen, &charsWritten, &infoLogTxt[0]); ANKI_LOGE("Ppline error log follows (vs:%u, fs:%u):\n%s", m_in.m_shaders[ShaderType::VERTEX].isCreated() ? m_in.m_shaders[ShaderType::VERTEX]->m_impl->getGlName() : -1, m_in.m_shaders[ShaderType::FRAGMENT].isCreated() ? m_in.m_shaders[ShaderType::FRAGMENT]->m_impl->getGlName() : -1, &infoLogTxt[0]); err = ErrorCode::USER_DATA; } return err; }
static GLenum convertBlendMethod(BlendMethod in) { GLenum out = 0; switch(in) { case BlendMethod::ZERO: out = GL_ZERO; break; case BlendMethod::ONE: out = GL_ONE; break; case BlendMethod::SRC_COLOR: out = GL_SRC_COLOR; break; case BlendMethod::ONE_MINUS_SRC_COLOR: out = GL_ONE_MINUS_SRC_COLOR; break; case BlendMethod::DST_COLOR: out = GL_DST_COLOR; break; case BlendMethod::ONE_MINUS_DST_COLOR: out = GL_ONE_MINUS_DST_COLOR; break; case BlendMethod::SRC_ALPHA: out = GL_SRC_ALPHA; break; case BlendMethod::ONE_MINUS_SRC_ALPHA: out = GL_ONE_MINUS_SRC_ALPHA; break; case BlendMethod::DST_ALPHA: out = GL_DST_ALPHA; break; case BlendMethod::ONE_MINUS_DST_ALPHA: out = GL_ONE_MINUS_DST_ALPHA; break; case BlendMethod::CONSTANT_COLOR: out = GL_CONSTANT_COLOR; break; case BlendMethod::ONE_MINUS_CONSTANT_COLOR: out = GL_ONE_MINUS_CONSTANT_COLOR; break; case BlendMethod::CONSTANT_ALPHA: out = GL_CONSTANT_ALPHA; break; case BlendMethod::ONE_MINUS_CONSTANT_ALPHA: out = GL_ONE_MINUS_CONSTANT_ALPHA; break; case BlendMethod::SRC_ALPHA_SATURATE: out = GL_SRC_ALPHA_SATURATE; break; case BlendMethod::SRC1_COLOR: out = GL_SRC1_COLOR; break; case BlendMethod::ONE_MINUS_SRC1_COLOR: out = GL_ONE_MINUS_SRC1_COLOR; break; case BlendMethod::SRC1_ALPHA: out = GL_SRC1_ALPHA; break; case BlendMethod::ONE_MINUS_SRC1_ALPHA: out = GL_ONE_MINUS_SRC1_ALPHA; break; default: ANKI_ASSERT(0); } return out; }
//============================================================================== void EventManager::unregisterEvent(EventsContainer::Iterator it) { ANKI_ASSERT(it != m_events.getEnd()); m_events.erase(getSceneAllocator(), it); }
//============================================================================== void EventManager::registerEvent(Event* event) { ANKI_ASSERT(event); m_events.pushBack(getSceneAllocator(), event); }
//============================================================================== Error EventManager::create(SceneGraph* scene) { ANKI_ASSERT(scene); m_scene = scene; return ErrorCode::NONE; }
Error GrManagerImpl::initSwapchain(const GrManagerInitInfo& init) { VkSurfaceCapabilitiesKHR surfaceProperties; ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &surfaceProperties)); if(surfaceProperties.currentExtent.width == MAX_U32 || surfaceProperties.currentExtent.height == MAX_U32) { ANKI_LOGE("Wrong surface size"); return ErrorCode::FUNCTION_FAILED; } m_surfaceWidth = surfaceProperties.currentExtent.width; m_surfaceHeight = surfaceProperties.currentExtent.height; uint32_t formatCount; ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr)); DynamicArrayAuto<VkSurfaceFormatKHR> formats(getAllocator()); formats.create(formatCount); ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, &formats[0])); VkColorSpaceKHR colorspace = VK_COLOR_SPACE_MAX_ENUM_KHR; while(formatCount--) { if(formats[formatCount].format == VK_FORMAT_B8G8R8A8_UNORM) { m_surfaceFormat = formats[formatCount].format; colorspace = formats[formatCount].colorSpace; break; } } if(m_surfaceFormat == VK_FORMAT_UNDEFINED) { ANKI_LOGE("Surface format not found"); return ErrorCode::FUNCTION_FAILED; } // Chose present mode uint32_t presentModeCount; vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr); presentModeCount = min(presentModeCount, 4u); Array<VkPresentModeKHR, 4> presentModes; vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, &presentModes[0]); VkPresentModeKHR presentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; if(init.m_config->getNumber("vsync")) { presentMode = VK_PRESENT_MODE_FIFO_KHR; } else { for(U i = 0; i < presentModeCount; ++i) { if(presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { presentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } else if(presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) { presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; break; } } } if(presentMode == VK_PRESENT_MODE_MAX_ENUM_KHR) { ANKI_LOGE("VK: Couldn't find a present mode"); return ErrorCode::FUNCTION_FAILED; } // Create swapchain VkSwapchainCreateInfoKHR ci = {}; ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; ci.surface = m_surface; ci.minImageCount = MAX_FRAMES_IN_FLIGHT; ci.imageFormat = m_surfaceFormat; ci.imageColorSpace = colorspace; ci.imageExtent = surfaceProperties.currentExtent; ci.imageArrayLayers = 1; ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; ci.queueFamilyIndexCount = 1; ci.pQueueFamilyIndices = &m_queueIdx; ci.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; ci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; ci.presentMode = presentMode; ci.clipped = false; ci.oldSwapchain = VK_NULL_HANDLE; ANKI_VK_CHECK(vkCreateSwapchainKHR(m_device, &ci, nullptr, &m_swapchain)); // Get images uint32_t count = 0; ANKI_VK_CHECK(vkGetSwapchainImagesKHR(m_device, m_swapchain, &count, nullptr)); if(count != MAX_FRAMES_IN_FLIGHT) { ANKI_LOGE("Requested a swapchain with %u images but got one with %u", MAX_FRAMES_IN_FLIGHT, count); return ErrorCode::FUNCTION_FAILED; } ANKI_LOGI("VK: Created a swapchain. Image count: %u, present mode: %u", count, presentMode); Array<VkImage, MAX_FRAMES_IN_FLIGHT> images; ANKI_VK_CHECK(vkGetSwapchainImagesKHR(m_device, m_swapchain, &count, &images[0])); for(U i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { m_backbuffers[i].m_image = images[i]; ANKI_ASSERT(images[i]); } // Create img views for(U i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { VkImageViewCreateInfo ci = {}; ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; ci.flags = 0; ci.image = m_backbuffers[i].m_image; ci.viewType = VK_IMAGE_VIEW_TYPE_2D; ci.format = m_surfaceFormat; ci.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; ci.subresourceRange.baseMipLevel = 0; ci.subresourceRange.levelCount = 1; ci.subresourceRange.baseArrayLayer = 0; ci.subresourceRange.layerCount = 1; ANKI_VK_CHECK(vkCreateImageView(m_device, &ci, nullptr, &m_backbuffers[i].m_imageView)); } return ErrorCode::NONE; }
Error Is::initInternal(const ConfigSet& config) { m_maxLightIds = config.getNumber("is.maxLightsPerCluster"); if(m_maxLightIds == 0) { ANKI_LOGE("Incorrect number of max light indices"); return ErrorCode::USER_DATA; } m_rtMipCount = computeMaxMipmapCount2d(m_r->getWidth(), m_r->getHeight(), 32); ANKI_ASSERT(m_rtMipCount); U clusterCount = m_r->getTileCountXY().x() * m_r->getTileCountXY().y() * config.getNumber("clusterSizeZ"); m_clusterCount = clusterCount; m_maxLightIds *= clusterCount; m_lightBin = getAllocator().newInstance<LightBin>(getAllocator(), m_r->getTileCountXY().x(), m_r->getTileCountXY().y(), config.getNumber("clusterSizeZ"), &m_r->getThreadPool(), &getGrManager()); // // Load the programs // StringAuto pps(getAllocator()); pps.sprintf("\n#define TILE_COUNT_X %u\n" "#define TILE_COUNT_Y %u\n" "#define CLUSTER_COUNT %u\n" "#define RENDERER_WIDTH %u\n" "#define RENDERER_HEIGHT %u\n" "#define MAX_LIGHT_INDICES %u\n" "#define POISSON %u\n" "#define INDIRECT_ENABLED %u\n" "#define IR_MIPMAP_COUNT %u\n", m_r->getTileCountXY().x(), m_r->getTileCountXY().y(), clusterCount, m_r->getWidth(), m_r->getHeight(), m_maxLightIds, m_r->getSm().getPoissonEnabled(), 1, m_r->getIr().getReflectionTextureMipmapCount()); // point light ANKI_CHECK(getResourceManager().loadResourceToCache(m_lightVert, "shaders/Is.vert.glsl", pps.toCString(), "r_")); ANKI_CHECK(getResourceManager().loadResourceToCache(m_lightFrag, "shaders/Is.frag.glsl", pps.toCString(), "r_")); PipelineInitInfo init; init.m_inputAssembler.m_topology = PrimitiveTopology::TRIANGLE_STRIP; init.m_depthStencil.m_depthWriteEnabled = false; init.m_depthStencil.m_depthCompareFunction = CompareOperation::ALWAYS; init.m_color.m_attachmentCount = 1; init.m_color.m_attachments[0].m_format = IS_COLOR_ATTACHMENT_PIXEL_FORMAT; init.m_shaders[U(ShaderType::VERTEX)] = m_lightVert->getGrShader(); init.m_shaders[U(ShaderType::FRAGMENT)] = m_lightFrag->getGrShader(); m_lightPpline = getGrManager().newInstance<Pipeline>(init); // // Create framebuffer // m_r->createRenderTarget(m_r->getWidth(), m_r->getHeight(), IS_COLOR_ATTACHMENT_PIXEL_FORMAT, TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE | TextureUsageBit::SAMPLED_COMPUTE, SamplingFilter::LINEAR, m_rtMipCount, m_rt); FramebufferInitInfo fbInit; fbInit.m_colorAttachmentCount = 1; fbInit.m_colorAttachments[0].m_texture = m_rt; fbInit.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE; fbInit.m_colorAttachments[0].m_usageInsideRenderPass = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE; m_fb = getGrManager().newInstance<Framebuffer>(fbInit); // // Create resource group // { ResourceGroupInitInfo init; init.m_textures[0].m_texture = m_r->getMs().m_rt0; init.m_textures[1].m_texture = m_r->getMs().m_rt1; init.m_textures[2].m_texture = m_r->getMs().m_rt2; init.m_textures[3].m_texture = m_r->getMs().m_depthRt; init.m_textures[3].m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ; init.m_textures[4].m_texture = m_r->getSm().getSpotTextureArray(); init.m_textures[5].m_texture = m_r->getSm().getOmniTextureArray(); init.m_textures[6].m_texture = m_r->getIr().getReflectionTexture(); init.m_textures[7].m_texture = m_r->getIr().getIrradianceTexture(); init.m_textures[8].m_texture = m_r->getIr().getIntegrationLut(); init.m_textures[8].m_sampler = m_r->getIr().getIntegrationLutSampler(); init.m_uniformBuffers[0].m_uploadedMemory = true; init.m_uniformBuffers[0].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX; init.m_uniformBuffers[1].m_uploadedMemory = true; init.m_uniformBuffers[1].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX; init.m_uniformBuffers[2].m_uploadedMemory = true; init.m_uniformBuffers[2].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX; init.m_uniformBuffers[3].m_uploadedMemory = true; init.m_uniformBuffers[3].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX; init.m_uniformBuffers[4].m_uploadedMemory = true; init.m_uniformBuffers[4].m_usage = BufferUsageBit::UNIFORM_FRAGMENT | BufferUsageBit::UNIFORM_VERTEX; init.m_storageBuffers[0].m_uploadedMemory = true; init.m_storageBuffers[0].m_usage = BufferUsageBit::STORAGE_FRAGMENT_READ | BufferUsageBit::STORAGE_VERTEX_READ; init.m_storageBuffers[1].m_uploadedMemory = true; init.m_storageBuffers[1].m_usage = BufferUsageBit::STORAGE_FRAGMENT_READ | BufferUsageBit::STORAGE_VERTEX_READ; m_rcGroup = getGrManager().newInstance<ResourceGroup>(init); } TextureInitInfo texinit; texinit.m_width = texinit.m_height = 4; texinit.m_usage = TextureUsageBit::SAMPLED_FRAGMENT; texinit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::UNORM); m_dummyTex = getGrManager().newInstance<Texture>(texinit); return ErrorCode::NONE; }
void* GrManagerImpl::reallocateCallback( void* userData, void* original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) { ANKI_ASSERT(!"TODO"); return nullptr; }
void HighRezTimer::stop() { ANKI_ASSERT(m_startTime != 0.0); ANKI_ASSERT(m_stopTime == 0.0); m_stopTime = getCurrentTime(); }
//============================================================================== void DebugDrawer::begin(GLenum primitive) { ANKI_ASSERT(primitive == GL_TRIANGLES || primitive == GL_LINES); m_primitive = primitive; }
void Input::init(NativeWindow* /*nativeWindow*/) { ANKI_ASSERT(gAndroidApp); gAndroidApp->userData = this; gAndroidApp->onAppCmd = handleAndroidEvents; }
//============================================================================== void TextureResource::loadInternal(const CString& filename, ResourceInitializer& rinit) { GlDevice& gl = rinit.m_resources._getGlDevice(); GlCommandBufferHandle jobs(&gl); // Always first to avoid assertions ( // because of the check of the allocator) GlTextureHandle::Initializer init; U layers = 0; Bool driverShouldGenMipmaps = false; // Load image Image* imgPtr = rinit.m_alloc.newInstance<Image>(rinit.m_alloc); Image& img = *imgPtr; img.load(filename, rinit.m_resources.getMaxTextureSize()); // width + height init.m_width = img.getSurface(0, 0).m_width; init.m_height = img.getSurface(0, 0).m_height; // depth if(img.getTextureType() == Image::TextureType::_2D_ARRAY || img.getTextureType() == Image::TextureType::_3D) { init.m_depth = img.getDepth(); } else { init.m_depth = 0; } // target switch(img.getTextureType()) { case Image::TextureType::_2D: init.m_target = GL_TEXTURE_2D; layers = 1; break; case Image::TextureType::CUBE: init.m_target = GL_TEXTURE_CUBE_MAP; layers = 6; break; case Image::TextureType::_2D_ARRAY: init.m_target = GL_TEXTURE_2D_ARRAY; layers = init.m_depth; break; case Image::TextureType::_3D: init.m_target = GL_TEXTURE_3D; layers = init.m_depth; default: ANKI_ASSERT(0); } // Internal format if(img.getColorFormat() == Image::ColorFormat::RGB8) { switch(img.getCompression()) { case Image::DataCompression::RAW: #if DRIVER_CAN_COMPRESS init.m_internalFormat = GL_COMPRESSED_RGB; #else init.m_internalFormat = GL_RGB; #endif driverShouldGenMipmaps = true; break; #if ANKI_GL == ANKI_GL_DESKTOP case Image::DataCompression::S3TC: init.m_internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; #else case Image::DataCompression::ETC: init.m_internalFormat = GL_COMPRESSED_RGB8_ETC2; break; #endif default: ANKI_ASSERT(0); } } else if(img.getColorFormat() == Image::ColorFormat::RGBA8) { switch(img.getCompression()) { case Image::DataCompression::RAW: #if DRIVER_CAN_COMPRESS init.m_internalFormat = GL_COMPRESSED_RGBA; #else init.m_internalFormat = GL_RGBA; #endif driverShouldGenMipmaps = true; break; #if ANKI_GL == ANKI_GL_DESKTOP case Image::DataCompression::S3TC: init.m_internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; #else case Image::DataCompression::ETC: init.m_internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; #endif default: ANKI_ASSERT(0); } } else { ANKI_ASSERT(0); } // format switch(img.getColorFormat()) { case Image::ColorFormat::RGB8: init.m_format = GL_RGB; break; case Image::ColorFormat::RGBA8: init.m_format = GL_RGBA; break; default: ANKI_ASSERT(0); } // type init.m_type = GL_UNSIGNED_BYTE; // mipmapsCount init.m_mipmapsCount = img.getMipLevelsCount(); // filteringType init.m_filterType = GlTextureHandle::Filter::TRILINEAR; // repeat init.m_repeat = true; // anisotropyLevel init.m_anisotropyLevel = rinit.m_resources.getTextureAnisotropy(); // genMipmaps if(init.m_mipmapsCount == 1 || driverShouldGenMipmaps) { init.m_genMipmaps = true; } else { init.m_genMipmaps = false; } // Now assign the data for(U layer = 0; layer < layers; layer++) { for(U level = 0; level < init.m_mipmapsCount; level++) { GlClientBufferHandle& buff = init.m_data[level][layer]; buff = GlClientBufferHandle( jobs, img.getSurface(level, layer).m_data.size(), (void*)&img.getSurface(level, layer).m_data[0]); } } // Add the GL job to create the texture m_tex = GlTextureHandle(jobs, init); // Add cleanup job jobs.pushBackUserCommand(deleteImageCallback, imgPtr); // Finaly enque the GL job chain jobs.flush(); }
Error MicroSwapchain::initInternal() { const VkDevice dev = m_factory->m_gr->getDevice(); // Get the surface size VkSurfaceCapabilitiesKHR surfaceProperties; U surfaceWidth = 0, surfaceHeight = 0; { ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR( m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &surfaceProperties)); if(surfaceProperties.currentExtent.width == MAX_U32 || surfaceProperties.currentExtent.height == MAX_U32) { ANKI_VK_LOGE("Wrong surface size"); return Error::FUNCTION_FAILED; } surfaceWidth = surfaceProperties.currentExtent.width; surfaceHeight = surfaceProperties.currentExtent.height; } // Get the surface format VkFormat surfaceFormat = VK_FORMAT_END_RANGE; VkColorSpaceKHR colorspace = VK_COLOR_SPACE_MAX_ENUM_KHR; { uint32_t formatCount; ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR( m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &formatCount, nullptr)); DynamicArrayAuto<VkSurfaceFormatKHR> formats(getAllocator()); formats.create(formatCount); ANKI_VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR( m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &formatCount, &formats[0])); while(formatCount--) { if(formats[formatCount].format == VK_FORMAT_B8G8R8A8_UNORM) { surfaceFormat = formats[formatCount].format; colorspace = formats[formatCount].colorSpace; break; } } if(surfaceFormat == VK_FORMAT_UNDEFINED) { ANKI_VK_LOGE("Surface format not found"); return Error::FUNCTION_FAILED; } } // Chose present mode VkPresentModeKHR presentMode = VK_PRESENT_MODE_MAX_ENUM_KHR; { uint32_t presentModeCount; vkGetPhysicalDeviceSurfacePresentModesKHR( m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &presentModeCount, nullptr); presentModeCount = min(presentModeCount, 4u); Array<VkPresentModeKHR, 4> presentModes; vkGetPhysicalDeviceSurfacePresentModesKHR( m_factory->m_gr->getPhysicalDevice(), m_factory->m_gr->getSurface(), &presentModeCount, &presentModes[0]); if(m_factory->m_vsync) { presentMode = VK_PRESENT_MODE_FIFO_KHR; } else { for(U i = 0; i < presentModeCount; ++i) { if(presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { presentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } else if(presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) { presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; break; } } } if(presentMode == VK_PRESENT_MODE_MAX_ENUM_KHR) { ANKI_VK_LOGE("Couldn't find a present mode"); return Error::FUNCTION_FAILED; } } // Create swapchain { VkSwapchainCreateInfoKHR ci = {}; ci.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; ci.surface = m_factory->m_gr->getSurface(); ci.minImageCount = MAX_FRAMES_IN_FLIGHT; ci.imageFormat = surfaceFormat; ci.imageColorSpace = colorspace; ci.imageExtent = surfaceProperties.currentExtent; ci.imageArrayLayers = 1; ci.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; ci.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; ci.queueFamilyIndexCount = 1; U32 idx = m_factory->m_gr->getGraphicsQueueIndex(); ci.pQueueFamilyIndices = &idx; ci.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; ci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; ci.presentMode = presentMode; ci.clipped = false; ci.oldSwapchain = VK_NULL_HANDLE; ANKI_VK_CHECK(vkCreateSwapchainKHR(dev, &ci, nullptr, &m_swapchain)); } // Get images { uint32_t count = 0; ANKI_VK_CHECK(vkGetSwapchainImagesKHR(dev, m_swapchain, &count, nullptr)); if(count != MAX_FRAMES_IN_FLIGHT) { ANKI_VK_LOGE("Requested a swapchain with %u images but got one with %u", MAX_FRAMES_IN_FLIGHT, count); return Error::FUNCTION_FAILED; } ANKI_VK_LOGI("Created a swapchain. Image count: %u, present mode: %u, size: %ux%u, vsync: %u", count, presentMode, surfaceWidth, surfaceHeight, U32(m_factory->m_vsync)); Array<VkImage, MAX_FRAMES_IN_FLIGHT> images; ANKI_VK_CHECK(vkGetSwapchainImagesKHR(dev, m_swapchain, &count, &images[0])); for(U i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { TextureInitInfo init("SwapchainImg"); init.m_width = surfaceWidth; init.m_height = surfaceHeight; init.m_format = Format::B8G8R8A8_UNORM; ANKI_ASSERT(surfaceFormat == VK_FORMAT_B8G8R8A8_UNORM); init.m_usage = TextureUsageBit::IMAGE_COMPUTE_WRITE | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE | TextureUsageBit::PRESENT; init.m_type = TextureType::_2D; TextureImpl* tex = m_factory->m_gr->getAllocator().newInstance<TextureImpl>(m_factory->m_gr, init.getName()); m_textures[i].reset(tex); ANKI_CHECK(tex->initExternal(images[i], init)); } } return Error::NONE; }
//============================================================================== void Material::parseMaterialTag(const XmlElement& materialEl, ResourceInitializer& rinit) { // levelsOfDetail // XmlElement lodEl = materialEl.getChildElementOptional("levelsOfDetail"); if(lodEl) { I tmp = lodEl.getInt(); m_lodsCount = (tmp < 1) ? 1 : tmp; } else { m_lodsCount = 1; } // shadow // XmlElement shadowEl = materialEl.getChildElementOptional("shadow"); if(shadowEl) { m_shadow = shadowEl.getInt(); } // blendFunctions // XmlElement blendFunctionsEl = materialEl.getChildElementOptional("blendFunctions"); if(blendFunctionsEl) { // sFactor m_blendingSfactor = blendToEnum( blendFunctionsEl.getChildElement("sFactor").getText()); // dFactor m_blendingDfactor = blendToEnum( blendFunctionsEl.getChildElement("dFactor").getText()); } else { m_passesCount = 2; } // depthTesting // XmlElement depthTestingEl = materialEl.getChildElementOptional("depthTesting"); if(depthTestingEl) { m_depthTesting = depthTestingEl.getInt(); } // wireframe // XmlElement wireframeEl = materialEl.getChildElementOptional("wireframe"); if(wireframeEl) { m_wireframe = wireframeEl.getInt(); } // shaderProgram // MaterialProgramCreator mspc( materialEl.getChildElement("programs"), rinit.m_tempAlloc); m_tessellation = mspc.hasTessellation(); U tessCount = m_tessellation ? 2 : 1; // Alloc program vector U progCount = 0; progCount += m_passesCount * m_lodsCount * tessCount; if(m_tessellation) { progCount += m_passesCount * m_lodsCount * 2; } progCount += m_passesCount * m_lodsCount; m_progs.resize(progCount); // Aloc progam descriptors m_pplines.resize(m_passesCount * m_lodsCount * tessCount); m_hash = 0; for(U shader = 0; shader < 5; shader++) { if(!m_tessellation && (shader == 1 || shader == 2)) { continue; } if(shader == 3) { continue; } for(U level = 0; level < m_lodsCount; ++level) { for(U pid = 0; pid < m_passesCount; ++pid) { for(U tess = 0; tess < tessCount; ++tess) { TempResourceString src(rinit.m_tempAlloc); src.sprintf("#define LOD %u\n" "#define PASS %u\n" "#define TESSELLATION %u\n", level, pid, tess); TempResourceString filename = createProgramSourceToChache(src); RenderingKey key((Pass)pid, level, tess); ProgramResourcePointer& progr = getProgram(key, shader); progr.load(filename.toCString(), &rinit.m_resources); // Update the hash m_hash ^= computeHash(&src[0], src.getLength()); } } } } populateVariables(mspc); // Get uniform block size ANKI_ASSERT(m_progs.size() > 0); m_shaderBlockSize = m_progs[0]->getGlProgram().findBlock("bDefaultBlock").getSize(); }
//============================================================================== void GlBuffer::create(GLenum target, U32 sizeInBytes, const void* dataPtr, GLbitfield flags) { ANKI_ASSERT(!isCreated()); if(target == GL_UNIFORM_BUFFER) { GLint64 maxBufferSize; glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxBufferSize); if(sizeInBytes > 16384) { ANKI_LOGW("The size (%u) of the uniform buffer is greater " "than the spec's min", sizeInBytes); } else if(sizeInBytes > (PtrSize)maxBufferSize) { ANKI_LOGW("The size (%u) of the uniform buffer is greater " "than the implementation's min (%u)", sizeInBytes, maxBufferSize); } } else if(target == GL_SHADER_STORAGE_BUFFER) { GLint64 maxBufferSize; glGetInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxBufferSize); if(sizeInBytes > pow(2, 24)) { ANKI_LOGW("The size (%u) of the uniform buffer is greater " "than the spec's min", sizeInBytes); } else if(sizeInBytes > (PtrSize)maxBufferSize) { ANKI_LOGW("The size (%u) of the shader storage buffer is greater " "than the implementation's min (%u)", sizeInBytes, maxBufferSize); } } m_target = target; m_size = sizeInBytes; ANKI_ASSERT(m_size > 0 && "Unacceptable size"); // Create glGenBuffers(1, &m_glName); glBindBuffer(m_target, m_glName); glBufferStorage(m_target, m_size, dataPtr, flags); // Map if needed if((flags & GL_MAP_PERSISTENT_BIT) && (flags & GL_MAP_COHERENT_BIT)) { const GLbitfield mapbits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; m_persistentMapping = glMapBufferRange(m_target, 0, sizeInBytes, flags & mapbits); ANKI_ASSERT(m_persistentMapping != nullptr); } }
//============================================================================== void SceneNode::removeComponent(SceneComponent* comp) { ANKI_ASSERT(0 && "TODO"); }
void visit(const TRenderableVariableTemplate& rvar) { typedef typename TRenderableVariableTemplate::Type DataType; const GlProgramVariable& glvar = rvar.getGlProgramVariable(); // Array size U arraySize; if(rvar.isInstanced()) { arraySize = std::min<U>(m_instanceCount, glvar.getArraySize()); } else { arraySize = glvar.getArraySize(); } // Set uniform // Bool hasWorldTrfs = m_renderable->getHasWorldTransforms(); const Mat4& vp = m_fr->getViewProjectionMatrix(); const Mat4& v = m_fr->getViewMatrix(); switch(rvar.getBuildinId()) { case BuildinMaterialVariableId::NO_BUILDIN: uniSet<DataType>(glvar, rvar.begin(), arraySize); break; case BuildinMaterialVariableId::MVP_MATRIX: if(hasWorldTrfs) { Mat4* mvp = m_drawer->m_r->getSceneGraph().getFrameAllocator(). newInstance<Mat4>(arraySize); for(U i = 0; i < arraySize; i++) { Transform worldTrf; m_renderable->getRenderWorldTransform( m_visibleNode->getSpatialIndex(i), worldTrf); mvp[i] = vp * Mat4(worldTrf); } uniSet(glvar, &mvp[0], arraySize); } else { ANKI_ASSERT(arraySize == 1 && "Shouldn't instance that one"); uniSet(glvar, &vp, 1); } break; case BuildinMaterialVariableId::MV_MATRIX: { ANKI_ASSERT(hasWorldTrfs); Mat4* mv = m_drawer->m_r->getSceneGraph().getFrameAllocator(). newInstance<Mat4>(arraySize); for(U i = 0; i < arraySize; i++) { Transform worldTrf; m_renderable->getRenderWorldTransform( m_visibleNode->getSpatialIndex(i), worldTrf); mv[i] = v * Mat4(worldTrf); } uniSet(glvar, &mv[0], arraySize); } break; case BuildinMaterialVariableId::VP_MATRIX: uniSet(glvar, &vp, 1); break; case BuildinMaterialVariableId::NORMAL_MATRIX: if(hasWorldTrfs) { Mat3* normMats = m_drawer->m_r->getSceneGraph().getFrameAllocator(). newInstance<Mat3>(arraySize); for(U i = 0; i < arraySize; i++) { Transform worldTrf; m_renderable->getRenderWorldTransform( m_visibleNode->getSpatialIndex(i), worldTrf); Mat4 mv = v * Mat4(worldTrf); normMats[i] = mv.getRotationPart(); normMats[i].reorthogonalize(); } uniSet(glvar, &normMats[0], arraySize); } else { ANKI_ASSERT(arraySize == 1 && "Having that instanced doesn't make sense"); Mat3 normMat = v.getRotationPart(); uniSet(glvar, &normMat, 1); } break; case BuildinMaterialVariableId::BILLBOARD_MVP_MATRIX: { // Calc the billboard rotation matrix Mat3 rot = m_fr->getViewMatrix().getRotationPart().getTransposed(); Mat4* bmvp = m_drawer->m_r->getSceneGraph().getFrameAllocator(). newInstance<Mat4>(arraySize); for(U i = 0; i < arraySize; i++) { Transform trf; m_renderable->getRenderWorldTransform(i, trf); trf.setRotation(Mat3x4(rot)); bmvp[i] = vp * Mat4(trf); } uniSet(glvar, &bmvp[0], arraySize); } break; case BuildinMaterialVariableId::MAX_TESS_LEVEL: { F32 maxtess = rvar.RenderComponentVariable:: template operator[]<F32>(0); F32 tess = 0.0; if(m_flod >= 1.0) { tess = 1.0; } else { tess = maxtess - m_flod * maxtess; tess = std::max(tess, 1.0f); } uniSet(glvar, &tess, 1); } break; case BuildinMaterialVariableId::BLURRING: { F32 blurring = 0.0; uniSet(glvar, &blurring, 1); } break; case BuildinMaterialVariableId::MS_DEPTH_MAP: { auto unit = glvar.getTextureUnit(); m_drawer->m_r->getMs()._getSmallDepthRt().bind(m_jobs, unit); } break; default: ANKI_ASSERT(0); break; } }
//============================================================================== OctreeNode* Octree::placeInternal(const Aabb& aabb, U depth, OctreeNode& node) { if(depth >= maxDepth) { return &node; } for(U i = 0; i < 2; ++i) { for(U j = 0; j < 2; ++j) { for(U k = 0; k < 2; ++k) { U id = i * 4 + j * 2 + k; // Get the node's AABB. If there is no node then calculate the // AABB Aabb childAabb; Bool child = node.children[id] != nullptr; if(child) { // There is a child childAabb = node.children[id]->aabb; } else { // Calculate calcAabb(i, j, k, node.aabb, childAabb); } // If aabb its completely inside the target => go deeper if(aabb.getMax() <= childAabb.getMax() && aabb.getMin() >= childAabb.getMin()) { if(!child) { #if ANKI_CFG_OCTREE_THREAD_SAFE node.mtx.lock(); // Check again now that the mutex is locked volatile Bool checkAgain = node.children[id] == nullptr; if(checkAgain) #endif { SceneAllocator<U8> alloc = sector->getSectorGroup().getSceneGraph(). getAllocator(); // Create new node if needed OctreeNode* newNode = ANKI_NEW(OctreeNode, alloc, childAabb, &node, alloc); node.addChild(id, newNode); } #if ANKI_CFG_OCTREE_THREAD_SAFE node.mtx.unlock(); #endif } ANKI_ASSERT(node.children[id]); return placeInternal(aabb, depth + 1, *node.children[id]); } } // k } // j } // i return &node; }
Error DescriptorSetLayoutFactory::getOrCreateLayout(const DescriptorSetLayoutInfo& dsinf, VkDescriptorSetLayout& out) { out = VK_NULL_HANDLE; LockGuard<Mutex> lock(m_mtx); auto it = m_map.find(dsinf); if(it != m_map.getEnd()) { out = *it; } else { // Create the layout VkDescriptorSetLayoutCreateInfo ci = {}; ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; const U BINDING_COUNT = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS + MAX_STORAGE_BUFFER_BINDINGS + MAX_IMAGE_BINDINGS; Array<VkDescriptorSetLayoutBinding, BINDING_COUNT> bindings; memset(&bindings[0], 0, sizeof(bindings)); ci.pBindings = &bindings[0]; U count = 0; U bindingIdx = 0; // Combined image samplers for(U i = 0; i < dsinf.m_texCount; ++i) { VkDescriptorSetLayoutBinding& binding = bindings[count++]; binding.binding = bindingIdx++; binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; binding.descriptorCount = 1; binding.stageFlags = VK_SHADER_STAGE_ALL; } // Uniform buffers bindingIdx = MAX_TEXTURE_BINDINGS; for(U i = 0; i < dsinf.m_uniCount; ++i) { VkDescriptorSetLayoutBinding& binding = bindings[count++]; binding.binding = bindingIdx++; binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; binding.descriptorCount = 1; binding.stageFlags = VK_SHADER_STAGE_ALL; } // Storage buffers bindingIdx = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS; for(U i = 0; i < dsinf.m_storageCount; ++i) { VkDescriptorSetLayoutBinding& binding = bindings[count++]; binding.binding = bindingIdx++; binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; binding.descriptorCount = 1; binding.stageFlags = VK_SHADER_STAGE_ALL; } // Images bindingIdx = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS + MAX_STORAGE_BUFFER_BINDINGS; for(U i = 0; i < dsinf.m_imgCount; ++i) { VkDescriptorSetLayoutBinding& binding = bindings[count++]; binding.binding = bindingIdx++; binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; binding.descriptorCount = 1; binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; } ANKI_ASSERT(count <= BINDING_COUNT); ci.bindingCount = count; ANKI_VK_CHECK(vkCreateDescriptorSetLayout(m_dev, &ci, nullptr, &out)); m_map.pushBack(m_alloc, dsinf, out); } return ErrorCode::NONE; }