| 57 | } |
| 58 | |
| 59 | void Texture2D::commit() |
| 60 | { |
| 61 | texData = getParamObject<Data>("data"); |
| 62 | |
| 63 | if (!texData || texData->numItems.z > 1) { |
| 64 | throw std::runtime_error(toString() |
| 65 | + " must have 2D 'data' array using the first two dimensions."); |
| 66 | } |
| 67 | |
| 68 | if (texData->size() > std::numeric_limits<std::uint32_t>::max()) |
| 69 | throw std::runtime_error(toString() |
| 70 | + " too large (over 4B texels, indexing is limited to 32bit"); |
| 71 | |
| 72 | const vec2i size = vec2i(texData->numItems.x, texData->numItems.y); |
| 73 | if (!texData->compact()) { |
| 74 | postStatusMsg(OSP_LOG_INFO) |
| 75 | << toString() |
| 76 | << " does currently not support strides, copying texture data."; |
| 77 | |
| 78 | auto data = new Data(getISPCDevice(), texData->type, texData->numItems); |
| 79 | data->copy(*texData, vec3ui(0)); |
| 80 | texData = data; |
| 81 | data->refDec(); |
| 82 | } |
| 83 | |
| 84 | format = static_cast<OSPTextureFormat>( |
| 85 | getParam<uint32_t>("format", OSP_TEXTURE_FORMAT_INVALID)); |
| 86 | filter = static_cast<OSPTextureFilter>( |
| 87 | getParam<uint32_t>("filter", OSP_TEXTURE_FILTER_LINEAR)); |
| 88 | wrapMode = getParam<vec2ui>("wrapMode", |
| 89 | vec2ui(getParam<uint32_t>("wrapMode", OSP_TEXTURE_WRAP_REPEAT))); |
| 90 | |
| 91 | if (format == OSP_TEXTURE_FORMAT_INVALID) |
| 92 | throw std::runtime_error(toString() + ": invalid 'format'"); |
| 93 | |
| 94 | if (sizeOf(format) != sizeOf(texData->type)) |
| 95 | throw std::runtime_error(toString() + ": 'format'='" + stringFor(format) |
| 96 | + "' does not match type of 'data'='" + stringFor(texData->type) |
| 97 | + "'!"); |
| 98 | |
| 99 | std::vector<void *> dataPtr; |
| 100 | dataPtr.push_back(texData->data()); |
| 101 | |
| 102 | if (getISPCDevice().disableMipMapGeneration) |
| 103 | mipMapData = nullptr; |
| 104 | else { |
| 105 | // Check if MIP maps were generated already |
| 106 | bool generateMipMaps = false; |
| 107 | MipMapCache &mmc = getISPCDevice().getMipMapCache(); |
| 108 | mipMapData = mmc.find(texData->data()); |
| 109 | if (!mipMapData) { |
| 110 | // conservatively estimate needed space for MIP maps and allocate |
| 111 | const auto maxMipTexels = (size.product() + 2) / 3 // for square textures |
| 112 | + (size.x + size.y - 1) |
| 113 | / std::min(size.x, size.y); // remaining 1D case |
| 114 | mipMapData = std::make_shared<devicert::BufferShared<char>>( |
| 115 | getISPCDevice().getDRTDevice(), maxMipTexels * sizeOf(format)); |
| 116 | |