Basically, CMSIS is a vendor-independent interface for some ARM Cortex chips, while ASF is a restricted library for Atmel (now owned my microchip) devices.
ARM Cortex is the core processor inside microntrollers from multiple vendors. It includes core components like SysTick, NVIC (Interrupt controller), and Micro Trace Buffer (MTB). This core is lisecensed to vendors like Atmel that design microntrollers around it, adding things like memory and peripherals (SERCOM, USB, etc)
The SAMD21 is an Atmel SAM microcontroller designed around an ARM Cortex-M0+ processor. You, as the programmer, have access to features of both.
CMSIS - Cortex Microcontroller Software Interface Standard
This is a hardware-abstraction layer (HAL) for Cortex-M and Cortex-A processors. It works with chips from Atmel, NXP, Freescale, etc. This standard includes low-level interfaces for using core components and lays out a template for creating hardware-dependent (per vendor) libraries as well. The aim is to create an interface which enables code to be portable across numerous chips. In other words, you can reuse the same code between chips from any vendor.
Pros: supports vendor-independent, portable code
Cons: difficult to achieve true vendor-independence, easy to screw up dependencies, tries to do too much and is fairly clunky & convoluted
ASF - Advanced (was Atmel) Software Framework
This is an enormous code library that (should) work with any of Atmel's AVR or ARM microntrollers, as well as development boards like the xplained-pro series. See the link for the supported devices. The point is to provide working code for chip peripherals so developers don't have to redesign the wheel each time, providing a (mostly) similar interface across numerous devices.
Pros: Quicker development, familiar interfaces, lots of starter projects & examples
Cons: Extremely bloated and error prone code, trying too hard to be like Arduino
Since the goal of CMSIS is to be vendor-independent over a few processor lines, but ASF is vendor-dependent but product-independent across multiple processors, the two don't fit together well. Of course, ASF uses CMSIS libs when it needs to, but it doesn't follow the standard. The biggest problem I've had with ASF is that it is overly abstracted, especially for low-resource microcontrollers where you need to know what is going on in the metal.
Creating a new project in Atmel Studio to blink an LED will use an obscene amount of memory space, pulling dozens of header and source files that do trivial operations, stringing them together in an extremely convoluted manner. Because the libraries need to do everything someone might want, they often do a lot of stuff you don't want them to be doing. Keep in mind, much of the code was developed by low-wage and inexperienced interns, and is not polished or efficient. You don't have to spend much time on AVR Freaks to encounter people with insight as to what goes on behind the scenes.
That said, if you want to design your own library, it's useful to look through the ASF example code to see how they initiated peripherals, as it's easy to overlook some step, especially with ARM chips that have multiple clock, generators, and so on. You can then create a platform-abstract layer interface that can, for example, enable and use the serial port on any chip by communicating with the vendor-specific code for a particular chip.
Consider these layers of code:
[ Application Programming Interface (API) ]
[ Vendor-Specific Implementation ]
[ Core Processor Implementation ]
The top layer (API) is what you put in your code. This would be things like
SERIAL_enable(port1, 9600, settings);
SERIAL_send(port1, "Hello, World!");
The middle layer defines those SERIAL functions which likely need to talk to some core processor component which is defined in the bottom layer. If you are following CMSIS, the middle layer can be swapped out for different platforms like the Atmel SAMD21 and NXP LPC810M, as long as each has a serial port. This would typically be done by some Makefile magic, passing a defined architecture parameter during compilation and linking.
Keep in mind, abstraction is a fundamental principal of software development, but can be your biggest enemy when you need to create efficient code on low-resource devices.